Крестики-нолики — логическая игра между двумя противниками на квадратном поле 3 на 3 клетки. Напишем программу игры крестики-нолики на Python с библиотекой tkinter и с применением Объектно Ориентированного программирования ООП.
Создадим поле из 9 клеток с кнопками класса Button для игры крестики-нолики.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Button(f, width=3, height=2, font=('times', 24, 'italic bold')
).pack(expand=YES, fill=BOTH, side=LEFT)
mainloop() # Главный цикл программы
Лист. 1. Программа, генерирующая игровое поле для крестиков-ноликов.
Рис. 1. Игровое поле, созданное программой листинг 1.
Чтобы у нас была возможность менять текст заголовка окна пронграммы, см. Рис. 1, мы должны в нашей программе явно создать главное окно программы с помощью конструктора Tk().
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Button(f, width=3, height=2, font=('times', 24, 'italic bold')
).pack(expand=YES, fill=BOTH, side=LEFT)
mainloop() # Главный цикл программы
Лист. 2. В программу добавлено создание окна программы с заголовком 'tic-tac-toe'.
Рис. 2. Окно программы с заголовком 'tic-tac-toe'.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
pass # наследник класса Button
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold')
).pack(expand=YES, fill=BOTH, side=LEFT)
mainloop() # Главный цикл программы
Лист. 3. В программе создан класс Btn на основе классса Button из библиотеки tkinter.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 4. В класс Btn добавлен метод (конструктор) __init__ с возможностью передачи аргументов в конструктор суперкласса Button.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
def play(self): # Функция игры
self.config(text='X') # Ход крестиков
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 5. В класс Btn добавлен метод play с возможностью размещения буквы 'X' на кнопке, по которой кликнул игрок.
Рис. 3. Игра крестики - нолики, созданная программой листинг 5.
В программе листинг 5, кнопка (объект) по которой кликнул игрок имеет имя self. Имена соседних кнопок в программе листинг 5 не определены. Для того, чтобы сделать ход ноликом, необходимо присвоить имя каждой кнопке на игровом поле.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
self.config(text='X') # Ход крестиков
for i in range(9):
Btn.btn_all[i].config(text=Btn.btn_all[i].num)
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 6. Все кнопки на игровом поле сгруппированы в список Btn.btn_all.
Рис. 4. Игровое поле создано программой листинг 6.
Функция (метод) Btn.play в программе листинг 6 демонстрирует возможностьизменения свойств любой кнопки на игровом поле.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
self.config(text='X') # Ход крестиков
for i in range(9):
if Btn.btn_all[i].cget('text') == '':
Btn.btn_all[i].config(text='O')
break
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 7. В метод Btn.play добавлен после хода крестика, ход нолика в первую найденную свободную клетку на игровом поле.
Рис. 5. Игра с компьютером.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.config(text='X') # Ход крестиков
Btn.playground[self.num] = 1 # Ход крестиков на виртуальном поле
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
Btn.btn_all[i].config(text='O') # Ход ноликов
Btn.playground[i] = -1 # Ход ноликов на виртуальном поле
break # Прервать поиск клетки
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 8.
Рис. 6.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.config(text='X') # Ход крестиков
Btn.playground[self.num] = 1 # Ход крестиков на виртуальном поле
if self.win(Btn.playground): # Если победа
tk.title('Win X') # Победили крестики
return
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
Btn.btn_all[i].config(text='O') # Ход ноликов
Btn.playground[i] = -1 # Ход ноликов на виртуальном поле
break # Прервать поиск клетки
def win(self, pg): # Если победа, return True
if pg[0] + pg[4] + pg[8] in (3, -3):
return True
return False
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 9.
Рис. 7.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.game_over: return # Если конец игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.config(text='X') # Ход крестиков
Btn.playground[self.num] = 1 # Ход крестиков на виртуальном поле
if self.win(Btn.playground): # Если победа
tk.title('Win X') # Победили крестики
Btn.game_over = True
return
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
Btn.btn_all[i].config(text='O') # Ход ноликов
Btn.playground[i] = -1 # Ход ноликов на виртуальном поле
break # Прервать поиск клетки
def win(self, pg): # Если победа, return True
if pg[0] + pg[4] + pg[8] in (3, -3):
return True
return False
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 10.
Рис. 8.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.game_over: return # Если конец игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.config(text='X') # Ход крестиков
Btn.playground[self.num] = 1 # Ход крестиков на виртуальном поле
if self.win(Btn.playground): # Если победа
tk.title('Win X') # Победили крестики
Btn.game_over = True
return
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
Btn.btn_all[i].config(text='O') # Ход ноликов
Btn.playground[i] = -1 # Ход ноликов на виртуальном поле
break # Прервать поиск клетки
if self.win(Btn.playground): # Если победа
tk.title('Win O') # Победили нолики
Btn.game_over = True
def win(self, pg): # Если победа, return True
if pg[0] + pg[1] + pg[2] in (3, -3):
return True
return False
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 11.
Рис. 9.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
self.move(i, -1) # Ход ноликов
break # Прервать поиск клетки
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
def win(self, pg): # Если победа, return True
if pg[0] + pg[1] + pg[2] in (3, -3):
return True
return False
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 12.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
for i in range(9): # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
self.move(i, -1) # Ход ноликов
break # Прервать поиск клетки
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 13.
Рис. 10.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
self.move(i, -1) # Ход ноликов
break # Прервать поиск клетки
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 14.
Рис. 11.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for i in range(9): # Если есть возможность победить
pg = Btn.playground.copy()
pg[i] = -1 if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 15.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 16.
Рис.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
if Btn.playground[2] == 1 and Btn.playground[6] == 1:
best = (1, 4, 8, 2, 6, 0, 7, 3, 5)
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 17.
Рис.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
if Btn.playground[2] == 1 and Btn.playground[6] == 1:
best = (1, 4, 8, 2, 6, 0, 7, 3, 5)
if Btn.playground.index(1) in (1, 3):
best = (1, 4, 0, 2, 6, 8, 7, 3, 5)
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 18.
Рис.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
if Btn.playground[2] == 1 and Btn.playground[6] == 1:
best = (1, 4, 8, 2, 6, 0, 7, 3, 5)
if Btn.playground.index(1) in (1, 3):
best = (1, 4, 0, 2, 6, 8, 7, 3, 5)
if Btn.playground[3] == 1 and Btn.playground[7] == 1:
best = (6, 4, 0, 2, 1, 8, 7, 3, 5)
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 19.
Рис.
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# t-t-t.py (tic tac toe)
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# t-t-t.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# t-t-t.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
if Btn.playground[2] == 1 and Btn.playground[6] == 1:
best = (1, 4, 8, 2, 6, 0, 7, 3, 5)
if Btn.playground.index(1) in (1, 3):
best = (1, 4, 0, 2, 6, 8, 7, 3, 5)
if Btn.playground[3] == 1 and Btn.playground[7] == 1:
best = (6, 4, 0, 2, 1, 8, 7, 3, 5)
if Btn.playground[4] == 1 and Btn.playground[0] == 1:
best = (2, 6, 8, 0, 1, 7, 3, 5)
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if all([not(i in (3, -3)) for i in [
pg[0] + pg[1] + pg[2],
pg[3] + pg[4] + pg[5],
pg[6] + pg[7] + pg[8],
pg[0] + pg[3] + pg[6],
pg[1] + pg[4] + pg[7],
pg[2] + pg[5] + pg[8],
pg[0] + pg[4] + pg[8],
pg[2] + pg[4] + pg[6]]]):
return False
return True
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 20.
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# t-t-t.py (tic tac toe)
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# t-t-t.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# t-t-t.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # Графическая библиотека
column = 3 # Количество колонок
row = 3 # Количество строк
class Btn(Button): # Класс Btn
btn_all = [] # Все кнопки (экземпляры типа Btn)
playground = [0] * (row*column) # Виртуальное игровое поле
game_over = False # Флаг конец игры
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = len(Btn.btn_all) # Номер кнопки
Btn.btn_all.append(self)
def play(self): # Функция игры
if Btn.playground[self.num] != 0: # Если клетка не свободна
return # Выход из функции
self.move(self.num, 1) # Ход крестиков
self.move(self.best(), -1) # Ход ноликов
def best(self): # Поиск лучшего хода
for k in (-1, 1): # Если есть возможность:
for i in range(9): # победить или проиграть
pg = Btn.playground.copy()
pg[i] = k if pg[i] == 0 else pg[i]
if self.win(pg): return i # Лучший ход
best = (4, 8, 1, 2, 6, 0, 7, 3, 5) # Порядок перебора ходов
if Btn.playground[2] == 1 and Btn.playground[6] == 1:
best = (1, 4, 8, 2, 6, 0, 7, 3, 5)
if Btn.playground.index(1) in (1, 3):
best = (1, 4, 0, 2, 6, 8, 7, 3, 5)
if Btn.playground[3] == 1 and Btn.playground[7] == 1:
best = (6, 4, 0, 2, 1, 8, 7, 3, 5)
if Btn.playground[4] == 1 and Btn.playground[0] == 1:
best = (2, 6, 8, 0, 1, 7, 3, 5, 4)
for i in best: # Поиск клетки для хода О
if Btn.playground[i] == 0: # Если клетка свободна
return i
def move(self, n, k): # Ход в n k=1 крестики, k=-1 нолики
if Btn.game_over: return # Если конец игры
Btn.playground[n] = k # Ход на виртуальном поле
Btn.btn_all[n].config(text = 'X' if k==1 else 'O') # Ход
if self.win(Btn.playground): # Если победа
Btn.game_over = True
tk.title('Win X' if k==1 else 'Win O')
elif not 0 in Btn.playground: # Если некуда ходить
Btn.game_over = True
tk.title('Ничья')
def win(self, pg): # Если победа, return True
if any([i in (3, -3) for i in
[pg[j] + pg[j+1] + pg[j+2] for j in range(0,9,3)]+
[pg[j] + pg[j+3] + pg[j+6] for j in range(3)]+
[pg[0] + pg[4] + pg[8], pg[2] + pg[4] + pg[6]]]):
return True
return False
tk = Tk() # Окно программы
tk.title('tic-tac-toe')
for i in range(row): # Формирование игрового поля
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки (клетки)
Btn(f, width=3, height=2, font=('times', 24, 'italic bold'))
mainloop() # Главный цикл программы
Лист. 21.