Содержание
  1. Подготовка к проекту: что нужно, чтобы сделать крестики-нолики на Python
  2. Создание игрового поля и вывод доски
  3. Почему поле [[" "] * 3] * 3 ломает игру
  4. Обработка пользовательского ввода
  5. Логика игры: проверка на выигрыш и завершение игры
  6. Как сделать крестики-нолики на Python с компьютером, который не проигрывает
  7. Создание пользовательского интерфейса: окно на tkinter
  8. Крестики-нолики на Pygame: что меняется
  9. Интеграция модели ChatGPT: как попросить нейросеть написать эту игру
  10. Частые ошибки и как их узнать по симптому
  11. Заключение: какой способ выбрать под свою задачу
  12. Частые вопросы про крестики-нолики на Python
ГайдыОбновлено · 09.2026

Python: создаем игру «Крестики-нолики» с помощью ChatGPT

28 марта 2024 · 22 минуты чтения

Как сделать крестики-нолики на Python: собрать поле из вложенных списков, задать список из восьми выигрышных линий и написать цикл, который передаёт ход. Консольная версия для двоих занимает 53 строки кода и работает без установки библиотек. Окно даёт tkinter из стандартной библиотеки, непобедимого соперника — функция минимакса на 16 строк.

Коротко:

  • Три способа собрать игру: консоль (ничего не ставим), окно на tkinter (ничего не ставим), графика на Pygame (нужен pip install pygame). Сравнение — в таблице ниже.
  • Победу удобно искать одним списком из восьми линий: восемь кортежей заменяют шестнадцать условий if.
  • Главная ловушка новичка — поле [[" "] * 3] * 3. Оно выглядит правильным и ставит символ сразу в три строки.
  • Компьютер-соперник на минимаксе не проигрывает: в нашем полном переборе всех партий — 681 игра, 498 побед бота, 183 ничьи, 0 поражений.
  • Код из старых руководств с openai.Completion.create(engine="davinci-codex") сегодня не запустится: модели Codex выключены 23 марта 2023 года.

Весь код ниже проверен запуском на Python 3.14.3 под Windows: консольная партия, партия против бота и клики в окне tkinter. Числа в статье взяты из этих прогонов, каждый воспроизводится одной командой.

Игра подходит как первый проект после синтаксиса: правила знает каждый, поле помещается в один экран, а по дороге разбираются списки, циклы, функции и обработка ввода. Если Python пока в планах, посмотрите подборку книг по Python для начинающих — крестики-нолики там встречаются в первой трети почти каждой. Подросткам, которые начинают с нуля, пригодится руководство по программированию для 14-летних.

Подготовка к проекту: что нужно, чтобы сделать крестики-нолики на Python

Из инструментов достаточно установленного Python и любого редактора. Дальше выбор один: где игра будет жить — в терминале, в окне на кнопках или в графическом окне с отрисовкой. Логика во всех трёх случаях одна и та же, различается только слой, который показывает поле и ловит ход.

Каждая статья в выдаче по этому запросу ведёт свой путь и молчит про остальные: одни дают консоль, другие сразу Pygame. Ниже — сравнение по тем параметрам, которые решают на старте.

Способ Что ставить Строк кода Что умеет Кому подходит
Консоль (input, print) ничего 53 ход вводится числами «строка столбец», поле печатается текстом первый проект, разбор логики
Окно на tkinter ничего, модуль в стандартной библиотеке 40 девять кнопок, клик мышью, строка состояния тот, кому нужна «настоящая» программа с окном
Графика на Pygame pip install pygame нашего замера нет своя отрисовка линий и символов, анимация, звук тот, кто идёт дальше в геймдев

Строки посчитаны по нашим файлам без пустых строк и комментариев. Консольная версия целиком — 69 строк вместе с комментариями, версия с окном — 51.

