我正在尝试为3D Tic Tac Toe游戏实现Minimax与Alpha-beta剪枝。然而,看起来算法选择了次优路径。
例如,你可以通过直接穿过立方体的中间或在一个平面上横穿来获胜。但AI似乎选择了在下一步而不是当前步骤中最优的单元格。
我尝试重新创建并调整我为算法返回的启发式方法,但没有取得太大进展。不管是哪一层,它似乎都有同样的问题。
代码在这里:这里。
相关的部分是computers_move
和think_ahead
(以及’2’变体,这些只是我在尝试一种略有不同的方法)。
我希望这可能是我忽略了什么简单的东西,但据我所知,我不确定问题出在哪里。如果有人能解释这个问题,我将非常感激。
def computers_move2(self): best_score = -1000 best_move = None h = None win = False for move in self.allowed_moves: self.move(move, self.ai) if self.complete: win = True break else: h = self.think_ahead2(self.human, -1000, 1000) self.depth_count = 0 if h >= best_score: best_score = h best_move = move self.undo_move(move) else: self.undo_move(move) if not win: self.move(best_move, self.ai) self.human_turn = Truedef think_ahead2(self, player, a, b): if self.depth_count <= self.difficulty: self.depth_count += 1 if player == self.ai: h = None for move in self.allowed_moves: self.move(move, player) if self.complete: self.undo_move(move) return 1000 else: h = self.think_ahead2(self.human, a, b) if h > a: a = h self.undo_move(move) else: self.undo_move(move) if a >= b: break return a else: h = None for move in self.allowed_moves: self.move(move, player) if self.complete: self.undo_move(move) return -1000 else: h = self.think_ahead2(self.ai, a, b) if h < b: b = h self.undo_move(move) else: self.undo_move(move) if a >= b: break return b else: diff = self.check_available(self.ai) - self.check_available(self.human) return diff
回答:
结果发现我的算法似乎运行正常。问题是由我的辅助函数move
和undo_move
引起的。此外,根源问题在于我的允许移动集合。
我注意到在探索树时,computer_plays
中最外层循环的移动数量急剧减少。即使在第一次扫描中,计算机和人类玩家每对回合的允许移动数量也会从总共27个减少到20个,然后是10个,最终是5个。
结果发现临时测试的移动没有被替换。所以我用标准列表替换了集合,并在每次移动/撤销后对列表进行排序,完全解决了我的问题。