Как сделать программу крестики нолики

Крестики-нолики — логическая игра между двумя противниками на квадратном поле 3 на 3 клетки или большего размера. Напишем программу игры крестики-нолики на Python с библиотекой tkinter.

Создадим поле из 9 кнопок для игры крестики-нолики.

from tkinter import * for i in range(9): Button().pack() mainloop()

Библиотека tkinter

В программе листинг 1, в первой строке мы импортируем все функции из библиотеки tkinter. Графическая библиотека tkinter входит в стандартный дистрибутив Python версии 3 и старше и служит для создания графического интерфейса программ на Pyton. В версии 2.7 имеется библиотека Tkinter с тем же функционалом.

Цикл for, функция range()

Ключевое слово for создаёт цикл, в котором переменная i последовательно принимает значения из диапазона range(9).

Функция range() создаёт диапазон значений. Параметрами функции range() могут быть границы диапазона и приращение (правая граница не включается в диапазон).

Цикл for создаётся с помощью ключевых слов for и in, определение цикла заканчивается двоеточием :. После двоеточия начинается тело цикла. Каждый оператор тела цикла, если он пишется с новой строки, должен иметь отступ слева. Для выделения блока операторов в python, (например, тела цикла) рекомендуется добавлять перед каждым оператором блока 4 пробела.

Как создать игру КРЕСТИКИ-НОЛИКИ?

Цикл for i in range(9): выполняется 9 раз, при этом переменная i принимает значения от 0 до 9 с шагом 1. 0 включительно 9 исключительно. Так как мы указли только один параметр диапазона range(), диапазон создан с левой границей 0 и шагом 1 по умолчанию. 9 — правая граница диапазона.

Конструктор Button() метод pack()

В цикле for выполняется конструктор Button() с методом pack().

Конструктор Button() создаёт объект кнопка. Метод pack() отображает объект кнопку в окне программы. Окно программы, у нас создаётся библиотекой tkinter по умолчанию, как только мы создаём в программе визуальный объект (кнопку, например). Функция Button() выполняется в цикле 9 раз и наша программа, листинг 1, создаёт 9 кнопок в окне нашего приложения, см. рис. 1.

from tkinter import * for i in range(9): Button().pack(expand=YES, fill=BOTH) mainloop()

В программе листинг 2 в методе pack() мы добавили два параметра. Параметр expand со значением YES применяется для того, чтобы визуальный объект мог занять всё свободное пространство в контейнере. В нашем случае, кнопка (визуальный объект) размещается в окне программы (контейнер).

Свойство fill со значением BOTH позволяет визуальному объекту растягиваться в обоих направлениях, по X и по Y до размера контейнера.

from tkinter import * for i in range(9): Button().pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

В программе листинг 3 параметр side со значением LEFT прижимает визуальный объект влево при размещении в контейнере.

Мастер класс Python. Игра крестики-нолики. Консоль

from tkinter import * for i in range(3): for j in range(3): Button().pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

Вложенные циклы

В программе листинг 4 мы, вместо одного цикла из 9 повторений сделали два вложенных цикла из 3х3 повторений. Программа всё так же создаёт 9 кнопок с теми же параметрами размещения, поэтому, внешне в окне программы ни чего не меняется.

from tkinter import * frm = [] for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): Button(frm[i]).pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

Списки, метод append(). Констуктор Frame()

В программе листинг 5 мы создали пустой список с именем frm. В цикле из трёх повторений в список frm методом append() добавляется 3 фрейма.

Фрейм — это контейнер для других визуальных объектов. По умолчанию фрейм невидим и прозрачен. Создаёт фреймы конструктор Frame(). В нашей программе мы размещаем невидимые фреймы на экране растянутыми по горизонтали методом pack() с соответствующими параметрами.

В итоге, мы имеем список frm состоящий из трёх фреймов. К верхнему фрейму можно обратиться по имени frm[0], к среднему — по имени frm[1], к нижнему — frm[3].

Во внутреннем цикле for методом Button() с параметром frm[i] создаются кнопки. Первый параметр метода Button() указывает на родительский контейнер в котором должна быть размещены кнопка. Так как переменная i первые три повторения внутреннего цикла имеет значение 0, то первые три кнопки размещаются в верхнем фрейме. Ещё три кнопки размещаются в среднем фрейме и ещё три — в нижнем.

