【问题标题】:minimax for tic-tac-toe井字游戏的极小极大
【发布时间】:2012-04-20 14:46:04
【问题描述】:

我正在尝试使用简单的极小极大算法来解决井字游戏。简单,但应该涵盖很多语言。到目前为止我所拥有的:

板表示为 9 个(未绑定)变量的数组,这些变量设置为 xo

那么获胜条件基本上是: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). 这基本上应该是我对极小极大所需的全部(显然是一个简单的实用函数,如果计算机获胜则返回 1,如果平局则返回 0 和 -1如果人类获胜,那很容易)。我只是不知道如何实现它,我在网上找到的所有示例都相当复杂,没有很好的解释。

请注意,我对 n^2 或更差的运行时行为很好 - 这实际上与效率无关。是的,我确实知道如何在 lisp、python、java 中编写 minimax - 只是不知道如何将该代码“移植”到 prolog。

【问题讨论】:

标签: algorithm prolog


【解决方案1】:

好吧,既然你已经有了 move/4 谓词,我将从收集所有可能的移动开始:

findall(X-Y, move(Player, Board, X, Y), Moves)

然后这只是评估每一步的问题,不是吗?为此,我会写一个像board_player_move_value/4 这样的谓词,给定一个棋盘和一个给定玩家的移动,确定该移动对这个玩家有多好。正是这个谓词可能取决于在这个阶段(对于其他玩家)可能的进一步移动,这就是极小极大发生的地方。例如,如果这一招赢得了比赛,那就是一个好招。如果另一个玩家可以在下一步中获胜,那么这是一个糟糕的举动等等。我会使用这个谓词来构建一个 Value-Move 形式的术语集合,使用 keysort/2 对它们进行排序,然后选择其中一个动作具有最佳价值,其中“最佳”取决于我是否正在尝试为最小化或最大化玩家找到移动。

【讨论】:

  • 啊,所以 findall 返回了所有可能移动的列表,这已经很有帮助了。我的问题是我不知道如何实现最大减少。基本上在 lisp 中,最大值看起来像 (if (terminalp state) (utility state)(reduce #'max (mapcar #'min-value (successors state)))) (我希望即使没有深入的 lisp 知识也能有点清楚,只是最简单的 minimax 版本,没有任何启发式)。 if 的基本情况很简单,(successors state) 部分与 findall 一起使用,但我只是不知道如何在该列表上进行映射和减少。
  • 您可以轻松地将每个 Lisp 函数转换为 Prolog 谓词,并带有一个附加参数来保存函数的返回值,因此代码看起来类似于: ( terminal(State) -> state_utility(State, Utility) ) ; state_successors(State, Succs), maplist(min_value, Succs, Mins), max_list(Mins, Utility))。这是可能的,因为函数只是关系的一种特殊情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多