Компьютер не проиграть в крестики-нолики
Я работаю над простой игрой кода Tic Tac Toe для C. У меня большая часть кода закончена, но я хочу, чтобы ИИ никогда не проигрывал.
Я читал об алгоритме минимакса, но я его не понимаю. Как использовать этот алгоритм, чтобы компьютер мог выигрывать или рисовать, но никогда не проигрывать?
4 ответов
путь к решению такого рода проблем - это исследование возможного будущего. Обычно (для шахмат или проектов AI) вы рассматриваете фьючерсы на определенное количество ходов вперед, но поскольку игры в крестики-нолики настолько короткие, Вы можете исследовать до конца игры.
концептуальная реализация
таким образом, вы создаете ветвящуюся структуру:
- ИИ возомнил себя делать каждый ход
- AI их воображает, что пользователь делает каждый ход они могут сделать после каждого своего хода
- тогда ИИ представляет каждый из своих следующих юридических шагов
- etc.
затем, идя от самого разветвленного конца (самого дальнего вперед во времени), игрок, чья очередь (AI или пользователь) выбирает, какое будущее лучше для него (победа, поражение или ничья) в каждой точке ветвления. Затем он передает игроку выше по дереву (ближе к настоящему); каждый раз выбирая лучшее будущее для игрока чей воображаемый поворот пока, наконец, вы не окажетесь в первой точке ветвления, где ИИ может видеть фьючерсы, которые разыгрываются в его сторону, проигрывая, рисуя и выигрывая. Он выбирает будущее, в котором он выигрывает (или если недоступен рисует).
фактической реализации
здесь этот подход хорошо работает с рекурсивной функцией. Каждый уровень функции опрашивает все свои ветви; передавая им возможное будущее и возвращает -1,0,+1; выбирая лучший результат для текущего игрока в каждой точке. Верхний уровень выбирает ход, на самом деле не зная, как каждое будущее проходит, насколько хорошо они получаются.
псевдо код
Я предполагаю, что в этом псевдо-коде +1-выигрыш AI, 0 - рисунка, -1 пользователь теряет
determineNextMove(currentStateOfBoard)
currentBestMove= null
currentBestScore= - veryLargeNumber
for each legalMove
score=getFutureScoreOfMove(stateOfBoardAfterLegalMove , AI’sMove)
if score>currentBestScore
currentBestMove=legalMove
currentBestScore=score
end
end
make currentBestMove
end
getFutureScoreOfMove(stateOfBoard, playersTurn)
if no LegalMoves
return 1 if AI wins, 0 if draw, -1 if user wins
end
if playersTurn=AI’sTurn
currentBestScore= - veryLargeNumber //this is the worst case for AI
else
currentBestScore= + veryLargeNumber //this is the worst case for Player
end
for each legalMove
score=getFutureScoreOfMove(stateOfBoardAfterLegalMove , INVERT playersTurn)
if playersTurn ==AI’sTurn AND score>currentBestScore //AI wants positive score
currentBestScore=score
end
if playersTurn ==Users’sTurn AND score<currentBestScore //user wants negative score
currentBestScore=score
end
end
return currentBestScore
end
этот псевдо-код не заботится о том, что такое начальная плата (вы называете эту функцию каждым движением AI с текущей доской) и не возвращает, какой путь займет будущее (мы не можем знать, будет ли пользователь играть оптимально, поэтому эта информация бесполезна), но он всегда будет выбирать ход, который идет к оптимальному будущему для AI.
соображения для больших проблем
в этом случае, когда вы исследуете до конца из игры очевидно, что лучшее возможное будущее (победа, поражение или ничья), но если вы только собираетесь (например) пять ходов в будущее, вам нужно будет найти какой-то способ определить это; в шахматах или черновиках партитура-самый простой способ сделать это с помощью позиции фигуры, являющейся полезным улучшением.
я делал такую штуку лет 5 назад. Я сделал исследования. В tic tac toe
Это не займет много времени, вам просто нужно подготовить шаблоны для первых двух или трех ходов.
нужно проверить как играть:
- компьютер начинается сначала.
- игрок начинает первым.
есть 9 различных стартовых позиций:
но на самом деле только 3 из них отличаются (другие повернутый.)
Поэтому после этого вы увидите, что нужно делать после некоторых конкретных ходов, я думаю, вам не нужны никакие алгоритмы в этом случае, потому что tic tac toe
окончание определяется по первым шагам. Так что в этом случае вам понадобится несколько if-else
или switch
заявления и random
генератор.
tic tac toe
принадлежат к группе игр, которые не будут потеряны, если вы знаете, как играть, поэтому для таких игр вам не нужно использовать деревья и модифицированные алгоритмы сортировки. Написать такой алгоритм вам нужно всего несколько функций:
-
CanIWin()
чтобы проверить, если компьютер имеет 2 подряд и можно выиграть. -
ShouldIBlock()
чтобы проверить, если игрок не имеет 2 в ряд и нужно заблокировать его.
эти две функции должны быть вызваны в этом порядке, если это возвращает true
вам нужно либо выиграть, либо не позволить игроку выиграть.
после этого вам нужно сделать другие расчеты для перемещения.
одна исключительная ситуация, когда компьютер начинает игру. Вам нужно выбрать ячейку, которая принадлежит наибольшему количеству разных направлений (их 8 - 3 горизонтальных, вертикальных и 2 диагональных). В таком алгоритме компьютер всегда будет выбирать центр, потому что он имеет 4 направления, вы должны добавить небольшую возможность выбрать второй лучший возможность сделать игру немного более привлекательным.
поэтому, когда вы достигнете ситуации, когда некоторые выбранные части платы и компьютера должны двигаться, вам нужно оценить каждую свободную ячейку. (если первая или вторая функция возвратила true
вы должны принять меры, прежде чем достичь этого места!!!). Поэтому, чтобы оценить ячейку, вам нужно подсчитать, сколько открытых направлений осталось на каждой ячейке, а также заблокировать хотя бы одно направление противника.
после этого у вас будет несколько возможные ячейки, чтобы поставить свою метку. Поэтому вам нужно проверить последовательность необходимых ходов, потому что у вас будет несколько вариантов, и может быть, один из них приведет вас к потере. Так что после этого вы будете иметь набор, и вы можете случайным образом выбрать ход, или выбрать тот, с большим счетом.
Я должен сказать аналогичную вещь, как сказано в начале поста. Большие игры не имеют совершенной стратегии и, скажем, шахматы во многом основаны на шаблонах, но и на стратегии передового мышления (для такая вещь использует Патрисия Боре). Так что для подведения итогов вам не нужны сложные алгоритмы, всего несколько функций, чтобы подсчитать, сколько вы выигрываете, а противник проигрывает с ходу.
сделайте вспомогательную программу для прогнозирования случаев, с которыми пользователь может выиграть. Затем вы можете сказать своему ИИ, чтобы сделать то, что пользователь должен сделать, чтобы выиграть.