tkinter ставить не нужно. В документации Python модуль описан так: «The tkinter package (“Tk interface”) is the standard Python interface to the Tcl/Tk GUI toolkit» — он поставляется вместе с интерпретатором на Windows и на большинстве Unix-систем. Проверить установку можно командой python -m tkinter: откроется окно с версией Tcl/Tk. У нас на Python 3.14.3 это Tcl/Tk 8.6.15.

Pygame — сторонний пакет. Официальный README на PyPI даёт одну команду: pip install pygame, а проверку — запуском встроенного примера python3 -m pygame.examples.aliens. Здесь есть нюанс, о котором стоит знать заранее: последняя версия на PyPI — pygame 2.6.1, выложена 29 сентября 2024 года, и готовые сборки в ней есть для CPython 3.6–3.13. Для 3.14 колёс в этой версии нет.

Мини-вывод: если цель — понять логику игры, берите консоль, сегодня же получите работающую программу. Окно на tkinter добавляется поверх той же логики и не требует ни одной установки.

Создание игрового поля и вывод доски

Поле — список из трёх списков по три клетки. Пустая клетка обозначается пробелом, ход — символом X или O. Сразу рядом заводим LINES: восемь троек координат, каждая из которых даёт победу. Три строки, три столбца, две диагонали — эти восемь линий понадобятся и для проверки победы, и позже для компьютера-соперника.

Пример кода: поле и печать доски

board = [[" " for _ in range(3)] for _ in range(3)]

LINES = [
    [(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1), (1, 2)], [(2, 0), (2, 1), (2, 2)],
    [(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)],
    [(0, 0), (1, 1), (2, 2)], [(0, 2), (1, 1), (2, 0)],
]


def print_board():
    print("   1 2 3")
    for i, row in enumerate(board):
        print(i + 1, " " + "|".join(row))
        if i != 2:
            print("   -+-+-")

Печать доски стоит сделать с номерами строк и столбцов по краям. Так игроку не нужно считать клетки глазами, и ход вводится ровно теми числами, которые он видит:

   1 2 3
1  X|X|O
   -+-+-
2  X|O|
   -+-+-
3  O| |

Это реальный вывод программы из нашего прогона — партия, где компьютер закрыл диагональ. Хранить поле списком списков удобно тем, что клетка адресуется парой чисел: board[row][col]. Строка нумеруется сверху вниз, столбец слева направо, обе с нуля. Отсюда растёт вторая частая ошибка новичков: игрок вводит «1 1» для верхнего левого угла, а программа ждёт «0 0». Лечится вычитанием единицы прямо при разборе ввода — этот приём в коде ниже. Мини-вывод: поле и список линий — это весь «движок» игры. Всё остальное в любой из трёх версий занимается только тем, чтобы показать поле человеку и получить от него координаты.

Почему поле [[" "] * 3] * 3 ломает игру

Самый короткий способ получить три строки по три клетки выглядит так: board = [[" "] * 3] * 3. Он печатается правильно и ломает игру на первом же ходу. Проверка занимает три строки в интерпретаторе:

board = [[" "] * 3] * 3
board[0][0] = "X"
print(board)
# [['X', ' ', ' '], ['X', ' ', ' '], ['X', ' ', ' ']]

Один ход поставил крестик в три клетки сразу. Причина описана в официальном FAQ Python — там разбирают такое же поле, только из двух столбцов: «replicating a list with * doesn’t create copies, it only creates references to the existing objects. The *3 creates a list containing 3 references to the same list of length two» (docs.python.org, раздел «How do I create a multidimensional list?»). Умножение списка копирует ссылки на один и тот же объект строки, поэтому запись в любую строку видна во всех трёх. Мы проверили это на нашей машине командой len({id(row) for row in board}): у поля из [[" "] * 3] * 3 она возвращает 1 — все три «строки» оказались одним объектом. У поля из генератора [[" " for _ in range(3)] for _ in range(3)] та же команда возвращает 3. Официальная документация предлагает тот же выход, что и в нашем коде: сначала создать список нужной длины, потом заполнить каждый элемент новым списком, либо собрать всё генератором списка. В коде игры это одна строка, которую вы уже видели выше. Признак, по которому ловушка узнаётся в чужом коде без запуска: квадратные скобки, звёздочка и число подряд для двумерной структуры. Если вы копируете крестики-нолики из статьи, ролика или ответа нейросети, это первое место, куда стоит посмотреть. Симптом на глазах пользователя выглядит мистически: игрок сходил в верхний левый угол, а игра сразу объявила победу по столбцу. Мини-вывод: поле собирайте генератором списка. Одна строка кода — и класс ошибок, который отнимает у новичка вечер, исчезает целиком.

