我正在编写一个简单的Connect-K AI(无剪枝,仅4层深度)。我想知道有什么最佳启发式方法可以快速计算出来。
我希望找到比我目前使用的更好的方法:
def eval(board, player) connections = 0 magnitude = 0 for x in range(0, self.boardW(board)): for y in range(0, self.boardH(board)): if(self.get_player(board, x, y) == player): #假设x和y在边界内 temp = 1 # 继续在这个方向上检查以找到temp的最大值 if (magnitude < temp): magnitude = temp if(self.get_player(board, x, y) == player): connection += 1 ........ return connection**2 + magnitude**2
基本上,这应该返回棋盘上任何位置与其相邻位置的最大连接数,加上在8个方向上(上、下、左、右、左上、左下、…)的连续项数。
我的k值将大于4;因此,我无法进行详尽的树搜索。
回答:
在这种情况下,极小极大搜索可能很有用,可以与简化的蒙特卡洛树搜索(MCTS)结合使用。基本上,更深的递归可以让你到达更多的游戏终态。通过分析在这些情况下哪位玩家获胜,你可以更好地理解某一行动的价值。
极小极大方法对于两名玩家之间的游戏非常有用,并且广泛用于此类棋盘游戏。MCTS可能有点过度,但其基本思想是用随机、更深的搜索来替代广泛的搜索。例如,与其有20的分支因子,仅有5层的递归(20^5 = 320万),你可以随机选择10个分支,并进行6-7步递归,计算量相同。
在类似项目(跳棋AI)中取得良好效果的方法是,在递归的更深处减少分支因子。通过定义最大分支(在递归步骤中要探索的最大分支数),让这个数字大于顶层的典型分支,并在递归的更深处减少到一个更小的数字(很快就减少到5-10,在底部减少到1-3)。这样,你可以兼顾两全。你探索了所有迫在眉睫的移动,同时也获得了很多关于它们如何影响游戏后期的信息。
快速总结:使用MCTS和极小极大,你可以找到很多终态。如果对手获胜,给它一个大的负分。如果你获胜,给它一个大的正分。如果两者都没有,你可以给它一个0,或者使用你在问题中展示的函数。让父游戏状态的分数依赖于其子节点的分数,通过使用极小极大算法来实现。