В дальнейшем у нас возникнет необходимость обращаться к кнопкам, как к объектам, по имени. Поэтому, в программе листинг 6 мы создали пустой список btn в который в цикле будет добавлено 9 кнопок.

from tkinter import * frm = []; btn = [] for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i])) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

В программе листинг 6 в цикле из 9 повторений в список btn методом append() добавляется 9 объектов класса Button (кнопоки). В списке btn все кнопки имеют индекс (номер) от 0 до 8 включительно. Чтобы разместить эти кнопки на экране методом pack(), к каждой кнопке мы должны обратиться по индексу. Индекс очередной кнопки мы вычисляем, используя параметры внешнего и внутреннего цикла, переменные i и j.

Читайте также:
Как скачивать из инстаграма программы

В остальном, программа листинг 6 не отличается от программы листинг 5.

from tkinter import * frm = []; btn = [] def play(n): btn[n].config(text=str(n)) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i])) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

Функция пользователя

В программе листинг 7 с помощью ключевого слова def мы создали функцию play(). Новые функции, созданные программистом в программе называют функциями пользователя. Новые функции, обычно, создают в начале программы после определения глобальных переменных, до их первого упоминания в коде программы.

В теле функции play() мы прописали метод config() применяемый к кнопке по которой кликнул игрок. Параметр text метода config() выводит на кнопку надпись. Функция str() превращает число в строку. Параметр n, передаваемый в функцию play() это номер кнопки по которой кликнул игрок.

Обработка событий

Функция play() будет зарегистрирована как обработчик события «клик мышью по кнопке». Обработчик события по умолчанию для кнопки можно зарегистрировать методом config(). Параметр command метода config() регистрирует обработчик события. Так как значением параметра command должно быть имя функции без скобок, мы для передачи параметра в функцию play в случае возникновения события, воспользовались lambda функцией.

Функция lambda()

Первый параметр lambda функции n вычисляется в процессе создания объекта кнопка, а второй параметр, указанный в lambda функции после двоеточия, передаётся для регистрации в качестве обработчика события. А в lambda функции мы указываем функцию play() с круглыми скобками и передаваемым параметром n. Причём, параметр n вячисляется на этапе создания кнопки и сохраняется в свойстве command как значение. То есть, функция play, как обработчик события будет вызвана с параметром номер кнопки, который был вычислен на этапе создания кнопки.

from tkinter import * frm = []; btn = []; who = True def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’) who = not(who) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i])) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT) mainloop()

from tkinter import * frm = []; btn = []; who = True def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’) who = not(who) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i], text=’ ‘, font=(‘mono’, 20, ‘bold’), width=3, height=2)) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1) mainloop()

from tkinter import * frm = []; btn = []; who = True def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’, state=DISABLED) who = not(who) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i], text=’ ‘, font=(‘mono’, 20, ‘bold’), width=3, height=2)) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1) mainloop()

Часть 2. Думалка.

from tkinter import * frm = []; btn = []; who = True playArea = [] def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’, state=DISABLED) playArea[n] = 1 if who else -1 who = not(who) print(playArea) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i], text=’ ‘, font=(‘mono’, 20, ‘bold’), width=3, height=2)) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1) playArea.append(0) mainloop()

[1, 0, 0, 0, 0, 0, 0, 0, 0] [1, 0, 0, 0, 0, 0, 0, 0, -1] [1, 0, 0, 0, 1, 0, 0, 0, -1] [1, 0, 0, 0, 1, 0, -1, 0, -1] [1, 0, 0, 0, 1, 0, -1, 1, -1] [1, -1, 0, 0, 1, 0, -1, 1, -1] [1, -1, 0, 0, 1, 1, -1, 1, -1] [1, -1, 0, -1, 1, 1, -1, 1, -1] [1, -1, 1, -1, 1, 1, -1, 1, -1]
from tkinter import * frm = []; btn = []; who = True playArea = [] standings = [] # Турнирная таблица (положение) def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’, state=DISABLED) playArea[n] = 1 if who else -1 standings[0] = playArea[0] + playArea[1] + playArea[2] standings[1] = playArea[3] + playArea[4] + playArea[5] standings[2] = playArea[6] + playArea[7] + playArea[8] standings[3] = playArea[0] + playArea[3] + playArea[6] standings[4] = playArea[1] + playArea[4] + playArea[7] standings[5] = playArea[2] + playArea[5] + playArea[8] standings[6] = playArea[0] + playArea[4] + playArea[8] standings[7] = playArea[2] + playArea[4] + playArea[6] print(n, standings[0:8]) who = not(who) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i], text=’ ‘, font=(‘mono’, 20, ‘bold’), width=3, height=2)) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1) playArea.append(0) standings.append(0) mainloop()