Обработка пользовательского ввода

Ход человека приходит строкой из input, и доверять ей нельзя: там окажутся буквы, одно число вместо двух, четвёрка вместо тройки и занятая клетка. Каждый из этих случаев роняет программу с ошибкой, если не поставить проверку. Разделим обязанности: move кладёт символ в клетку и сообщает, получилось ли, а ask крутится в цикле, пока не получит корректный ход.

Пример кода: ход игрока и разбор ввода

def move(row, col, symbol):
    if board[row][col] == " ":
        board[row][col] = symbol
        return True
    print("Клетка занята")
    return False


def ask(symbol):
    while True:
        raw = input(f"Ход {symbol}, строка и столбец через пробел: ").split()
        if len(raw) != 2 or not all(x.isdigit() for x in raw):
            print("Нужны два числа от 1 до 3")
            continue
        row, col = int(raw[0]) - 1, int(raw[1]) - 1
        if row not in (0, 1, 2) or col not in (0, 1, 2):
            print("Числа только от 1 до 3")
            continue
        if move(row, col, symbol):
            return

Три проверки закрывают три разных отказа. isdigit отсекает буквы и знаки, из-за которых int() падает с ValueError. Проверка вхождения в (0, 1, 2) отсекает сразу два случая: «9 9» уронит программу через IndexError, а «0 0» после вычитания единицы даст индекс -1 — Python поймёт его как последнюю строку и молча поставит символ в противоположный угол поля. Возврат False из move отсекает повторный ход в занятую клетку. Мы прогнали эту версию с намеренно битым вводом: сначала «1 1» дважды подряд, потом буквы «а б», потом «9 9». Программа ответила «Клетка занята», «Нужны два числа от 1 до 3», «Числа только от 1 до 3» и продолжила партию, ни разу не завершившись аварийно. Отдельно про -1 при разборе: человек считает с единицы, список — с нуля. Вычитание единицы прямо в строке разбора держит это преобразование в одном месте программы. Все остальные функции работают уже с индексами и о нумерации для человека не знают. Мини-вывод: обработка ввода занимает столько же строк, сколько сама логика игры, и именно она отличает работающую программу от примера из учебника.

Логика игры: проверка на выигрыш и завершение игры

Один ход в крестиках-ноликах: что делает программа после ввода координат
Один ход в крестиках-ноликах: что делает программа после ввода координат

Победу проверяют после каждого хода. Вариант «в лоб» — по условию if на каждую из восьми линий, и так для обоих символов: шестнадцать проверок. Список LINES убирает их все: перебираем восемь троек координат и смотрим, стоят ли в них три одинаковых непустых символа.

Пример кода: победитель, ничья и главный цикл

def winner():
    for line in LINES:
        a, b, c = (board[i][j] for i, j in line)
        if a != " " and a == b == c:
            return a
    return None


def full():
    return all(cell != " " for row in board for cell in row)


def game():
    symbol = "X"
    while True:
        print_board()
        ask(symbol)
        if winner():
            print_board()
            print(f"Победили {winner()}")
            return
        if full():
            print_board()
            print("Ничья")
            return
        symbol = "O" if symbol == "X" else "X"


game()

