Крестики-нолики — логическая игра между двумя противниками на квадратном поле 3 на 3 клетки или большего размера. Цель игры, занять три клетки в ряд, включая диагонали. Пишем программу игры крестики-нолики на Python с библиотекой tkinter.
Кто решает задачи по комбинаторной геометрии, тот
впоследствии пишет короткие и сильные алгоритмы.
Саватеев.
Мы публикуем методическую разработку для занятий с детьми старше 12-ти лет в кружке программирование на Python. Цель - научить детей строить логические выражения и пользоваться условным оператором if (elif, else), использовать цикл for, вложенный цикл и операторы continue и break, а также, создавать собственные функции и возвращать из них результат. В конце статьи приведён пример использования алгоритма minimax с рекурсией (динамическое программирование).
Возьмём шаблон для игр на поле в клетку. Подробнее о создании этого шаблона на странице Игровое поле 2023.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def play(n): # функция обработчик нажатия на кнопку
btn[n].config(text=n)
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(text=playground[n])
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 1.
Игра Крестики-нолики для 2-х игроков
апва
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row # виртуальное игровое поле
def play(n): # функция обработчик нажатия на кнопку
btn[n].config(text="X")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 2.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def play(n): # функция обработчик нажатия на кнопку
move(n, playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[9] *= -1
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 3.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def play(n): # функция обработчик нажатия на кнопку
if playground[n] == 0:
move(n, playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 4.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] == 0:
move(n, playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
print(won(p_g))
print(standings)
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 5.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] == 0 and not(won(playground)):
move(n, playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 6.
Ира с компьютером
Игрок и компьютер ходят по очереди.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def best(p_g): # поиск лучшего хода
return p_g.index(0) # ход болвана
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 7. Игра с болваном.
Возможно, лучший первый ход в ценр?
Лист. 8. Компьютер ходит в центр, если центральная клетка не занята.
#!/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.
# I thank Sergey Polozkov and Timur Sharafutdinov, Yana Romanova, Gleb Shalimov
# for checking the code for hidden errors.
#
# brownian-motion.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 *
from random import *
btn = [0]*9 # Для кнопок
first = True # Первым ходит нолик
def startGame():
global first, btn, playArea, standings
playArea = [0]*9 # Виртуальное игровое поле
standings = [0]*8 # Суммы линий
for i in btn: i.config(text=' ', font=('mono', 20, 'bold'), width=5, heigh=3)
if first:
n = choice(range(9))
btn[n].config(text = 'O')
playArea[n] = -1
first = not first
tk.title('Tic Tac Toe')
def won(Ar): # Подсчёт сумм линий
for i in range(3):
standings[i] = Ar[i*3] + Ar[i*3+1] + Ar[i*3+2]
standings[i+3] = Ar[i] + Ar[i+3] + Ar[i+6]
standings[6] = Ar[0] + Ar[4] + Ar[8]
standings[7] = Ar[2] + Ar[4] + Ar[6]
if 3 in standings or -3 in standings: return True
return False
def theBest():
if playArea[4] == 0: return 4 # Первый ход
for i in range(9): # Если есть возможность победить
if playArea[i] != 0: continue # Если клетка не свободна
A = playArea.copy() # Делаем копию виртуального поля
A[i] = -1 # Делаем пробный ход
if won(A): return i # Если пробный ход принёс победу
best = True # Предположим что ход i не плохой
for j in range(9): # Есть возможность проиграть?
if A[j] != 0: continue # Если клетка не свободна
B = A.copy() # Делаем копию копии виртуального поля
B[j] = 1 # Делаем пробный ход
if won(B) or (standings.count(2)>1 and -2 not in standings):
best = False # Xод i оказывается плохой
break
if best: сandidate = i # Если ход i не плохой
return сandidate # Если следующий ход не победный
def test(): # Нолик победил или ничья
if won(playArea) or 0 not in playArea:
tk.title('O win' if -3 in standings else 'No won')
return True
return False
def play(n): # Ход крестика, поиск хода нолика
if test(): # Если конец игры
startGame()
return
if playArea[n] != 0: return # Если клетка не свободна
btn[n].config(text = 'X') # Ход крестика
playArea[n] = 1 # Ход на виртуальном поле
if test(): return # Если конец игры
i = theBest() # Оптимальный ход
btn[i].config(text = 'O') # Делаем ход
playArea[i] = -1
if test(): return # Если конец игры
tk = Tk() # Окно программы
for i in range(0, 3):
frm = Frame()
frm.pack(expand=YES, fill=BOTH)
for j in range(0, 3):
btn[i*3+j] = Button(frm, command = lambda n=i*3+j: play(n))
btn[i*3+j].pack(side=LEFT, expand=YES, fill=BOTH)
startGame()
mainloop()
sgsfg
min-max
xcvf
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(minimax(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def minimax(p_g): # поиск лучшего хода
return p_g.index(0) # ход болвана
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 50. За основу взят листинг 7.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(minimax(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
def minimax(p_g): # поиск лучшего хода
return p_g.index(0) # ход болвана
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
51
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(minimax(playground)[1], playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
def minimax(p_g): # поиск лучшего хода
if won(p_g): return [p_g[9], None]
elif 0 not in p_g: return [0, None]
best = [p_g[9]*2, None]
for i in range(9):
if p_g[i] == 0:
new_pg = p_g.copy()
setpg(i, new_pg)
value = minimax(new_pg)[0]
if p_g[9] == 1 and value <= best[0]:
best = [value, i]
elif p_g[9] == -1 and value >= best[0]:
best = [value, i]
return best
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
53
#!/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.
# I thank Sergey Polozkov and Timur Sharafutdinov
# for checking the code for hidden errors.
#
# brownian-motion.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 * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(minimax(playground)[1], playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
return p_g
def minimax(p_g): # поиск лучшего хода
if won(p_g): return [p_g[9], None]
elif 0 not in p_g: return [0, None]
best = [p_g[9]*2, None]
for i in range(9):
if p_g[i] == 0:
value = minimax(setpg(i, p_g.copy()))[0]
if p_g[9] == 1 and value <= best[0]:
best = [value, i]
elif p_g[9] == -1 and value >= best[0]:
best = [value, i]
return best
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
55
В определении функции setpg() добавлена строка return p_g, что позволило в определении функции minimax() в цикле for объединить 3 строки в одну.
2024 год
ыв
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def best(p_g): # поиск лучшего хода
return p_g.index(0) # ход болвана
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 1. Ходилка. Игра с болваном.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
p_g[n] = p_g[9]
p_g[9] *= -1
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def best(p_g): # поиск лучшего хода
for i in range(9):
if p_g[i] == 0:
best = i
return best
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 2. Игра с болваном, который перебрав все возможные ходы, выбирает последний ход.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
def best(p_g): # поиск лучшего хода
for i in range(9):
if p_g[i] == 0:
best = i
return best
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 3. Функция move разделена на 2 функции move и setpg.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
def best(p_g): # поиск лучшего хода
for i in range(9):
if p_g[i] == 0:
best = i
new_pg = p_g.copy()
setpg(i, new_pg)
if won(new_pg):
return best
return best
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 4. Компьютер делает ход на копии playground и если он находит победный ход, то делает его.
from tkinter import * # графическая библиотека
from random import shuffle # перемешать список suffle(A)
column = 3 # столбцы
row = 3 # строки
btn = []
playground = [0] * column * row + [1] # виртуальное игровое поле
# если playground[9] = 1, ходит чел.
# если playground[9] = -1, ходит комп.
def won(p_g): # вычисляет факт победы
global standings
standings = [0] * 8 # турнирная таблица (состояния на линиях)
for i in range(3):
for j in range(3):
standings[i] += p_g[i*3 + j]
standings[i+3] += p_g[i + j*3]
standings[6] += p_g[i*4]
standings[7] += p_g[i*2 + 2]
if 3 in standings or -3 in standings: return True
return False
def play(n): # функция обработчик нажатия на кнопку
if playground[n] != 0 or (won(playground)):
return
move(n, playground)
if 0 in playground and not(won(playground)):
move(best(playground), playground)
def move(n, p_g): # Ход в клетку n
btn[n].config(text = "X" if p_g[9] == 1 else "O")
setpg(n, p_g)
if won(p_g):
tk.title("Победили Х" if p_g[9] == -1 else "Победили 0")
def setpg(n, p_g): # сделать ход на виртуальном поле
p_g[n] = p_g[9]
p_g[9] *= -1
def best(p_g): # поиск лучшего хода
best = p_g.index(0)
for i in range(9):
if p_g[i] == 0:
new_pg = p_g.copy()
setpg(i, new_pg)
if won(new_pg):
return i
elif not virtplay_x(new_pg):
best = i
return best
def virtplay_x(p_g):
for i in range(9):
if p_g[i] == 0:
new_pg = p_g.copy()
setpg(i, new_pg)
if won(new_pg):
return True
return False
tk = Tk()
tk.geometry('300x300')
tk.title("Tic-tac-toe")
for i in range(row):
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH) # Вывод фрейма на экран
for j in range(column):
n = i * column + j
btn += [Button(f)]
btn[n].pack(expand=YES, fill=BOTH, side=LEFT)
btn[n].config(width=3, height=2)
btn[n].config(command=lambda n=n: play(n))
mainloop() # главный цикл программы
Лист. 5. Компьютер продумывает стратегию на 2 хода, но не видит угрозу вилки.