【问题标题】:TicTacToe strategic reduction井字游戏战略缩减
【发布时间】:2011-02-28 16:13:49
【问题描述】:

我决定写一个解决井字游戏的小程序,以便在一个小游戏上尝试一些剪枝技术的效果。使用 minimax 解决它的完整博弈树最终只有 549,946 个可能的博弈。通过 alpha-beta 剪枝,需要评估的状态数量减少到 18,297 个。然后我应用了一个转置表,将数字降低到 2,592。现在我想看看这个数字能降到多低。

我要应用的下一个增强功能是战略性缩减。其基本思想是结合具有同等战略价值的国家。例如,在第一步中,如果 X 先下,那么选择一个角而不是另一个角在策略上没有什么不同(假设你的对手打得最好)。在同样的情况下,板壁的中心也是如此,中心也很重要。通过仅减少到重要状态,您最终只会在第一步中评估 3 个状态而不是 9 个。这种技术应该非常有用,因为它会修剪靠近博弈树顶部的状态。这个想法来自 CMU 的一个小组创建的 GameShrink 方法,只是我试图避免编写通用形式,而只是做将技术应用于井字游戏所需的操作。

为了实现这一点,我修改了我的哈希函数(用于转置表)以枚举所有策略上等效的位置(使用旋转和翻转函数),并且只返回每个棋盘的最低值。不幸的是,现在我的程序认为 X 在先走时可以从空棋盘中强制 5 步获胜。经过长时间的调试后,我发现程序总是返回具有最低战略意义的移动(我将最后一个移动存储在换位表中作为我的状态的一部分)。有没有更好的方法可以添加此功能,或者有一种简单的方法来确定适用于当前情况的正确移动方式以及我已经完成的操作?

【问题讨论】:

  • 这是一个有趣的问题,据我所知,所有其他浮动实现也使用“检查每个方格”方法,而不是构建决策树。我不确定这是否可以称为 A.I.虽然:s
  • @Codesleuth 小心术语——决策树是一种机器学习技术,不适用于此处
  • @Shaggy Frog:如果你说的是神经网络,那不是我的意思。
  • @Codesleuth 决策树不是神经网络,但它们都是机器学习算法的形式。此外,这里描述的启发式搜索当然是人工智能的一种形式。我建议您花一些时间研究该主题。
  • @Shaggy Frog:什么?你为什么争论这个?我的建议是这可能不是人工智能。是个人观点,因为我不认为预先确定的决策表或增量搜索足够先进以成为智能。我得出这个结论是因为我已经研究过这个话题。

标签: search artificial-intelligence tic-tac-toe


【解决方案1】:

出于好奇,我编写了一个程序来构建一个完整的转置表来玩游戏,而无需任何额外的逻辑。考虑到 8 种对称性,并假设计算机 (X) 启动并运行确定性,则只需要 49 个表条目!

1 个空板条目

2 件 5 个条目

4 件 21 个条目

6 件 18 个条目

8 件 4 个条目

【讨论】:

  • 这太棒了!你可以让它处理第二个吗?
  • @NickLarsen 当然。另外,如果计算机从中心开始而不是先打角球(同时仍然打“最佳比赛”并且永不输球),桌子会变得更小......我现在正在尝试分析确定(并模拟)最小换位表在其他游戏中“最佳播放”所需的大小,假设计算机播放确定性
  • 10 年后,这太棒了。
  • “确定性”表示计算机每次对每个特定板配置的响应都完全相同。
  • 现在我得到了一个 N = 37 的解决方案,请参见此处:stackoverflow.com/a/65800312/502187 但我正在存储带有奇数块的板。
【解决方案2】:

您可能想尝试使用蒙特卡罗模拟来解决井字游戏。如果其中一个(或两个)玩家是机器玩家,它可以简单地使用以下步骤(这个想法来自 coursera 课程 Principles of Computing 1 中的一个迷你项目,这是 RICE 大学教授的计算机专业基础知识的一部分。):

每个机器玩家都应该使用蒙特卡罗模拟从给定的井字棋棋盘位置选择下一步。总的想法是从位置开始玩一系列随机移动的游戏,然后使用这些游戏的结果来计算一个好的移动。

当一个特定的机器玩家赢得这些随机游戏之一时,它想要偏爱它所玩的方格(希望选择获胜的动作)并避开对手所玩的方格。相反,当它输掉其中一场随机游戏时,它想要偏向对手所玩的方格(以阻止其对手)并避开它所玩的方格。

简而言之,获胜玩家在这些随机游戏中所玩的方格应该比失败者所玩的方格更受青睐。在这种情况下,两个玩家都是机器玩家。

以下动画显示了 2 名机器玩家之间的游戏(以 平局 结束),在每个棋盘状态下使用 10 次 MC 试验来确定下一步行动。

它显示了每个机器玩家如何通过使用蒙特卡罗模拟来学习玩游戏,在棋盘的每个状态下进行 10 次试验(少量试验),分数显示在 右下角 每个方格的每个玩家在其对应的回合中使用,以选择其下一步行动(根据模拟结果,较亮的单元格代表当前玩家更好的行动)。

这里是我的blog,了解更多详情。

