使用评估函数返回的值从minimax中找到合适的移动

所以,我正在尝试为一个简单的游戏实现minimax算法,这个游戏有两个玩家,每个玩家有两个皇后。总共有4个皇后在一个7×7的棋盘上。因此,每个回合,玩家需要将他的两个皇后移动到新的位置。

我尝试通过递归minimax函数来找到minmax,如下所示。基本情况应该返回一个整数,这是评估函数返回的分数。但是,当我遍历到叶子节点后,我如何找到minmax呢?

这个函数应该能够返回queen1和queen2的最佳移动。但我不明白如何从叶子节点的值中找到min和max。我不知道如何传播这些值。我实在无法理解/想象这一点。


回答:

从你的问题中,我感觉到你大部分的困惑在于,函数应该返回什么?是返回一个分数,还是一个移动?一般来说,你实际上应该将这件事分成两个独立的函数;

  1. 一个minimax()函数,应该看起来大致像你目前所拥有的(我没有详细检查正确性,可能有一些小错误,但总体上至少看起来接近正确)。这个函数只应该返回一个整数/浮点数/其他类型的值,即节点的值(如果已经足够深,则定义为评估函数的值,或者所有子节点的最大值/最小值(取决于哪位玩家将要移动))。

  2. 类似于choose_move()的函数,应该返回一个要执行的移动。它应该通过调用minimax()来为所有子节点计算,然后返回导致子节点值最大的移动(建议随机打破平局)。

注意:你的代码中似乎也有一些错误,看起来返回得太频繁了。例如,对于最大化玩家,你在第一次看到score > best_val时就已经返回了,而你应该继续循环遍历所有其他移动,以确定是否有任何移动可能有更高的分数。

对于最小化玩家的代码应该与最大化玩家的代码更加“对称”,现在看起来差异太大。


编辑:为了修复分数返回过快的问题,这行代码:

return best_move_q_1, best_move_q_2, score

应该简单地移到所有可能动作的循环之外。想法是,遍历所有动作,评估它们(通过递归minimax调用),然后返回与最佳移动相关的移动和分数。这意味着它必须在动作循环之外,你不能在仍在这些循环内时就返回,因为那样你还没有完成所有动作的循环,可能会错过更好的选择。

在这种情况下,做法是简单地将那行代码向左移动4个缩进。它应该直接在for move_q_1 in moves_1:行下方(在同一缩进级别),因为那是遍历所有移动的循环开始的地方。

然后,那行代码还应该更改为返回best_val(所有子节点中最佳分数),而不是score(最后一个子节点的评估)。

之后,not maximizing_player情况的代码应该更改为与上面其他情况的代码更加相似。

然后,我刚刚注意到另一件事;接近顶部,你决定评估depth == 0(或者游戏状态是否为终止状态)。然而,在递归调用中,你总是增加传递的深度级别。这看起来很奇怪(除非你在第一次调用时传递了一个负深度?)。你可能想要做以下之一:

  1. 在第一次调用minimax时,传递你想要搜索的最大深度(例如,3或5或其他)。然后,在递归调用minimax时,总是递减它,而不是递增(以确保它最终达到depth=0的点进行评估)。

  2. 不是在depth == 0时进行评估,而是在depth == max_depth时进行评估,其中max_depth再次是一个常数,如3或5或其他。然后,你对minimax的初始调用应该有depth=0

我没有详细检查是否还有其他错误,所以如果你觉得这还不够,请随时告诉我(或者尝试将你的代码与算法在其他地方的伪代码进行比较,看看差异在哪里,以及你是否能理解它们)。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注