Minimax / Alpha Beta for Android Reversi Game

我需要为Android实现一个黑白棋游戏。我已经完成了游戏的所有功能,游戏可以正常运行,但问题是我没有实现AI。实际上,每次电脑走棋时,它都会选择能获得最多棋子的位置。

我决定实现alpha-beta剪枝算法。我在网上做了很多研究,但始终无法得出最终的结论如何实现。我尝试实现了一些函数,但无法达到预期的效果。

我的棋盘存储在Board类中(在这个类中,每个玩家的棋子存储在一个二维int数组中)。我附上了一个小图表(对图表的外观表示歉意)。

图表: https://docs.google.com/file/d/0Bzv8B0L32Z8lSUhKNjdXaWsza0E/edit

我需要帮助来弄清楚如何在我的实现中使用minimax算法。

到目前为止,我了解到我需要创建一个关于棋盘价值的评估函数。

为了计算棋盘的价值,我需要考虑以下元素:-空角(我的问题是,我只需要关心空角,还是我可以在当前移动中占据的角?这里有一个困惑)。-棋盘的机动性:检查在当前移动后可移动的棋子数量。-棋盘的稳定性……我知道这意味着棋盘上不能被翻转的棋子数量。-移动将为我提供的棋子数量

我计划实现一个新的BoardAI类,它将接受我的Board对象和深度作为参数。

你能告诉我一个逻辑上的思路,我应该如何实现这个AI吗?我需要一些关于在计算深度时的递归帮助,我不明白它是如何计算出最佳选择的。

谢谢你!


回答:

首先,你可以查看这段代码,这是我多年前写的跳棋AI。有趣的部分是最后一个函数(alphabeta)。(这是Python写的,但我认为你可以把它看作是伪代码)。

显然,我不能教你所有的alpha/beta理论,因为它可能有点棘手,但也许我可以给你一些实用的建议。

评估函数

这是实现一个好的min/max alpha/beta算法(以及任何其他启发式搜索算法)的关键点之一。编写一个好的启发式函数是AI开发中的艺术部分。你必须很好地了解游戏,与专业玩家交流以了解哪些棋盘特征对回答问题:这个位置对玩家X有多好?很重要。

你已经指出了像机动性、稳定性和空角这样的好特征。然而,请注意,评估函数必须快速,因为它会被调用很多次。

一个基本的评估函数是

H = f1 * w1 + f2 * w2 + ... + fn * wn

其中f是一个特征分数(例如空角的数量),w是一个相应的权重,表示特征f在总分中的重要性

找到权重值的唯一方法是:经验和实验。;)

基本算法

现在你可以开始实现算法了。第一步是理解游戏树的导航。在我的AI中,我只是使用主要棋盘作为一个黑板,AI可以尝试移动。

例如,我们从某个配置的棋盘B1开始。

步骤1:获取所有可用的移动。你必须找到所有适用于B1的给定玩家的移动。在我的代码中,这是通过self.board.all_move(player)完成的。它返回一个移动列表。

步骤2:应用移动并开始递归。假设函数返回了三个移动(M1M2M3)。

  1. 取第一个移动M1并应用它以获得新的棋盘配置B11。
  2. 在新配置上递归应用算法(查找在B11中适用的所有移动,应用它们,对结果进行递归,…)
  3. 撤销移动以恢复B1配置。
  4. 取下一个移动M2并应用它以获得新的棋盘配置B12。
  5. 依此类推。

注意:只有当所有移动都是可逆的时,才能执行步骤3。否则,你必须找到另一种解决方案,比如为每个移动分配一个新棋盘。

在代码中:

for mov in moves :    self.board.apply_action(mov)    v = max(v, self.alphabeta(alpha, beta, level - 1, self._switch_player(player), weights))    self.board.undo_last()

步骤3:停止递归。这个树非常深,所以你必须对算法设置一个搜索限制。一个简单的方法是在n级后停止迭代。例如,我从B1开始,max_level=2current_level=max_level

  1. 从B1(当前级别2)开始,我应用,例如,M1移动以获得B11。
  2. 从B11(当前级别1)开始,我应用,例如,M2移动以获得B112。
  3. B122是一个“当前级别0”的棋盘配置,所以我停止递归。我返回应用于B122的评估函数值,然后返回到级别1。

在代码中:

if level == 0 :    value = self.board.board_score(weights)    return value

现在…标准算法伪代码返回最佳叶子值。但我想知道哪个移动能带我到最佳叶子!为此,你必须找到一种方法将叶子值映射到移动。例如,你可以保存移动序列:从B1开始,序列(M1 M2 M3)将玩家带到值为-1的棋盘B123;序列(M1 M2 M2)将玩家带到值为2的棋盘B122;依此类推…然后你可以简单地选择将AI带到最佳位置的移动。

希望这对你有帮助。

编辑:关于alpha-beta的一些笔记。Alpha-Beta算法很难在没有图形示例的情况下解释。因此,我想链接我找到的最详细的alpha-beta剪枝解释之一:这个。我认为我真的无法做得比这更好。:)

关键点是:Alpha-beta剪枝为MIN-MAX添加了两个节点的界限。这些界限可以用来决定是否应该扩展一个子树。

这些界限是:

  • Alpha:可能解的最大下界。
  • Beta:可能解的最小上界。

如果在计算过程中,我们发现一种情况Beta < Alpha,我们可以停止对该子树的计算。

显然,查看前面的链接以了解它的工作原理。;)

Related Posts

L1-L2正则化的不同系数

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

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

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

f1_score metric in lightgbm

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

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

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

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

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

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

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

发表回复

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