Порядок проверок в цикле важен. Сначала победа, потом ничья: последний, девятый ход может одновременно закрыть линию и заполнить поле, и при обратном порядке игра объявит ничью там, где был выигрыш. Это ошибка, которую видно только в одной партии из многих, поэтому её легко пропустить при беглой проверке. Условие a != " " and a == b == c тоже неслучайно. Без первой половины три пустые клетки считаются линией, и программа объявляет победителем пробел на пустом поле. Собранная целиком программа — 69 строк вместе с комментариями и пустыми строками, 53 строки кода. Запускается командой python tictactoe.py в папке с файлом. Блоки из этого раздела и предыдущих идут в файл в том же порядке: поле и LINES, print_board, winner, full, move, ask, game, вызов game(). Мини-вывод: игра завершается двумя условиями, и оба должны стоять после хода в правильном порядке. Победа проверяется первой.

Как сделать крестики-нолики на Python с компьютером, который не проигрывает

Один ход бота: как минимакс выбирает клетку
Один ход бота: как минимакс выбирает клетку

Соперник-программа обычно пишется одним из двух способов. Первый — набор правил: занять центр, закрыть линию противника, иначе ходить в угол. Такой бот легко обыгрывается, потому что правила всегда чего-то не учитывают. Второй — минимакс: функция перебирает все продолжения партии до конца и выбирает ход, который даёт лучший результат при худшем ответе соперника. На поле 3×3 перебор считается мгновенно, поэтому бот получается идеальным.

Пример кода: минимакс на 16 строк

def minimax(symbol, bot):
    win = winner()
    if win:
        return (1, None) if win == bot else (-1, None)
    if full():
        return 0, None
    human = "O" if bot == "X" else "X"
    moves = []
    for i in range(3):
        for j in range(3):
            if board[i][j] == " ":
                board[i][j] = symbol
                score, _ = minimax(human if symbol == bot else bot, bot)
                board[i][j] = " "
                moves.append((score, (i, j)))
    return max(moves) if symbol == bot else min(moves)

Функция возвращает пару «оценка, ход». Победа бота — 1, поражение — -1, ничья — 0. Ключевые три строки внутри цикла: поставили пробный символ, ушли в рекурсию за оценкой, вернули клетку обратно. Поле восстанавливается на каждом шаге, поэтому отдельная копия доски не нужна. Главный цикл меняется в одном месте: когда очередь бота, вместо ask вызывается minimax.

def game_with_bot(bot="O"):
    symbol = "X"
    while True:
        print_board()
        if symbol == bot:
            score, cell = minimax(bot, bot)
            move(cell[0], cell[1], bot)
            print(f"Компьютер сходил в {cell[0] + 1} {cell[1] + 1}")
        else:
            ask(symbol)
        if winner():
            print_board()
            print(f"Победили {winner()}")
            return
        if full():
            print_board()
            print("Ничья")
            return
        symbol = "O" if symbol == "X" else "X"


game_with_bot("O")

Утверждение «бот непобедим» мы проверили полным перебором партий. Скрипт играет за человека все возможные ходы во всех возможных позициях, бот отвечает минимаксом, программа считает исходы. Результат на Python 3.14.3 под Windows:

  • бот ходит вторым (играет за O): 681 партия — 498 побед бота, 183 ничьи, 0 поражений;
  • бот ходит первым (играет за X): 101 партия — 99 побед бота, 2 ничьи, 0 поражений.

Ноль поражений в обоих прогонах — это и есть определение идеальной игры: выиграть у такого соперника нельзя, максимум ничья. Ничьих у бота-второго заметно больше, потому что первый ход даёт преимущество, и человек им пользуется.

Цена перебора тоже измерена. Первый ход на пустом поле стоит 549 946 рекурсивных вызовов и 1,5 секунды. Уже на третьем ходу партии, когда две клетки заняты, остаётся 6 812 вызовов и 0,02 секунды, а вся партия против бота-второго прошла у нас за 0,2 секунды. Отсюда практический приём: если бот ходит первым, задайте ему первый ход константой (любой угол или центр) — пауза перед стартом исчезнет, сила игры останется прежней.

