# Tic tac toe — крестики-нолики по шагам (статическая реализация интерфейса)
В данном примере проекта приводится игра крестики-нолики с четырьмя кнопками. Пример использует упрощенную модель 2х2, которая помогает понять какие шаги необходимо пройти для реализации полной версии программы.
Задание:
Названия переменных должны быть корректными:
- существующие английские слова;
- имя переменной всегда начинается с имени существительного отражающее суть/смысл переменной;
- соединение двух и/или более слов через нижнее подчеркивание.
Создать окно с названием версии и виджеты Button() .
- реализовать отображение четырех кнопок.
Рекомендации:
В названиях кнопок можно использовать цифры обозначающие место положение соответствующей кнопки: "button_11", где первая единица означает столбик, а вторая — строка.
Для задания размеров кнопки лучше использовать параметры grid() : ipadx= и ipady= , т.к. данный способ не вызывает ошибки при подключенной библиотеки ttk.
# 2. Реализация нажатия кнопок
Добавляем функции нажатия кнопок и отображение "Х".
Задание:
Изменить версию в заголовке окна.
Названия функций должны быть корректными:
- существующие английские слова;
- название начинается всегда с глагола отражающие суть/смысл функции;
- соединение двух и/или более слов через нижнее подчеркивание: "кнопка_нажата".
Создать четыре функции нажатия кнопок для отображения значка "Х".
Рекомендации:
- Тело созданных функций желательно делать максимально похожими, это необходимо для понимания универсальности функций.
# 3. Смена ввода "Х" на "О"
Задание:
- Изменить версию в заголовке окна.
- Добавить глобальную переменную для отслеживания очереди хода игрока.
- Изменить тело функций, учитывая очередность:
- при последующем нажатии кнопки происходило чередование выводимых символов "Х" и "О".
- на этом шаге символы в кнопках могут заменять друг друга.
Рекомендации:
- Тело созданных функций желательно делать максимально похожими.
- Для отслеживания состояния переключения можно воспользоваться функцией print() .
# 4. Проверка ввода
Задание:
- Изменить версию в заголовке окна.
- Изменить тело функций, добавив проверку на пустоту:
- при последующем нажатии кнопки, если в кнопке ещё не задан символ, то происходило вывод символа "Х" или "О", в зависимости от очередности.
- на этом шаге символы, выведенные в кнопках, не могут заменять друг друга.
Рекомендации:
- Тело созданных функций желательно делать максимально похожими.
- Для отслеживания состояния переключения можно воспользоваться функцией print() .
- Создать дополнительные функции и переменные не требуется.
# 5. Кнопка "новая игра"
Для дальнейшего удобства проверки работы программы добавим кнопку "новая игра".
Задание:
- Изменить версию в заголовке окна.
- Добавим кнопку "NEW GAME".
- Напишите функцию создания новой игры, которая убирает все символы с кнопок.
# 6. Составление условий победы
Для начала реализации проверки победителя составим логические выражения для проверки победы игрока символом "Х".
Задание:
- Изменить версию в заголовке окна.
- Напишите функцию проверки победителя:
- вызов функции происходит после хода каждого игрока;
- используя функцию print() выводите все состояния победных комбинаций: горизонтали, вертикали и диагонали;
- проверьте правильность работы всех условий.
Рекомендации:
Для удобства в консоли выводите текст вида: "Row 1: True" или "Diagonal 12-21: True" и т.п.
Не забывайте использовать f""-строку.
# 7. Проверка победы "Х"
В этом шаге добавляем проверку условия и если выпала выигрышная комбинация, то в консоль выводиться: "X — won!"
Задание:
- Изменить версию в заголовке окна.
- Измените функцию проверки победителя:
- создайте одну "условную" конструкцию if;
- добавьте логические выражения проверки "Х" в условие, соединив логические выражения;
- при появлении выигрышной комбинации в консоль выводиться "X — won!"
- Проверьте правильность работы нескольких комбинаций.
Рекомендации:
- Лучше проверить все возможные выигрышные комбинации для исключения ошибки.
# 8. Проверка победы "ХО"
В этом шаге добавляем проверку условия и если выпала выигрышная комбинация, то в консоль выводиться: "X — won!" или "О — won!"
Задание:
- Изменить версию в заголовке окна.
- Измените функцию проверки победителя:
- изменить условие при котором будет проверяться соответствие выигрышных комбинаций "Х" или "О";
- при появлении выигрышной комбинации в консоль выводится "X — won!" или "О — won!" в соответствии с игровым полем.
- Проверьте правильность работы нескольких комбинаций.
Рекомендации:
- Лучше проверить все возможные выигрышные комбинации для исключения ошибки для "Х" и "О".
# 9. Конец игры
При выигрыше одним из игроков реализуем блокировку кнопок. При создании новой игры блокировка должна отключаться.
Крестики-нолики на CSS
Довольно странный вариант игры. Мне хотелось понять как ещё можно сымитировать игровую логику.
Правда, без капельки JS всё-же не обошлось: я не обнаружила способ сбрасывать игру и возложила это на JS. Если попытаться обойтись совсем без него, можно было бы просто перегружать страницу.
Результат игры обрабатывается с помощью CSS. Игра заканчивается при однозначном выигрыше либо при ничьей и полностью заполненном поле.
Теоретически можно было бы учитывать ничью до заполнения поля, это возможно, но код будет совсем длинным, так что я отказалась от этой затеи.
Ещё следовало бы сделать плавным появление панели с результатом, но у меня не получилось совладать с поведением псевдоэлементов. Анимировались некоторые свойства, которые точно об этом никто не просил, например text-indent . Для более аккуратной анимации проишлось бы увеличить код на две трети, или я просто не сообразила как это можно решить изящнее.
Я думаю, этот способ можно использовать и для полей побольше, хотя в этом случае селекторы будут километровыми, и без препроцессоров уже точно не обойтись не получится.
Пишем игру крестики-нолики на Python на двоих и против компьютера
Если вы учитесь программировать, то программирование игр — это очень хороший способ освоить алгоритмы и структуры данных. В этом уроке мы разберем запрограммируем игру крестики нолики на Python. Полный код программы с искусственным интеллектом для игрока-компьютера занимает всего 140 строк. В варианте игры где человек играет против человека — раза в два меньше.
Игра крестики-нолики хороша тем, что ее правила знакомы всем с детства и понятны каждому. Это даст вам возможность сосредоточиться именно на процессе программирования, а не на анализе правил игры. В процессе работы над игрой крестики-нолики мы будем использовать только стандартные функции языка Python без подключения каких либо сторонних библиотек.
Шаг 1. Подбор структуры данных
Программирование любой игры начинается с моделирования ее объектов средствами языка программирования. Когда мы программируем игру крестики нолики нам нужно подумать где в программе хранить поле для игры с ходами которые сделали игроки.
В языке программирования Python наилучшим выбором будет список из 9 значений. Назовем его maps. Первоначально этот список будет заполнен цифрами от 1 до 9. Это сделано для удобства организации диалога с пользователем. Пользователю будет достаточно ввести символ от 1 до 9, что бы мы смогли понять куда он сделал ход. После того как ход сделан, цифру мы заменим на символ нолика или крестика. (Можно было заполнить цифрами от 0 до 8. В этом случает было бы удобнее работать — цифра и есть индекс элемента в списке, но первый нолик будет смущать игроков).
Еще мы создадим второй список victories в котором будем хранить информацию обо всех выигрышных комбинациях. И нам будет нужно создать функцию print_maps, которая будет выводить содержимое нашего списка maps на экран.
Со структурами данных разобрались.
Шаг 2. Выполнение очередного хода и проверка на выигрыш
Карта для игры у нас есть, отображать ее мы умеем. Теперь нужно создать две вспомогательные функции, прежде чем мы приступим к программированию основного цикла игры.
Первая функция будет рисовать на поле крестик или нолик, в зависимости от того что в нее передали. Позицию в нее так же нужно будет передавать. Вставлять переданный элемент мы будем по индексу. Индекс определим функцией index (если бы мы пронумеровали от 0 до 8 элементы в maps, то переданное значение и было бы индексом. Можете попробовать — будет на одну строчку кода меньше.)
После каждого ходы мы должны проверять — не победил ли кто то из игроков. Для этого переберем все победные линии из списка victories и проверим нет ли там комбинации из трех крестиков или трех ноликов.
Эта функция вернет «X» в случае победы крестиков и «O» в случае победы ноликов.
Шаг 3. Основный игровой цикл
Ну вот мы и подошли к созданию основного игрового цикла. Нам предстоит крутиться в цикле до момента пока кто нибудь не выиграет. Игроки будут по очереди делать ходы, мы будем проверять каждый раз не победил ли кто и как только кто то побеждает — выходим из цикла и завершаем программу.
Вот полный код программы крестики-нолики на Python для двух игроков:
Вот так выглядит процесс игры в крестики-нолики для 2 игроков:
Шаг 4. Добавление алгоритма для искусственного интеллекта в игре крестики-нолики
А вот теперь мы подобрались к самому интересному моменту в программировании. Нам нужно создать искусственный интеллект, который всегда будет выигрывать или сводить игру к ничьей. На самом деле в игре крестики-нолики такой алгоритм написать совсем не сложно.
Для написания такого алгоритма нам понадобится вспомогательная функция, которая будет проверять все победные линии в игре и подсчитывать в них количество крестиков и ноликов. Если функция находит такую линию, то она возвращает позицию на этой линии куда нужно сделать ход. Например мы будем отслеживать линии где противник поставил два крестика и обязательно поставим нолик, что бы не дать ему выиграть. Вот эта функция:
А сейчас мы напишем функцию для поиска очередного лучшего хода для искусственного интеллекта. Запрограммируем такой алгоритм для каждого хода (компьютер играет ноликами):
- Если этим ходом можем выиграть — выигрываем (уже 2 нолика стоят на одной из линий). Иначе идем к шагу 2.
- Если можем помешать выиграть человеку — мешаем ( у человека уже 2 крестика на линии — ставим на нее нолик). Иначе идем к шагу 3.
- Если на линии одна наша фигура — ставим вторую. Если пока ни одной нашей фигуры — идем к шагу 4.
- Ставим нолик в центр. Если центр занят идем к шагу 5.
- Ставим в левый верхний угол.
А вот так все это выглядит в программе на Python:
Немного перепишем и основной цикл игры. Теперь вместо человека 2 ход будет делать компьютер. Компьютер каждый раз будет говорить куда делает ход. Если компьютер не дает ответ, значит наметилась ничья — завершаем партию и объявляем ничью. Вот таким станет основной цикл игры, когда мы перепишем программу крестики-нолики под игру против компьютера:
Готовая программа для игры в крестики нолики против компьютера на Python
Вот готовая программа для для игры против искусственного интеллекта.
Вот пример игрового процессе. В этой игре победил компьютер:
Вы можете прямо сейчас поиграть в крестики нолики против компьютера или друг против друга. Просто скопируйте текст программы на этой странице и вставьте его в поле программы в этом онлайн эмуляторе Python: https://replit.com/languages/python3 или тут https://www.onlinegdb.com/online_python_compiler
Домашнее задание
У нас получилась довольно беспощадная программа. Ее искусственный интеллект победить не возможно. Человек либо проигрывает, либо играет в ничью. Подумайте как можно дать человеку иногда выигрывать? Возможно вы захотите создать несколько уровней. Например в первом искусственный интеллект очень слаб, дальше он умнет. Или у вас будет на выбор несколько режимов игры на выбор: слабый ИИ, средний и непобедимый.
В общем ваша задача немного ослабить искусственный интеллект в нашей игре крестики-нолики. Сделать его чуть более человечным.
Крестики-нолики (PixiJS)

