Jocul de X și 0 - TicTacToe - în Python și PySide - partea I
python pyside tic-tac-toe x-si-0
Acum ceva timp m-am hotărât să codez jocul de "x și 0" în Python folosind ca bibliotecă grafică PySide. Ideea a fost să mă familiarizez mai bine cu PySide și - în plus - să-mi îmbunătățesc Python-ul (și să răspund unei provocări mai vechi a unui prieten).
Jocul de "x și 0" este destul de simplu dar nu e chiar atât de ușor de codat pe cât e de jucat, mai ales dacă nu esti un programator de meserie. Probabil că partea cea mai importantă este cea premergătoare implementării în cod propriu-zise: si anume partea de proiectare. Iei creion și hârtie și încerci să schițezi cum ar trebui să decurgă jocul dar și variabilele (și tipul lor) de care ai nevoie (un fel de scriere în pseudocod). Dacă te apuci să codezi înainte de a înțelege lucrurile astea codul merge foarte greu pentru că nu ai o vedere de ansamblu a ceea ce trebuie să faci. De mare importanță (am realizat mai târziu, deși cred că citisem undeva asta) este stabilirea încă de la început a variabilelor globale și a tipului lor.
Pentru început m-am gândit că variabilele de care aș avea nevoie ar fi: mutariom - de tipul listă (list), mutaricalc - tot listă și mutariramase - o listă cu toare mutările posibile (9 în "x și 0") din care o să îndepărtez fiecare mutare efectuată. Cam așa arată variabilele:
self.mutariom = [] self.mutariramase = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] self.mutaricalc = []
mutariramase este o listă de tupluri care indică rândul și coloana unei celule într-un tabel - fiindcă pentru reprezentarea grafică a jocului m-am hotărât să folosesc un widget din PySide de tip tabel: QTableWidget
. Nu știu dacă e cea mai bună alegere, dar până la urmă mi s-a părut suficientă.
Apoi a trebuit sa adaug o altă variabilă - o listă cu toate celulele/elementele tabelului:
self.items = [self.tabel.item(0, 0), self.tabel.item(0, 1), self.tabel.item(0, 2), self.tabel.item(1, 0), self.tabel.item(1, 1), self.tabel.item(1, 2), self.tabel.item(2, 0), self.tabel.item(2, 1), self.tabel.item(2, 2)]
În X și 0 sunt câteva capcane sau încolțiri, pentru a le evita am creat o nouă variabilă - un dicționar - în care cheia (key) este un tuplu format din două tupluri (care reprezintă încolțirea) iar valoarea (value) un tuplu (care reprezintă mutarea calculatorului pentru a evita încolțirea):
self.incoltiri = {((0, 1), (1, 2)):(0, 2), ((1, 2), (0, 1)):(0, 2), ((1, 2), (2, 1)):(2, 2), ((2, 1), (1, 2)):(2, 2), ((2, 1), (1, 0)):(2, 0), ((1, 0), (2, 1)):(2, 0), ((1, 0), (0, 1)):(0, 0), ((0, 1), (1, 0)):(0, 0), ((0, 2), (2, 1)):(2, 2), ((2, 1), (0, 2)):(2, 2), ((2, 1), (0, 0)):(2, 0), ((0, 0), (2, 1)):(2, 0), ((1, 0), (0, 2)):(0, 0), ((0, 2), (1, 0)):(0, 0), ((0, 1), (2, 2)):(0, 2), ((2, 2), (0, 1)):(0, 2), ((1, 2), (2, 0)):(2, 2), ((2, 0), (1, 2)):(2, 2), ((2, 2), (1, 0)):(2, 0), ((1, 0), (2, 2)):(2, 0), ((2, 0), (0, 1)):(0, 0), ((0, 1), (2, 0)):(0, 0), ((0, 0), (1, 2)):(0, 2), ((1, 2), (0, 0)):(0, 2)}
Am mai adăugat trei variabile - de tip listă - cu câmpurile din colțuri, din mijlocuri și cu variantele de câștig:
self.colturi = [(0,0), (0, 2), (2,0), (2, 2)] self.mijlocuri = [(0,1), (1, 2), (2, 1), (1,0)] self.varianteWin = [ [(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1), (1, 2)], [(2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)], [(0, 0), (1, 1), (2, 2)], [(2, 0), (1, 1), (0, 2)] ]
Am fost nevoit să folosesc tupluri (care să conțină coordonatele celulelor) pentru că acestea sunt imuabile (adică elementele lor nu-și modifică ordinea așa cum se întâmplâ într-o listă).
Pentru comoditate am redenumit numele fiecărei celule (i-am dat un nume mai scurt), deși nu era necesar:
self.unu = self.tabel.item(0, 0) self.doi = self.tabel.item(0, 1) self.trei = self.tabel.item(0, 2) self.patru = self.tabel.item(1, 0) self.cinci = self.tabel.item(1, 1) self.sase = self.tabel.item(1, 2) self.sapte = self.tabel.item(2, 0) self.opt = self.tabel.item(2, 1) self.noua = self.tabel.item(2, 2)
Acestea sunt toate variabilele globale pe care le-am folosit. În postarea/postările următoare o să prezint partea de grafică și partea de AI (de fapt funcția care stabilește ce mută calculatorul, în funcție de mutările omului).
Pentru cei care nu au răbdare am făcut un cont pe GitHub și am încărcat jocul acolo, așadar îl puteți descărca de aici. Pentru a-l rula trebuie să aveți python 2.7+ și PySide instalat (un ghid de instalare a bibiliotecii PySide în Windows îl găsiți pe sait, aici. Dacă folosiți Windows trebuie să faceți o mică modificare ca butonul de restart (al jocului) să funcționeze - linia de cod:
subprocess.call("python" + " TicTacToe.py", shell=True)
din funcția restartJoc
trebuie modificată astfel
subprocess.call("python" + " /Calea/catre/fisierul/TicTacToe.py", shell=True)
Nu uitați spațiul liber din fața căii către fișier (imediat după ghilimelele ce urmează după plus).
Pe data viitoare și (ro)cod cu spor!