Ускорить перебор можно и по-другому: добавить альфа-бета-отсечение или кешировать оценки позиций через functools.cache. Для поля 3×3 в этом нет нужды, но если вы решите растянуть игру до 4×4 или до «пять в ряд», перебор без отсечений станет неподъёмным.

Схема ниже собирает порядок вызовов внутри одного хода бота: от главного цикла до возврата оценки вверх по рекурсии.

Мини-вывод: непобедимый соперник — это 16 строк и одна замена в главном цикле. Ни одной внешней библиотеки для этого не требуется.

Создание пользовательского интерфейса: окно на tkinter

Консоль отлично показывает логику, но играть в неё скучно. Окно с девятью кнопками собирается на том же движке: вся версия с интерфейсом заняла у нас 51 строку файла, из них 40 строк кода. Устанавливать ничего не нужно: tkinter входит в стандартную библиотеку Python.

Идея простая. Девять кнопок раскладываются сеткой grid, каждая знает свои координаты и при нажатии зовёт одну функцию click(row, col). Функция ставит символ в board, меняет надпись на кнопке, проверяет победу и ничью и переключает игрока. Строка состояния под полем показывает, чей ход.

Пример кода: поле на кнопках

import tkinter as tk

# LINES и функцию winner() берём из консольной версии без изменений

board = [[" " for _ in range(3)] for _ in range(3)]
symbol = "X"

root = tk.Tk()
root.title("Крестики-нолики")
status = tk.Label(root, text="Ходят X", font=("Arial", 16))
status.grid(row=3, column=0, columnspan=3)
buttons = [[None] * 3 for _ in range(3)]


def click(row, col):
    global symbol
    if board[row][col] != " " or winner():
        return
    board[row][col] = symbol
    buttons[row][col]["text"] = symbol
    win = winner()
    if win:
        status["text"] = f"Победили {win}"
    elif all(cell != " " for line in board for cell in line):
        status["text"] = "Ничья"
    else:
        symbol = "O" if symbol == "X" else "X"
        status["text"] = f"Ходят {symbol}"


for i in range(3):
    for j in range(3):
        buttons[i][j] = tk.Button(root, text=" ", width=4, height=2,
                                  font=("Arial", 28),
                                  command=lambda r=i, c=j: click(r, c))
        buttons[i][j].grid(row=i, column=j)

root.mainloop()

Две детали здесь ловят больше всего новичков. Первая — lambda r=i, c=j: click(r, c). Если написать lambda: click(i, j), все девять кнопок будут ходить в правую нижнюю клетку: замыкание запоминает сами переменные цикла и в момент клика подставляет их последние значения. Значения по умолчанию в параметрах лямбды фиксируют координаты сразу при создании кнопки.

Вторая — global symbol. Без этой строки присваивание внутри click создаст локальную переменную, и игра застрянет на крестиках навсегда.

Мы прогнали эту версию программно: пять кликов подряд по клеткам верхней строки и центра дали ожидаемые надписи и статус «Победили X», а клик после победы уже ничего не менял. Список LINES и функция winner берутся из консольной версии без единой правки.

Мини-вывод: окно на tkinter — это тот же движок игры плюс слой кнопок. Логику из консольной версии переносить не нужно, она работает как есть.

Крестики-нолики на Pygame: что меняется

Pygame нужен, когда поле рисуется линиями и символами в графическом окне: своя картинка, анимация, звук на ход. Пакет ставится командой pip install pygame из официального README проекта на PyPI, проверка установки — запуском встроенного примера python3 -m pygame.examples.aliens.

Что меняется по сравнению с консолью:

  • появляется главный цикл кадров: события, обновление состояния, отрисовка, pygame.display.flip();
  • ход ловится событием мыши, и координаты пикселей нужно перевести в клетку;
  • поле рисуется четырьмя линиями, символы — линиями и окружностями;
  • логика победы, ничьей и смены игрока остаётся ровно той же, что в консольной версии.

Перевод пикселей в клетку — это одна строка на каждую координату. При стороне клетки 100 пикселей и поле, которое начинается в левом верхнем углу окна:

x, y = pygame.mouse.get_pos()
row, col = y // 100, x // 100

Порядок здесь обратный привычному: вертикальная координата y даёт номер строки, горизонтальная x — номер столбца. Перепутанные местами row и col — самая частая причина того, что символ появляется в зеркальной клетке.

Честное предупреждение про версии. На PyPI лежит pygame 2.6.1 от 29 сентября 2024 года, и готовые сборки в ней есть для CPython с 3.6 по 3.13. Для Python 3.14 колёс в этой версии нет, поэтому проверить графическую версию на той же машине, где гонялись остальные примеры, мы не смогли. Если вы уже на 3.14 и хотите именно Pygame — держите рядом установленный Python 3.13.

Мини-вывод: Pygame меняет только слой показа. Переносить в него имеет смысл готовую и проверенную логику из консольной версии, тогда отладка сведётся к координатам и отрисовке.

Интеграция модели ChatGPT: как попросить нейросеть написать эту игру

Крестики-нолики — задача, которую языковые модели решают уверенно: примеров в обучающих данных тысячи. Код вы получите почти наверняка. Ценность здесь в другом — знать, что в этом коде проверять. По разбору готовых решений и типовых ответов моделей набирается четыре места.

  • Как создано поле. Если там [[" "] * 3] * 3, игра сломается на первом ходу — разбор выше.
  • Есть ли проверка занятой клетки. Без неё второй игрок затирает чужой символ.
  • Порядок проверок победы и ничьей. Ничья, проверенная первой, съедает выигрыш девятым ходом.
  • Что происходит при вводе букв. Голый int(input()) роняет программу с ValueError.

Формулировка запроса влияет на результат сильнее, чем выбор модели. Рабочий шаблон: «Напиши игру крестики-нолики на Python для двух игроков в консоли. Поле — список списков, создать генератором списка. Проверку победы сделай списком из восьми линий. Ввод проверяй на буквы, на выход за границы и на занятую клетку. Без внешних библиотек, с комментариями на русском». Каждое предложение здесь закрывает один из дефектов из списка выше.

Отдельно про подсказки внутри игры через API. Вызов openai.Completion.create(engine="davinci-codex", ...), который кочует по руководствам 2023 года, сегодня не работает по двум причинам сразу, и обе зафиксированы в официальном списке отключений OpenAI. Модели семейства Codex, включая code-davinci-002, отключены 23 марта 2023 года с рекомендованной заменой gpt-4o. Эндпоинт /v1/engines, откуда взялся параметр engine, отключён ещё 3 декабря 2022 года, замена — /v1/models (страница Deprecations в документации OpenAI).

В актуальной библиотеке вызов выглядит иначе: клиент создаётся через from openai import OpenAI, а запрос уходит в client.chat.completions.create() с параметром model вместо engine. Официальный README пакета описывает Chat Completions как предыдущий стандарт генерации текста, который поддерживается бессрочно, и предлагает Responses API как текущий. Версия пакета на PyPI на момент проверки — openai 3.3.1 от 19 августа 2026 года.

Мини-вывод: нейросеть экономит время на наборе кода и не отменяет проверку. Четыре пункта из списка выше занимают минуту и ловят почти все дефекты сгенерированных решений.

Частые ошибки и как их узнать по симптому

Таблица собрана по дефектам, которые мы ловили в собственном коде во время прогонов и в чужих готовых решениях по этому запросу. Симптом виден без отладчика, причина всегда одна и та же.

Симптом на экране Причина в коде Что править
Один ход заполняет три клетки в столбце поле создано как [[" "] * 3] * 3 собрать поле генератором списка
Игра объявляет победу на пустом поле в проверке линии нет условия «клетка непустая» добавить a != " " перед сравнением
Девятый ход закрыл линию, а игра пишет «Ничья» заполненность поля проверяется раньше победы поменять два условия местами
Программа падает с ValueError int() вызван до проверки на цифры проверить ввод через isdigit
Символ появляется в противоположном углу индекс -1 после ввода «0 0» проверить диапазон после вычитания единицы
Второй игрок затирает чужой символ нет проверки занятости клетки вернуть False из функции хода
Все кнопки в окне ходят в одну клетку в lambda нет значений по умолчанию писать lambda r=i, c=j: click(r, c)
Символы в окне не меняются с X на O внутри функции нет global symbol объявить переменную глобальной

Чек-лист перед тем, как считать игру готовой: партия доигрывается до победы по строке, по столбцу и по диагонали; ничья объявляется на полном поле; ввод букв, лишних чисел и занятой клетки не роняет программу; повторный клик после конца партии ничего не меняет. Пять минут по этому списку экономят вечер отладки.

Если хочется собрать вторую игру в том же духе, но уже в браузере, посмотрите пошаговое руководство по игре «Найди пару» на HTML и JS: там та же структура — поле, состояние, проверка условия победы, — только слоем показа работает страница.

Заключение: какой способ выбрать под свою задачу

Если это первый проект после синтаксиса — консольная версия. Она собирается за вечер, показывает всю логику целиком и не требует ни одной установки. Если игру нужно кому-то показать — та же логика плюс окно на tkinter, ещё сорок строк. Если хочется соперника — минимакс, шестнадцать строк и одна замена в главном цикле. Pygame берите тогда, когда за крестиками-ноликами стоит следующая цель: собственная графика, анимация и путь в геймдев.

Что стоит сделать с готовой игрой дальше: вынести поле и правила в класс, добавить счёт серии партий, дать выбор «играть за X или за O», ограничить глубину перебора и посмотреть, как бот начинает ошибаться. Последнее наглядно показывает, откуда берётся сила бота: чем меньше ходов вперёд он смотрит, тем дальше его игра от идеальной.

Частые вопросы про крестики-нолики на Python

Сколько строк кода занимают крестики-нолики на Python?

Консольная версия для двух игроков из этой статьи — 69 строк файла, из них 53 строки кода без пустых строк и комментариев. Версия с окном на tkinter — 51 строка файла и 40 строк кода. Компьютер-соперник на минимаксе добавляет ещё 16 строк.

Нужно ли что-то устанавливать, чтобы сделать крестики-нолики на Python?

Для консольной версии и для версии с окном ставить нечего: tkinter входит в стандартную библиотеку Python и работает сразу после установки интерпретатора. Отдельная установка нужна только для графики на Pygame — команда pip install pygame.

Как сделать так, чтобы компьютер в крестиках-ноликах не проигрывал?

Нужен минимакс: функция перебирает все продолжения партии до конца и выбирает ход с лучшим результатом при худшем ответе соперника. В нашем полном переборе бот-минимакс за O сыграл 681 партию — 498 побед, 183 ничьи, 0 поражений; за X — 101 партию, 99 побед, 2 ничьи, 0 поражений.

Почему поле из [[‘ ‘] * 3] * 3 работает неправильно?

Потому что умножение списка раскладывает ссылки на один и тот же объект вместо копий: все три строки поля оказываются одним списком, и один ход ставит символ сразу в три клетки. Правильный способ — генератор списка: [[‘ ‘ for _ in range(3)] for _ in range(3)].

Можно ли попросить ChatGPT написать крестики-нолики на Python?

Можно, код обычно рабочий, но проверить в нём стоит четыре места: как создано поле, есть ли проверка занятой клетки, что проверяется раньше — победа или ничья, и что происходит при вводе букв. Готовые примеры с вызовом openai.Completion.create и параметром engine устарели: модели Codex отключены 23 марта 2023 года, эндпоинт /v1/engines — 3 декабря 2022 года.

Читайте также

3 материала