我决定写一个小程序来解决井字棋问题,以尝试一些对于这个简单游戏的剪枝技巧的效果。使用minimax解决所有可能的游戏,完整的游戏树仅有 549,946 种可能。利用alpha-beta剪枝技术,评估所需的状态数量减少到 18,297。然后我应用置换表将数量降至 2,592。现在我想看看这个数字能否再次降低。
我想要应用的下一个改进是战略缩减。基本思路是将具有等效战略价值的状态合并。例如,在第一步时,如果X先走,选择其中一个角落与选择另一个角落在战略上没有区别(假设你的对手会最优地行动)。在相同情况下,墙中央的位置也是如此,并且中心位置也非常重要。通过只保留重要状态,您只需要评估三个状态,而不是九个状态,以进行第一步操作。由于这种剪枝技术能够减少游戏树顶部附近的状态,因此该技术应该非常有用。这个想法来自CMU的一个小组创建的GameShrink方法,但我试图避免编写通用表单,只是做必要的工作将该技术应用于井字棋。
为了实现这一点,我修改了我的哈希函数(用于置换表),枚举所有具有战略等效性的位置(使用旋转和翻转功能),并且只返回每个棋盘的最低值。不幸的是,现在我的程序认为X可以在先手情况下从空棋盘中用5步获胜。经过长时间的调试后,显然对于最低重要移动,程序总是返回它的移动(我将上次移动存储在置换表中作为我的状态的一部分)。是否有更好的方法来添加此功能,或者已经完成的操作中有适用于当前情况的确定正确移动的简单方法?