Это лучшее описание, которое я мог придумать. Именно с это целью я начал писать простенькие программы чтобы отточить свои навыки, познакомиться с новыми конструкциями в привычном мне языке и если честно, то это даже стало приносить мне удовольствие.
Если у вас мало опыта разработки, то статья будет полезной, а если у вас уже есть опыта разработки, то потратьте время на что-то более стоящее.
Это не обучение. Больше похоже на блог.
Была цель сделать 3 версии игры крестики нолики.
1 — Самое простое(без красивого визуала, с помощью DOM)
2 — Дать возможность играть вдвоем(один компьютер)
3 — Перенести все это в canvas
Описывать крестики-нолики я не буду, надеюсь, все знают принцип игры. Все полезные ссылки(репозиторий, документация) будут в конце статьи.
Что из этого вышло? Хм…
Первая версия

Это самое простое. Если честно, то и последующие версии не отличаются сложностью…
Нам нужна верстка из контейнера в котором потребуется разместить наше игровое поле. Я добавил data-item каждому элементу т.к. думал, что потребуется идентификатор, но его я не использовал.
Сразу хочу предупредить! Данный код не стоит расценивать как единственно верным и писать иначе считать ошибкой. Это мой способ решения и не более того.
Так. Для начала нам потребуется забиндить клик по ячейке. Во время клика мы ходим(бот тоже, но по очереди) и проверяем ячейку.
Бот ходит рандомно.
Здесь можно было написать все через циклы. Я выбрал более простой путь. У меня поле всегда статично. Поэтому простая проверка ячеек. Стоит отметить, что я возвращаю объект чтобы в будущем проверить кто одержал победу. В объекте свойства val и win. Val отвечает за окончание игры.
Во время клика у нас есть проверка, а вернул ли checkMap val: true. Если да, то завершаем игру.
Вторая версия
Два игрока за одним компьютером.
Вынес часть логики из обработчика клика в отдельную функцию и передаю в функцию контекст вызова, ведь нам нужно определить на какую кнопку жмякнули.
Я разделил на две функции, но в них есть дублирование кода. В идеале разделить на 3. Одна основная, а две работающие с контекстом.
Третья версия
Пожалуй это самый интересный пункт т.к. теперь игра действительно похожа на игру, а не на взаимодействие DOM элементов.
Я выбрал для работы PixiJS. Не могу сказать ничего о + и — этой библиотеки, но я посмотрел один пример в котором было 60 000 элементов и все они анимированные. Анимация простая, но FPS держался на 50-60. Мне это понравилось и я стал читать документацию. Скажу сразу, знания анг языка у меня минимальны, было сложно, а на Русском статей очень мало.(или я плохо искал). Пришлось методом тыка и с помощью гуугл переводчика пробираться через тернии.
Посмотрел лишь один доклад на эту тему Юлия Пучнина «Жирная анимация с Pixi js».
Доклад от 2014 года и нужно понимать, что API могло измениться. Одним глазом в документацию, а вторым на видео. Так и изучал. Хватило 4 часа чтобы написать такой простенький прототип. Ближе к коду.
Производим дефолтную инициализацию pixi
а так же создадим wrapper(основной контейнер с ячейками) и поместим его в наш canvas
В цикле мы создаем наши ячейки, задаем им нужные размеры, координаты, а так же добавляет дефолтное значение ячейке в виде пустой строки т.к. это пригодится в будущем и вешаем на ячейки обработчики, предварительно включив флаг интерактивности у контейнера.
addValueInBlock отвечает за ход каждого игрока. Я не нашел лучше способа чем объявлять для каждого текста свои стили. Там меняется цвет, а как изменить цвет так и не разобрался. Приходится каждый раз новые стили задавать тексту. Также здесь идет проверка ячеек.
Касаемо самой проверки. checkMap. Я так понял, у pixiJS нельзя обратиться к элементу по имени или id. Приходится перебирать всю коллекцию в контейнере из-за этого код выглядит громозким. Функция ничем не отличается от предыдущих, кроме параметров, которые она возвращает.
Ну и две последних функции отвечают за окончание игры и очистку канваса. Мне кажется, объяснение здесь лишнее.
Если подытожить, то было интересно провести разработку в несколько этапов. Пусть не идеальный цикл разработки, но с чего то мне нужно было начинать.