【讨论】:

    【解决方案3】:

    我的直觉是你使用太大的锤子来解决这个问题。 9 个点中的每一个只能有两个标签之一:X 或 O 或空。那么您最多有 3^9 = 19,683 个独特的板。由于每块板有 3 个等效反射,因此您实际上只有 3^9 / 4 ~ 5k 块板。您可以通过丢弃无效的板来减少这种情况(如果它们同时有一行 X 和一行 O)。

    因此,使用紧凑的表示形式,您将需要不到 10kb 的内存来枚举所有内容。我会评估整个游戏图并将其存储在内存中。

    我们可以通过自下而上而不是自上而下计算极大极小值(如在您的树搜索方法中),用其真正的极小极大值标记每块棋盘。这是一个总体大纲:我们计算所有独特棋盘的极小极大值,并在游戏开始前首先标记它们。要进行极小极大走法,您只需查看当前状态之后的棋盘,然后选择具有最佳极小极大值的走法。

    以下是执行初始标记的方法。生成所有有效的独特板,抛出反射。现在我们开始标记具有最多移动 (9) 的棋盘,并向下迭代到具有最少移动 (0) 的棋盘。用胜利、失败和平局标记任何残局板。对于轮到 X 移动的任何非残局棋盘: 1) 如果存在 X 获胜的后续棋盘,则将此棋盘标记为获胜; 2) 如果在后续棋盘中没有获胜但有平局,则将此棋盘标记为平局; 3) 如果在随后的棋盘中没有获胜和没有平局,则将此棋盘标记为失败。轮到 O 时的逻辑类似。

    就实现而言,由于状态空间很小,我会将“如果存在”逻辑编码为所有 5k 状态的简单循环。但是,如果您真的想为 渐近 运行时间调整它,您将构建一个有向图,其中哪些棋盘状态导致哪些其他棋盘状态,并通过在边缘。

    【讨论】:

    • 我会投票赞成这个作为答案,但你错过了使用特定锤子的练习要点。不过,您是对的,没有 549,946 种可能的井字游戏(即使包括未选择的游戏,也没有那么多可能的状态,更不用说游戏了)。这个想法很有趣,但发布者需要先弄清楚可能发生的事情的细节。从 3x3 网格的 512 种可能的结束状态开始,消除不可能的情况,然后然后处理等效的移动和状态。
    • 谢谢,也许我可以为快速算法计算出更多细节。我理解你关于这个练习的观点,但我建议使用一种不能很好地解决特定问题的技术没有什么价值,尤其是当替代方案不仅更便宜、更简单、更快时。使用不适合问题的技术也可能会限制您对该技术的了解(即在现实世界中,如果您一直使用替代方法,您将从练习中获得哪些可重用的知识/经验?)
    • 我非常感谢这个答案,我有几个问题和几点。如果你在你的状态中包含移动历史,就像基本的 minimax 隐含的那样,有 549,946 个可能的可达状态在棋盘填满或任一玩家连续 3 次时终止,如果你允许游戏继续进行,则更多在非空棋盘上找到赢家,尽管我没有。我确实同意额外的工作是毫无价值的,显然基本的极小极大即使是微不足道的游戏也需要付出巨大的努力,但这并不妨碍锻炼。
    • 使用转置表应该将树的大小减少到只有在游戏中可能达到的状态数,而不管历史如何,这很好,因为历史不会影响井字游戏中的可用移动和因此对最优移动没有影响。仅使用转置表,我的小程序在井字游戏中显示了 5478 个可达状态,我认为这对我的规则是正确的。
    • 由于棋盘点可以是空白的,因此可能的状态数是 3^9 = 19683。意识到有效的、可达状态的 X 数与 O 数相同或 X 比 O 多 1由于我的规则,很多州都无法到达,5478 似乎是合理的。 2^9 仅代表叶子节点,用于填充板上的每个位置,没有特定的顺序。
    【解决方案4】:

    关于这一点有很多可以说的,但我在这里只给出一个可以减小树大小的提示:Matt Ginsberg 开发了一种称为 Partition Search 的方法,它可以在板上减少等效性。它在 Bridge 中运行良好,他以井字游戏为例。

    【讨论】:

      【解决方案5】:

      当您考虑反射和旋转时,您就走在了正确的轨道上。但是,您将其应用到错误的地方。不要将它添加到你的转置表或转置表代码中——将它放在移动生成函数中,以便从一开始就消除逻辑上等价的状态。

      使您的转置表和相关代码尽可能小且高效。

      【讨论】:

      • 这很有帮助。有趣的是,一旦我这样做了,我就遇到了各种各样的问题。事实证明,我专注于提前解决游戏,并尝试从以前评估过的位置开始比赛,这些位置有时没有被评估过。一旦我修改它以重新运行每个动作的搜索,所有问题都消失了。现在我开始介绍订购技术。您是否知道订购出版物的任何好的举措?
      • 不是临时的,因为移动排序通常与域密切相关。在搜索树的顶部附近,它可能非常重要,但在靠近底部时,它可能会花费更多时间而不是在节点扩展中节省的时间。考虑只在从底部开始 >=3 层的节点处进行。一般而言,一件便宜又容易的事情是对每个节点进行深度 1 搜索,然后根据它进行排序,这有助于您利用现有的评估功能。
      【解决方案6】:

      您需要返回(反向)转置以及最低值位置。这样,您可以将反向换位应用于预期的移动以获得下一个位置。

      【讨论】:

      • 这是我过去发现的一种非常有价值的技术,特别是对于非常复杂的游戏,比如我在玩扑克时,但感觉对于这个简单的事情来说,付出的努力比值得的要多项目。我也从未编写过通用形式的状态映射器。你知道吗?将来可能是一个不错的项目。
      【解决方案7】:

      为什么需要使转置表可变?最好的举动不取决于历史。

      【讨论】:

        猜你喜欢
        • 2015-06-12
        • 1970-01-01
        • 2015-01-08
        • 1970-01-01
        • 2014-04-12
        • 2015-12-06
        相关资源
        最近更新 更多