0 [1, 0, 0, 1, 0, 0, 1, 0] 1 [0, 0, 0, 1, -1, 0, 1, 0] 2 [1, 0, 0, 1, -1, 1, 1, 1] 5 [1, -1, 0, 1, -1, 0, 1, 1] 4 [1, 0, 0, 1, 0, 0, 2, 2] 8 [1, 0, -1, 1, 0, -1, 1, 2] 7 [1, 0, 0, 1, 1, -1, 1, 2] 6 [1, 0, -1, 0, 1, -1, 1, 1] 3 [1, 1, -1, 1, 1, -1, 1, 1]
from tkinter import * frm = []; btn = []; who = True playArea = [] standings = [] # Турнирная таблица (положение) def play(n): global who btn[n].config(text= ‘X’ if who else ‘O’, state=DISABLED) playArea[n] = 1 if who else -1 standings[0] = playArea[0] + playArea[1] + playArea[2] standings[1] = playArea[3] + playArea[4] + playArea[5] standings[2] = playArea[6] + playArea[7] + playArea[8] standings[3] = playArea[0] + playArea[3] + playArea[6] standings[4] = playArea[1] + playArea[4] + playArea[7] standings[5] = playArea[2] + playArea[5] + playArea[8] standings[6] = playArea[0] + playArea[4] + playArea[8] standings[7] = playArea[2] + playArea[4] + playArea[6] print(n, standings[0:8]) for i in range(8): if standings[i] == 3: print(‘X win’) elif standings[i] == -3: print(‘O win’) who = not(who) for i in range(3): frm.append(Frame()) frm[i].pack(expand=YES, fill=BOTH) for j in range(3): btn.append(Button(frm[i], text=’ ‘, font=(‘mono’, 20, ‘bold’), width=3, height=2)) btn[i*3+j].config(command=lambda n=i*3+j:play(n)) btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1) playArea.append(0) standings.append(0) mainloop()

Читайте также:
Описание программы умники и умницы

0 [1, 0, 0, 1, 0, 0, 1, 0] 1 [0, 0, 0, 1, -1, 0, 1, 0] 4 [0, 1, 0, 1, 0, 0, 2, 1] 2 [-1, 1, 0, 1, 0, -1, 2, 0] 8 [-1, 1, 1, 1, 0, 0, 3, 0] X win

Источник: adior.ru

Крестики Нолики на Python: 5 Старт, Стоп и Результаты игры

Продолжаю серию статей по написанию игры «Крестики Нолики» на Python.

Предыдущие части:

Ранее мы создали игровое поле, создали функции отрисовки Крестика и Нолика и функцию обработки кликов по игровому полю, создали «Глупого Бота», который ставит нолики в пустые ячейки. Сделали проверку выигрыша и функцию зачеркивания выигрышной комбинации.

В этой статье доработаем функцию «end_game», чтобы игра завершалась корректно. Создадим функцию «new_game» которая будет запускать новую игру. Сделаем вывод статистики на экран.

Добавим переменные «you_win», «bot_win», «draw_game» для подсчета статистики и присвоим им значение 0.

Добавим переменные «you_win», «bot_win», «draw_game»

Определим функцию «new_game», которая будет запускать новую игру. В функцию перенесем из основной программы создание переменных «win» и «condition» и определим как глобальные, к ним добавим еще одну переменную «run_game», которая будет хранить в себе состояние игры, запущена или нет. Присваиваем значение «True».

Далее стираем все, что у нас есть на холсте (что осталось от предыдущей игры) командой «games.delete(«all»)». Цикл «for» который создавал ячейки на нашем холсте, переносим внутрь нашей функции. Все наша функция готова.

Функция «new_game»

В низу программы перед «root.mainloop()» добавляем вызов функции «new_game»

Добавляем вызов функции «new_game»

