Как написать крестики нолики на python
Перейти к содержимому

Как написать крестики нолики на python

  • автор:

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

Закачайте дистрибутив игры, распакуйте. В нем два основных файла: runner.py, tictactoe.py. runner.py был уже создан для вас, он содержит код, создающий графический интерфейс игры. tictactoe.py содержит логику игры, вам надо закончить определение необходимых функции. После этого выполните в терминале python runner.py, чтобы запустить игру.

Шаги выполнения

  • Зайдите на https://code.cs50.io.
  • Загрузите дистрибутив.
  • Распакуйте.
  • Сделайте папку tictactoe рабочей.
  • Установите необходимые пакеты.
  • Завершите реализацию player, actions, result, winner, terminal, utility, minimax.

Пояснения

  • player для заданного состояния возвращает, кто ходит X или O. Начинают игру X.
  • action для заданного состояния игры должна возвращать set (множество) возможных действий. Каждое действие должно быть представлено как (i, j), i- строка и j — столбец пустой ячейки.
  • result для состояния и действия, возвращает новое состояние, не изменяет входное. Создаём копию входного состояние, в указанную действием ячейку помещаем знак ходящего игрока. Для создания копии используйте команду copy.deepcopy.
  • winner для заданного состояния возвращает победителя, если есть. Если X игрок победил, возвращает X. Если победил O, возвращает O. Победит тот, кто сделает три хода в строке, столбце или по диагонали. Если нет победителя, то функция должна вернуть None.
  • terminal для состояния возвращает True, если игра закончена, иначе — False. Игра закончена, если кто-то выиграл, или все ячейки были заполнены.
  • utility для терминального состояния возвращает -1, если выиграл O. Возвращает 0, если игра закончилась в ничью. 1, если выиграл X. Предполагаем, что функция будет вызываться только на состояния, для которых terminal(board) даёт True.
  • minimax для состояния возвращает оптимальный ход для игрока. Ход в виде пары (j, j). Если состояние терминальное, то возвращает None.

Как проверить

Сделайте рабочим каталог с программой.

Вы можете проверить правильность выполнения задания, выполнив команду Для отправки на проверку выполните команду

Как написать крестики нолики на python

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

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

Библиотека 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.

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

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

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

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

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

Списки, метод 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 кнопок.

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

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

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

В программе листинг 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, как обработчик события будет вызвана с параметром номер кнопки, который был вычислен на этапе создания кнопки.

Играем в Крестики-Нолики с Python и GTK

Новый блог GTK+ порадовал статьёй для начинающих и я решил попробовать что-то более простое, чем C++/C. Python оказался как нельзя кстати. Объём кода на Python для работы с GTK значительно меньше чем на C++, что не может не радовать.

PyGTK

PyGTK — биндинг библиотеки GTK для языка Python, PyGTK используется во многих открытых программах (например IM Gajim). Библиотека может быть очень интересна для Python программистов, поскольку проста в обращении и полностью скрывает реализацию GTK.

Под катом пример приложения.

Пример приложения

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

Окно игры:
Окно игры Крестики-Нолики

Итак приступим к реализации. В программе есть пара классов: XO_Field и XO_Win, первый хранит информацию о поле, второй создаёт GUI для приложения и обрабатывает события.

Я использовал для примера модуль pygtk, установленный из пакетного менеджера в Ubuntu, на других системах стоит воспользоваться пакетами или python easy-install, а для Windows есть инсталлятор.

Используем модуль pygtk версии 2.0 или старше:

Создадим простое окно, по закрытию которого будем прерывать и цикл событий GTK. Функция destroy будет приведена чуть позже.

Для окна воспользуемся вертикальной компоновкой из трёх строк с горизонтальной.
Так кнопки будут расположены как раз в виде квадрата 3×3. Для каждой из кнопок добавляется обработчик события «clicked», синтаксис добавления очень похож на сигналы и слоты в Qt.

Функция, создающая кнопку:

Запуск основного цикла событий GTK и уничтожение окна:

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

Сама игра в Крестики-Нолики и её реализация довольно тривиальна, ссылка на исходный код приведена ниже. Больший интерес представляет сам цикл работы приложения Python в связке с GTK, так например сборщик мусора при сборке ссылок на объекты GTK также вызывает деструкторы для них, поскольку элементы UI содержат много ссылок на ресурсы.

Глава 10.1 Исходный код игры «Крестики-Нолики».

Как всегда, я настоятельно советую набирать программу самостоятельно. Это и практика и программу понимать вы будете лучше. Впрочем, вы всегда можете скачать образец программы на странице «Загрузки«.

Итак, откройте новое окно текстового редактора Python Shell, наберите приведенный ниже код и сохраните в файле с названием ‘TicTacToe.py’ Впрочем, файл можете назвать как захотите. Но если вы потом решите конвертировать программу в *.exe — формат, то могут возникнуть проблемы с символами кириллицы в названии.

Поделиться ссылкой:

Понравилось это:

Похожее

2 комментария в “ Глава 10.1 Исходный код игры «Крестики-Нолики». ”

Добавь в начало кода
import time
import random
seconds=int(str(time.ctime()).split(‘:’)[2][0:3])
for a in range(seconds):
_random.randint(0,1)
Иначе первым всегда будет ходить один и тот же игрок,
а при добавлении данного кода в начало зависит от того момента, когда юзер открыл игру, сколько игра грузилась (а это уже зависит от компа)
Если вы используете другие функции этого модуля, надо повторять тот же код и для других функций:
import time
import random
seconds=int(str(time.ctime()).split(‘:’)[2][0:3])
for a in range(seconds):
_random.функция(аргументы)

Все это верно, но статья преследует максимально доступно и понятно объяснить концепт человеку, который еще не очень хорошо понимает Python. Кроме того, это, по сути, перевод из книги. Не хотелось ничего менять.
Но все что Вы написали, безусловно верно. И если человеку действительно будет интересно, как можно модифицировать программу, то как раз Ваш комментарий даст ему пищу для размышлений. Все останется как было.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *