我有一个学校项目是用 C++ 编写日期游戏(示例参见 http://www.cut-the-knot.org/Curriculum/Games/Date.shtml),其中电脑玩家必须实现带有 alpha-beta 剪枝的 Minimax 算法。 到目前为止,我理解该算法背后的目标是最大化潜在收益,同时假设对手会最小化这些收益。
但是,我阅读的所有资源都没有帮助我理解如何设计评估函数,minimax 算法的所有决策都基于此函数。 所有示例都将任意数字分配给叶节点,但是,我需要真正为这些节点分配有意义的值。
直觉告诉我,获胜的叶节点应该是 +1,失败的叶节点应该是 -1,但是中间节点如何评估呢?
任何帮助都将不胜感激。
回答:
最基本的 minimax 仅评估叶节点,标记胜负和平局,并将这些值向上传递到树中,以确定中间节点的值。 如果游戏树难以处理,则需要将截止深度用作 minimax 函数的附加参数。 一旦达到深度,就需要为不完整状态运行某种评估函数。
minimax 搜索中的大多数评估函数都是特定于领域的,因此很难找到针对你的特定游戏的帮助。 记住,评估需要返回特定玩家(通常是 max,但不是在使用 negamax 实现时)赢得该位置的预期百分比。 几乎任何研究较少的游戏都将与另一个研究更多的游戏非常相似。 这一点与游戏 捡棍子 密切相关。 仅使用 minimax 和 alpha beta,我估计游戏是可处理的。
如果必须为非终端位置创建评估函数,这里有一些关于棍子游戏的分析的帮助,你可以决定它是否对日期游戏有用。
首先寻找一种通过查看终端位置和所有可能导致该位置的移动来强制产生结果的方法。 在棍子游戏中,终端位置是在最后一次移动中剩下 3 根或更少的棍子。 因此,紧随该终端位置的位置是给你的对手留下 4 根棍子。 现在,目标是让你的对手无论如何都剩下 4 根棍子,这可以通过给你留下 5、6 或 7 根棍子来完成,你希望迫使你的对手让你处于这些位置之一。 为了让你处于 5、6 或 7 的位置,你的对手需要处于 8 的位置。 继续这种逻辑,很快就会出现一种模式。 总是让你的对手拥有一个可以被 4 整除的数字,你就赢了,否则,你就输了。
这是一个相当简单的游戏,但确定启发式的方法很重要,因为它可以直接应用于你的任务。 由于最后一个移动的人先走,并且一次只能更改 1 个日期属性,因此你知道为了获胜,需要剩下正好 2 个移动……等等。
祝你好运,让我们知道你最终做了什么。