В функции «winner» определим переменные «you_win», «bot_win», «draw_game» как глобальные. И в зависимости от того кто победил, будем добавлять 1 к значению соответствующей переменной.

В функции «winner» определим переменные «you_win», «bot_win», «draw_game» как глобальные

В функцию «cliсk» добавим условие если игра запущена, то весь функционал работает. Иначе запускаем функцию «new_game». Что бы после завершения игры при клике на экран не отрабатывались нажатия с запуском функций «add_x».

В функцию «cliсk» добавим условие

Теперь займемся функцией «end_game». Импортируем модуль «time». Убираем вывод в консоль. Определяем переменную «run_game» как глобальную. Устанавливаем ей значение «False», чтобы отключить обработку кликов.

С помощью метода «time.sleep» делаем задержку 0,5 секунды.

Очищаем наш холст. И с помощью метода «create_text» выводим, текст, который хранится в переменной «win».

Обновляем экран «games.update», делаем задержку 0,5 секунды. Еще раз очищаем холст и с помощью метода «create_text» выводим нашу статистику. Для формирования текста используем «f-строку» . Ниже еще выводим одну строку с текстом «Нажми для продолжения»

Источник: dzen.ru

Крестики-нолики

Очень полезно в целях изучения языка программирования написать на нем несколько простых программ. Здесь мы представим игру крестики-нолики, которая написана на Python 3 с графическим интерфейсом.

О программе

В этой игре можно помериться силами с компьютером. Первый ход за игроком. Но победить искусственный интеллект в этом противостоянии будет не так уж и просто. Компьютер не делает «зевков» и если у него есть шанс победить, он непременно им воспользуется.

Внизу расположена кнопка для начала новой игры. По её нажатию игровое поле очистится и можно будет начать игру заново.

Игрок ставит крестики, а компьютер нолики. Как всегда, побеждает тот, кто первый составит линию из своих символов: по горизонтали, вертикали или диагонали.

Библиотеки и объявление переменных

Для отображения графики будем использовать стандартную библиотеку Tkinter, которая устанавливается вместе с Python. Так же нам потребуется библиотека random для того, чтобы получать случайные числа, благодаря которым ходы компьютера будут неожиданными.

Это также стандартная библиотека Python. Так что ничего дополнительно устанавливать не надо. Просто подключаем их с помощью import . Создаем окно root , устанавливаем ему заголовок и объявляем необходимые переменные:

  • game_run – в эту переменную будем записывать False при завершении игры, чтобы запретить делать ходы когда уже выявлен победитель.
  • field – это будет двумерный список, в котором будут храниться кнопки игрового поля. Ходом будет изменение надписи на кнопке на символ «X» или «O».
  • cross_count в этой переменной мы будем отслеживать количество крестиков на поле. Чтобы по выставлению пятого крестика, в случае если никто не выиграл фиксировать ничью.
Читайте также:
Примеры управляющих программ для токарных станков с чпу

from tkinter import * import random root = Tk() root.title(‘Criss-cross’) game_run = True field = [] cross_count = 0

Обработка нажатия кнопок

Функция new_game будет вызываться при нажатии кнопки начала новой игры. На поле убираются все крестики и нолики. Цвет кнопок делаем бледно-лиловым.

Устанавливаем глобальные переменные game_run и cross_count в начальные значения. Это глобальные переменные к которым пытаемся обратиться из функции. Поэтому перед попыткой изменить их значение, в Python надо использовать ключевое слово global .

def new_game(): for row in range(3): for col in range(3): field[row][col][‘text’] = ‘ ‘ field[row][col][‘background’] = ‘lavender’ global game_run game_run = True global cross_count cross_count = 0

Функция click будет вызываться после нажатия на поле, то есть при попытки поставить крестик. Если игра еще не завершена, то крестик ставится. После этого увеличиваем счетчик количества выставленных крестиков.

Потом проверяем с помощью функции check_win , не победили ли мы этим ходом. Если еще не выявлен победитель и есть еще ходы, то выполняет ход компьютер функцией computer_move , и также после хода идет проверка выигрыша.

def click(row, col): if game_run and field[row][col][‘text’] == ‘ ‘: field[row][col][‘text’] = ‘X’ global cross_count cross_count += 1 check_win(‘X’) if game_run and cross_count < 5: computer_move() check_win(‘O’)

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

