Tic tac toe, czy też kółko i krzyżyk, to jedna z najpopularniejszych gier na świecie, oraz doskonaly projekt dla początkujących programistów. Poniżej zobaczymy jeden z sposobów w jaki możemy tą grę napisać i wykorzystamy do tego prostą bibliotekę Python Turtle.
Import biblioteki Python Turtle oraz podstawowe ustawienia
Standardowo importujemy bibliotekę Turtle. Dodatkowo random oraz time. Przydadzą się później.
Tworzymy planszę gry o wymiarach 600 x 600. Rozmiar możemy ustawić za pomocą funkcji window.setup(). Współżędne lewego, górnego rogu to (-300, 300). Przyda się to nam potem. Do tego tworzymy naszego żółwia o ksywce 'xo’, który będzie odpowiadać za rysowanie linii, Xów oraz O.
import turtle import random import time window = turtle.Screen() BOK = 600 X = -300 Y = 300 window.setup(BOK,BOK) window.title('Kółko i krzyżyk') window.bgcolor('black') xo = turtle.Turtle() xo.color('white') xo.speed(0) xo.pensize(7) xo.hideturtle()
Najważniejsze zmienne
Cała tablica do gry w tic, tac, toe, składa się z 9 pól. 3 na 3.
Potrzebujemy zmiennej która będzie przechować informację czy i gdzie są postawione X oraz O. Możemy wykorzystać do tego prostą listę 3-elementową. Każdy jej element odpowiada za wiersz, i jest również listą 3 elementową. W ten sposób mamy możliwość przechowania 9 elementów.
tablica = [[None,None,None], [None,None,None], [None,None,None]] kolej = random.choice(['x','o'])
Jeżeli użytkownik kliknie w powiedzmy, w pole po lewej na dole, to będziemy mogli odwołać się do tablicy poprzez tablica [ 2 ] [ 0 ]. Ale to zobaczymy za chwilę.
następną zmienną którą potrzebujemy to 'kolej’. Zmienna kolej będzie przechowywać informację czyja jest kolej. Czy X czy O. Na początku jest losowana ta informacja, dlatego potrzebowaliśmy zaimportować bibliotekę random na początku programu.
Rysujemy siatkę do gry
Linie rysujemy w odstępie 1/3 szerokości. Zarówno w pionie jak i w poziomie. Tutaj przydają się X oraz Y zdefiniowane na początku. Pierwsza linia pionowa jest w odległości 1/3 długości boku oraz X. itd.
ODSTĘP = int(BOK / 3) for a in [1,2]: # linie w pionie xo.penup() xo.goto(X + a*ODSTĘP, Y) xo.pendown() xo.goto(X + a*ODSTĘP, -Y) # linie w poziomie xo.penup() xo.goto(X, Y -a*ODSTĘP) xo.pendown() xo.goto(-X, Y -a*ODSTĘP)
W rezultacie otrzymujemy piękną siatkę i 9 pól.
Obsługa zdarzenia kliknięcia myszki
Na naszej siatce, będą pojawiać się X oraz O, w zależności od tego gdzie klieknie gracz. Należy poinformować Turtle, że po kliknięciu w planszę ma podjąć akcję.
window.onclick(click) window.listen() window.mainloop()
Następnie będziemy musieli utworzyć funkcję click()
Rysowanie X lub O
Funkcja click, ma całkiem sporo do zrobienia:
- Musi stwierdzić które pole klikną gracz. nie chodzi tylko o x i y, gdyż to zostanie jej przekazane przez parametry, ale o to które z 9 pól to jest.
- Następnie musi sprawdzić w zmiennej tablica czy to pole jest puste. Jeżeli jest tam już x albo o, to należy zignorować kliknięcie myszy
- Jeżeli pole jest puste, to należy narysować tam X lub O. W zależności czyja jest kolej
- Musimy dodać informację do zmiennej tablica, o nowym X lub O
- A następnie sprawdzić czy X lub O wygrywa. Jednak, do tego celu napiszemy osobną funkcję – sprawdź()
- Jeżeli mamy zwycięzce, to wstrzymujemy program na 1 sekundę, a następnie piszemy na środku ekranu, kto wygrał
def click(x,y): global kolej # które pole klikną gracz kolumna = 0 wiersz = 0 if x < X + ODSTĘP: kolumna = 0 elif x > X + 2*ODSTĘP: kolumna = 2 else: kolumna = 1 if y < Y - 2*ODSTĘP: wiersz = 2 elif y > Y - ODSTĘP: wiersz =0 else: wiersz = 1 # Czy pole, które klikną gracz, jest puste ? if tablica[wiersz][kolumna] != None: return # narysować X lub O, w zależności czyja jest kolej kolumna_środek = (kolumna*ODSTĘP + ODSTĘP/2) - BOK/2 wiersz_środek = (-wiersz*ODSTĘP - ODSTĘP/2) + BOK/2 xo.penup() xo.goto(kolumna_środek-25, wiersz_środek-25) if kolej == 'x': xo.write('X', font=('Arial',50)) else: xo.write('O', font=('Arial',50)) # dodać informację x / o do tablicy tablica[wiersz][kolumna] = kolej if kolej == 'o': kolej = 'x' else: kolej = 'o' # sprawdzić czy x lub o wygrywają if sprawdz() != None: xo.penup() xo.goto(-150,0) time.sleep(1) xo.clear() xo.write(" Wygrały " + sprawdz(), font=("Arial",50))
Sprawdzanie czy X lub O wygrały
Funkcja sprawdź(), jest wykorzystywa przez funkcję click() i wywolywana po pojawieniu sie nowego X oraz O. Jej zadaniem jest sprawdzenie czy mamy zwyciężcę, a jeżeli tak, to zwrócenie informacji czy jest to X czy O. Gracz wygrywa, w momencie w którym X lub O:
- Zajmują całą kolumnę
- Zajmują cały wiersz
- Zajmują 3 pola po skosie
Jeżeli funkcja stwierdzi że ma takie same wartości, X lub O, to zwraca tą wartość.
def sprawdz(): # po skosie if tablica[0][0] == tablica[1][1] == tablica[2][2]: return tablica[2][2] if tablica[0][2] == tablica[1][1] == tablica[2][0]: return tablica[2][0] # w wierszu for w in range(3): if tablica[w][0] == tablica[w][1] == tablica[w][2]: return tablica[w][0] # w kolumnie for k in range(2): if tablica[0][k] == tablica[1][k] == tablica[2][k]: return tablica[0][k] return None
Podsumowując
Python Turtle, poradził sobie z prostą grafiką, jaka była potrzebna do gry tic tac toe, jednak nie jest to biblioteka, która jest zoptymalizowana pod gry. W kolejnych artykułach, będziemy pokazywać bardziej złożone gry takie jak pac man czy tetris i tym razem sięgniemy po bibliotekę pygame. Działa ona bardzo podobnie do Python Turtle, tak więc zmiana będzie bardzo prosta, natomiast przy bardziej rozbudowanych grach, spisze się lepiej.
Do Python Trutle, będziemy wracać, gdyż jest to bardzo dobra biblioteka aby uczyć się Python oraz wizualizować różne ciekawe koncepcje, jak na przykład funkcje rekurencyjne.
Python Turtle
- Wstęp do Python Turtle
- Wyścig żółwi – prosta gra z Python Turtle
- Obsługa zdarzeń w Python Turtle
- Tic Tac Toe, czyli kółko i krzyżyk z Python Turtle <– Jesteś tutaj
Całość kodu
import turtle import random import time window = turtle.Screen() BOK = 600 X = -300 Y = 300 window.setup(BOK,BOK) window.title('Kółko i krzyżyk') window.bgcolor('black') xo = turtle.Turtle() xo.color('white') xo.speed(0) xo.pensize(7) xo.hideturtle() tablica = [[None,None,None], [None,None,None], [None,None,None]] kolej = random.choice(['x','o']) # linie ODSTĘP = int(BOK / 3) for a in [1,2]: xo.penup() xo.goto(X + a*ODSTĘP, Y) xo.pendown() xo.goto(X + a*ODSTĘP, -Y) xo.penup() xo.goto(X, Y -a*ODSTĘP) xo.pendown() xo.goto(-X, Y -a*ODSTĘP) def sprawdz(): # po skosie if tablica[0][0] == tablica[1][1] == tablica[2][2]: return tablica[2][2] if tablica[0][2] == tablica[1][1] == tablica[2][0]: return tablica[2][0] # w wierszu for w in range(3): if tablica[w][0] == tablica[w][1] == tablica[w][2]: return tablica[w][0] # w kolumnie for k in range(2): if tablica[0][k] == tablica[1][k] == tablica[2][k]: return tablica[0][k] return None def click(x,y): global kolej # które to pole kolumna = 0 wiersz = 0 if x < X + ODSTĘP: kolumna = 0 elif x > X + 2*ODSTĘP: kolumna = 2 else: kolumna = 1 if y < Y - 2*ODSTĘP: wiersz = 2 elif y > Y - ODSTĘP: wiersz =0 else: wiersz = 1 # pole jest puste ? if tablica[wiersz][kolumna] != None: return # narysować kolumna_środek = (kolumna*ODSTĘP + ODSTĘP/2) - BOK/2 wiersz_środek = (-wiersz*ODSTĘP - ODSTĘP/2) + BOK/2 xo.penup() xo.goto(kolumna_środek-25, wiersz_środek-25) if kolej == 'x': xo.write('X', font=('Arial',50)) else: xo.write('O', font=('Arial',50)) # dodać informację x / o tablica[wiersz][kolumna] = kolej if kolej == 'o': kolej = 'x' else: kolej = 'o' # sprawdź if sprawdz() != None: xo.penup() xo.goto(-150,0) time.sleep(1) xo.clear() xo.write(" Wygrały " + sprawdz(), font=("Arial",50)) window.onclick(click) window.listen() window.mainloop()