Добавить в корзинуПозвонить
Найти в Дзене
IT Start | Python

Крестики-нолики с графическим интерфейсом на Python

Введение В данной статье напишем код игры крестики-нолики с графическим интерфейсом на Python с использованием библиотеки tkinter. Т.к. tkinter входит в стандартную библиотеку Python — устанавливать его не придётся. Создание корневого окна Для написания кода нам понадобится импортировать tkinter и messagebox из tkinter. import tkinter as tk
from tkinter import messagebox Теперь создадим корневое окно и сразу вызовем метод mainloop() (главный цикл обработки событий). import tkinter as tk
from tkinter import messagebox root = tk.Tk()
root.mainloop() Создание класса TicTacToe и инициализация атрибутов Перейдём к созданию класса, в котором будет написана вся логика игры. Создадим класс TicTacToe и инициализируем все необходимые атрибуты: import tkinter as tk
from tkinter import messagebox class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна self.current_player = "X" # Установка
Оглавление

Введение

В данной статье напишем код игры крестики-нолики с графическим интерфейсом на Python с использованием библиотеки tkinter.

Т.к. tkinter входит в стандартную библиотеку Python — устанавливать его не придётся.

Создание корневого окна

Для написания кода нам понадобится импортировать tkinter и messagebox из tkinter.

import tkinter as tk
from tkinter import messagebox

Теперь создадим корневое окно и сразу вызовем метод mainloop() (главный цикл обработки событий).

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()
root.mainloop()

Создание класса TicTacToe и инициализация атрибутов

Перейдём к созданию класса, в котором будет написана вся логика игры. Создадим класс TicTacToe и инициализируем все необходимые атрибуты:

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля

root = tk.Tk()
root.mainloop()

Также при помощи цикла создадим игровое поле в виде кнопок:

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля
for i in range(3):
row = [] # Создание списка для хранения кнопок в строке
for j in range(3):
# Создание кнопки и привязка метода on_button_click к событию нажатия
button = tk.Button(self.master, text=" ", font=("Arial", 20), width=5, height=2,
command=lambda i=i, j=j: self.on_button_click(i, j))
button.grid(row=i, column=j, sticky="nsew") # Размещение кнопки на сетке
row.append(button) # Добавление кнопки в строку
self.buttons.append(row) # Добавление строки кнопок в общий список

self.reset_button = tk.Button(self.master, text="Новая игра", command=self.reset_game) # Создание кнопки для сброса игры
self.reset_button.grid(row=3, column=0, columnspan=3, sticky="nsew") # Размещение кнопки на сетке

root = tk.Tk()
root.mainloop()

Создание метода on_button_click()

Мы можем заметить, что в цикле во время создания кнопки идёт привязка к методу on_button_click(). Данный метод будет предназначен для того, чтобы заполнить игровую клетку определённым символом (крестиком или ноликом). Также при достижении победы одним из игроков данный метод отобразит всплывающее окно, оповещающее о победе одного из игроков или ничьей. Создадим данный метод:

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля
for i in range(3):
row = [] # Создание списка для хранения кнопок в строке
for j in range(3):
# Создание кнопки и привязка метода on_button_click к событию нажатия
button = tk.Button(self.master, text=" ", font=("Arial", 20), width=5, height=2,
command=lambda i=i, j=j: self.on_button_click(i, j))
button.grid(row=i, column=j, sticky="nsew") # Размещение кнопки на сетке
row.append(button) # Добавление кнопки в строку
self.buttons.append(row) # Добавление строки кнопок в общий список

self.reset_button = tk.Button(self.master, text="Новая игра", command=self.reset_game) # Создание кнопки для сброса игры
self.reset_button.grid(row=3, column=0, columnspan=3, sticky="nsew") # Размещение кнопки на сетке

def on_button_click(self, i, j):
if self.board[i * 3 + j] == " ": # Проверка, что клетка пуста
self.board[i * 3 + j] = self.current_player # Установка символа текущего игрока в клетку
self.buttons[i][j].config(text=self.current_player) # Обновление текста на кнопке
if self.check_winner(i, j): # Проверка на победу
messagebox.showinfo("Победа", f"Игрок {self.current_player} выиграл!") # Отображение сообщения о победе
self.reset_game() # Сброс игры
elif " " not in self.board: # Проверка на ничью
messagebox.showinfo("Ничья", "Ничья!") # Отображение сообщения о ничьей
self.reset_game() # Сброс игры
else:
self.current_player = "O" if self.current_player == "X" else "X" # Смена игрока

root = tk.Tk()
root.mainloop()

Создание метода check_winner()

Теперь мы можем заметить, что в методе on_button_click() присутствует вызов метода check_winner(). Данный метод, который мы сейчас напишем предназначен для проверки, победил ли на данный момент кто-то из игроков, или нет.

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля
for i in range(3):
row = [] # Создание списка для хранения кнопок в строке
for j in range(3):
# Создание кнопки и привязка метода on_button_click к событию нажатия
button = tk.Button(self.master, text=" ", font=("Arial", 20), width=5, height=2,
command=lambda i=i, j=j: self.on_button_click(i, j))
button.grid(row=i, column=j, sticky="nsew") # Размещение кнопки на сетке
row.append(button) # Добавление кнопки в строку
self.buttons.append(row) # Добавление строки кнопок в общий список

self.reset_button = tk.Button(self.master, text="Новая игра", command=self.reset_game) # Создание кнопки для сброса игры
self.reset_button.grid(row=3, column=0, columnspan=3, sticky="nsew") # Размещение кнопки на сетке

def on_button_click(self, i, j):
if self.board[i * 3 + j] == " ": # Проверка, что клетка пуста
self.board[i * 3 + j] = self.current_player # Установка символа текущего игрока в клетку
self.buttons[i][j].config(text=self.current_player) # Обновление текста на кнопке
if self.check_winner(i, j): # Проверка на победу
messagebox.showinfo("Победа", f"Игрок {self.current_player} выиграл!") # Отображение сообщения о победе
self.reset_game() # Сброс игры
elif " " not in self.board: # Проверка на ничью
messagebox.showinfo("Ничья", "Ничья!") # Отображение сообщения о ничьей
self.reset_game() # Сброс игры
else:
self.current_player = "O" if self.current_player == "X" else "X" # Смена игрока

def check_winner(self, i, j):
row = all(self.board[i*3 + col] == self.current_player for col in range(3)) # Проверка по горизонтали
col = all(self.board[row*3 + j] == self.current_player for row in range(3)) # Проверка по вертикали
diag1 = all(self.board[i*3 + i] == self.current_player for i in range(3)) # Проверка по диагонали
diag2 = all(self.board[i*3 + 2-i] == self.current_player for i in range(3)) # Проверка по диагонали
return any([row, col, diag1, diag2]) # Возвращает True, если есть победа

root = tk.Tk()
root.mainloop()

Создание метода check_winner()

Последний метод который мы создадим — это check_winner(), который также неоднократно вызывается и в других методах. Он предназначен для начала игры с нуля. Т.е. благодаря нему поле будет очищаться, также будет установлен начальный игрок в виде крестика.

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля
for i in range(3):
row = [] # Создание списка для хранения кнопок в строке
for j in range(3):
# Создание кнопки и привязка метода on_button_click к событию нажатия
button = tk.Button(self.master, text=" ", font=("Arial", 20), width=5, height=2,
command=lambda i=i, j=j: self.on_button_click(i, j))
button.grid(row=i, column=j, sticky="nsew") # Размещение кнопки на сетке
row.append(button) # Добавление кнопки в строку
self.buttons.append(row) # Добавление строки кнопок в общий список

self.reset_button = tk.Button(self.master, text="Новая игра", command=self.reset_game) # Создание кнопки для сброса игры
self.reset_button.grid(row=3, column=0, columnspan=3, sticky="nsew") # Размещение кнопки на сетке

def on_button_click(self, i, j):
if self.board[i * 3 + j] == " ": # Проверка, что клетка пуста
self.board[i * 3 + j] = self.current_player # Установка символа текущего игрока в клетку
self.buttons[i][j].config(text=self.current_player) # Обновление текста на кнопке
if self.check_winner(i, j): # Проверка на победу
messagebox.showinfo("Победа", f"Игрок {self.current_player} выиграл!") # Отображение сообщения о победе
self.reset_game() # Сброс игры
elif " " not in self.board: # Проверка на ничью
messagebox.showinfo("Ничья", "Ничья!") # Отображение сообщения о ничьей
self.reset_game() # Сброс игры
else:
self.current_player = "O" if self.current_player == "X" else "X" # Смена игрока