Функция check_win осуществляет проверку выигрыша. Она перебирает все возможные комбинации полей, образующих линию и вызывает с ними функцию check_line . Переменная smb – это символ «X» или «O», то есть крестики или нолики. Если задан «O», то проверяется: не победил ли компьютер.

Если зафиксирован выигрыш, то меняем цвет фона кнопок, составляющих линию на розовый. А также записываем в game_run значение False .

def check_win(smb): for n in range(3): check_line(field[n][0], field[n][1], field[n][2], smb) check_line(field[0][n], field[1][n], field[2][n], smb) check_line(field[0][0], field[1][1], field[2][2], smb) check_line(field[2][0], field[1][1], field[0][2], smb) def check_line(a1,a2,a3,smb): if a1[‘text’] == smb and a2[‘text’] == smb and a3[‘text’] == smb: a1[‘background’] = a2[‘background’] = a3[‘background’] = ‘pink’ global game_run game_run = False

Проверяем все возможные варианты, так как теоретически можно одним ходом составить сразу 2 линии.

Действия компьютера

Ход компьютера рассчитывается в функции computer_move . Алгоритм его действий следующий:

  1. Проверка возможности победы. Если компьютеру представился шанс победы – он не должен его упустить. Сразу же делает победу.
  2. Проверка возможной победы противника за один ход. Если игрок выставил два крестика в ряд, компьютер пытается разрушить планы игрока.
  3. Случайный ход. Так как победить нет возможности и нет угрозы проигрыша, то выбирается случайное свободное поле. В бесконечном цикле wile перебираются случайные числа, пока они не выпадут на не занятое поле.

def can_win(a1,a2,a3,smb): res = False if a1[‘text’] == smb and a2[‘text’] == smb and a3[‘text’] == ‘ ‘: a3[‘text’] = ‘O’ res = True if a1[‘text’] == smb and a2[‘text’] == ‘ ‘ and a3[‘text’] == smb: a2[‘text’] = ‘O’ res = True if a1[‘text’] == ‘ ‘ and a2[‘text’] == smb and a3[‘text’] == smb: a1[‘text’] = ‘O’ res = True return res def computer_move(): for n in range(3): if can_win(field[n][0], field[n][1], field[n][2], ‘O’): return if can_win(field[0][n], field[1][n], field[2][n], ‘O’): return if can_win(field[0][0], field[1][1], field[2][2], ‘O’): return if can_win(field[2][0], field[1][1], field[0][2], ‘O’): return for n in range(3): if can_win(field[n][0], field[n][1], field[n][2], ‘X’): return if can_win(field[0][n], field[1][n], field[2][n], ‘X’): return if can_win(field[0][0], field[1][1], field[2][2], ‘X’): return if can_win(field[2][0], field[1][1], field[0][2], ‘X’): return while True: row = random.randint(0, 2) col = random.randint(0, 2) if field[row][col][‘text’] == ‘ ‘: field[row][col][‘text’] = ‘O’ break

Графический интерфейс

Все элементы графического интерфейса мы будем размещать с помощью упаковщика grid . В цикле добавим кнопки игрового поля. Они будут храниться в двумерном список. В языке программирования Python добавляют элементы в список с помощью метода append .

Свойство colorspan у кнопки начала игры выставляем в 3, чтобы он занимал всю ширину таблицы

for row in range(3): line = [] for col in range(3): button = Button(root, text=’ ‘, width=4, height=2, font=(‘Verdana’, 20, ‘bold’), background=’lavender’, command=lambda row=row, col=col: click(row,col)) button.grid(row=row, column=col, sticky=’nsew’) line.append(button) field.append(line) new_button = Button(root, text=’new game’, command=new_game) new_button.grid(row=3, column=0, columnspan=3, sticky=’nsew’) root.mainloop()

Игровое поле мы делали таким же образом как и кнопки в примере с калькулятором, размещённом в отдельной статье.

В целом, реализация игры крестики-нолики неплохо подходит для изучающих программирование на Python 3. Можно немного усложнить задачу, добавив уровни сложности. Например, на простом уровне сложности компьютер делает абсолютно случайные ходы. На более сложном не упускает возможности победить, но все еще может прозевать два крестика выставленных в ряд.

Источник: all-python.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru