我正在尝试用简单的minimax算法解决井字游戏。简单,但应该涵盖很多语言。到目前为止我所拥有的:
该板表示为9个(未绑定)变量的数组,可设置为x
或o
。
对于所有八种变体,胜利条件基本上是:win(Player, [X1,X2,X3|_]) :- X1==Player,X2==Player,X3==Player.
等。 draw只是一个简单的检查是否所有变量都被绑定。
move子句也很简单:move(Player, [X|_], 0, 0) :- var(X), X=Player.
,同样适用于所有可能的位置(我将为以后的程序保留代码重用:))。
现在我可以通过简单的回溯生成所有可能的动作:move(Player, Board, X, Y).
基本上应该是我对minimax所需的全部(显然是一个简单的实用函数,如果计算机获胜则返回1,如果是平局则返回0) -1如果人类获胜,那很容易)。我根本不知道如何实现它,我在网上找到的所有例子都相当复杂,并没有得到很好的解释。
注意我对n ^ 2或更差的运行时行为很好 - 它实际上与效率无关。是的,我知道如何在lisp,python,java中编写minimax - 只是不知道如何将该代码“移植”到prolog。
答案 0 :(得分:2)
好吧,因为你已经拥有了你的move / 4谓词,我将从收集所有可能的动作开始:
findall(X-Y, move(Player, Board, X, Y), Moves)
然后,这只是评估每一步的问题,不是吗?为此我会写一个像board_player_move_value/4
这样的谓词,给定一个棋盘和一个给定玩家的移动,确定这个玩家的移动有多好。正是这个谓词可能取决于此阶段可能的进一步移动(对于其他玩家),这是minimax发生的地方。例如,如果这一举动赢得比赛,这是一个很好的举动。如果其他玩家可以在下一步中获胜,那么这是一个糟糕的举动等等。我会使用这个谓词来构建Value-Move形式的术语集合,使用keysort / 2对它们进行排序,然后选择其中一个动作具有最佳价值,“最佳”取决于我是否试图寻找最小化或最大化玩家的举动。