def check_winner(self, i, j):
row = all(self.board[i*3 + col] == self.current_player for col in range(3)) # Проверка по горизонтали
col = all(self.board[row*3 + j] == self.current_player for row in range(3)) # Проверка по вертикали
diag1 = all(self.board[i*3 + i] == self.current_player for i in range(3)) # Проверка по диагонали
diag2 = all(self.board[i*3 + 2-i] == self.current_player for i in range(3)) # Проверка по диагонали
return any([row, col, diag1, diag2]) # Возвращает True, если есть победа

def reset_game(self):
self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Очистка игрового поля
for i in range(3):
for j in range(3):
self.buttons[i][j].config(text=" ") # Очистка текста на кнопках

root = tk.Tk()
root.mainloop()

Проверка работы кода

Осталось создать экземпляр нашего класса TicTacToe и передать в него root.

import tkinter as tk
from tkinter import messagebox

class TicTacToe:
def __init__(self, master):
self.master = master # Определение корневого окна
self.master.title("Крестики-нолики") # Установка заголовка окна

self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Создание пустого игрового поля

self.buttons = [] # Создание списка для хранения кнопок игрового поля
for i in range(3):
row = [] # Создание списка для хранения кнопок в строке
for j in range(3):
# Создание кнопки и привязка метода on_button_click к событию нажатия
button = tk.Button(self.master, text=" ", font=("Arial", 20), width=5, height=2,
command=lambda i=i, j=j: self.on_button_click(i, j))
button.grid(row=i, column=j, sticky="nsew") # Размещение кнопки на сетке
row.append(button) # Добавление кнопки в строку
self.buttons.append(row) # Добавление строки кнопок в общий список

self.reset_button = tk.Button(self.master, text="Новая игра", command=self.reset_game) # Создание кнопки для сброса игры
self.reset_button.grid(row=3, column=0, columnspan=3, sticky="nsew") # Размещение кнопки на сетке

def on_button_click(self, i, j):
if self.board[i * 3 + j] == " ": # Проверка, что клетка пуста
self.board[i * 3 + j] = self.current_player # Установка символа текущего игрока в клетку
self.buttons[i][j].config(text=self.current_player) # Обновление текста на кнопке
if self.check_winner(i, j): # Проверка на победу
messagebox.showinfo("Победа", f"Игрок {self.current_player} выиграл!") # Отображение сообщения о победе
self.reset_game() # Сброс игры
elif " " not in self.board: # Проверка на ничью
messagebox.showinfo("Ничья", "Ничья!") # Отображение сообщения о ничьей
self.reset_game() # Сброс игры
else:
self.current_player = "O" if self.current_player == "X" else "X" # Смена игрока

def check_winner(self, i, j):
row = all(self.board[i*3 + col] == self.current_player for col in range(3)) # Проверка по горизонтали
col = all(self.board[row*3 + j] == self.current_player for row in range(3)) # Проверка по вертикали
diag1 = all(self.board[i*3 + i] == self.current_player for i in range(3)) # Проверка по диагонали
diag2 = all(self.board[i*3 + 2-i] == self.current_player for i in range(3)) # Проверка по диагонали
return any([row, col, diag1, diag2]) # Возвращает True, если есть победа

def reset_game(self):
self.current_player = "X" # Установка начального игрока
self.board = [" " for _ in range(9)] # Очистка игрового поля
for i in range(3):
for j in range(3):
self.buttons[i][j].config(text=" ") # Очистка текста на кнопках

root = tk.Tk()
game = TicTacToe(root)
root.mainloop()

Пример игры:

     Крестики-нолики с графическим интерфейсом на Python Admin
Крестики-нолики с графическим интерфейсом на Python Admin

Консольная игра «Крестики-нолики на Pytho

Курс по созданию GUI на Python tkinter

Заключение

В ходе статьи мы с Вами написали код игры «Крестики-нолики» с графическим интерфейсом на Python используя библиотеку tkinter. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂

Мой Telegram канал

Мой YouTube канал

Курс по Python (50 видоуроков + дополнительные уроки)

Курс по созданию телеграм-ботов на Python с фреймворком Aiogram