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