Void & Random_dude
Привет, я тут небольшую консольную крестики-нолики собрал, с базовым AI на основе мини-макс. Стараюсь, чтобы код был компактный, но при этом интересно играть. Как ты думаешь, как лучше структурировать ходы, чтобы потом было удобно подкручивать?
Проще всего представить доску как плоский список из девяти ячеек, с индексами от 0 до 8 – вот и все состояние игры. Тогда можно легко копировать этот список для рекурсии, и не нужно будет возиться с двумерным массивом. Держи отдельно список свободных ячеек, чтобы перебирать только их при генерации ходов.
Сам процесс генерации ходов вынеси в отдельную функцию, которая принимает текущий список доски и возвращает лучший индекс. Внутри нее вызывай вспомогательную функцию minimax, которая копирует доску, делает ход, меняет игрока и рекурсивно вызывает себя.
Если захочешь потом подкрутить ИИ – просто измени систему оценки или добавь ограничение глубины поиска в этой вспомогательной функции. Можно еще вынести простую функцию "сделать ход" – она применит ход к доске и проверит, не закончилась ли игра (победа/поражение/ничья), чтобы слой пользовательского интерфейса оставался чистым. Так код получится компактным, логика будет собрана в одном месте, и ты сможешь заменить minimax на что-то более сложное, не трогая остальную часть кода.
Это здравый подход. Я бы сделал состояние доски неизменным при рекурсии, может, лучше использовать кортежи вместо списков, чтобы избежать случайных изменений. Это ещё и поможет потом, если захочешь кешировать оценки. Как сейчас обработка ввода от пользователя в интерфейсе?
Просто сделай все по-простому: покажи игроку доску с цифрами от 1 до 9, чтобы он знал, куда вводить. Считывай строку через input(), убирай лишние пробелы и пробуй преобразовать ее в целое число, затем вычитай единицу, чтобы получить индекс ячейки на доске. Если число вне диапазона или ячейка уже занята, просто выведи короткое сообщение об ошибке и вернись к началу. Никаких замысловатых циклов, только while True, который завершится, как только будет введен правильный ход. Потом обнови доску и переключи игрока. В принципе, вот и все – так интерфейс будет чистым и удобным для изменений.
Звучит эффективно. Только убедись, что цикл завершится корректно, когда кто-то выиграет, а то застрянешь в нём навсегда. Может, верни какой-то статус из функции игры, чтобы главный цикл мог остановиться, когда игра закончится. Так что основная логика останется на месте, как ты и сказал.
Ну, возвращай небольшой кортеж статуса – типа (доска, игрок, победитель). Тогда основной цикл просто сможет завершиться, если победитель не None или доска заполнена. Так всё будет аккуратно, без лишних флажков, плавающих где-то.
Понял, так будет чище. Дай знать, если возникнут какие-то проблемы с логикой победы.
Всё пока нормально у меня, но если что странное вылезет с этой проверкой победы – сразу напишу. Спасибо, что предупредил!
Отлично, дай знать, если что-то изменится.