具有 Minimax 和 Alpha-beta 修剪的 3D Tic Tac Toe 选择次优移动
3D Tic Tac Toe with Minimax & Alpha-beta pruning picks sub-optimal moves
我正在尝试为 3D 井字游戏实现带有 Alpha-beta 剪枝的 Minimax。但是,该算法似乎选择了次优路径。
例如,您只需 运行 直接穿过立方体的中间或穿过一块棋盘即可获胜。 AI 似乎会选择在 下一个 回合而不是当前回合最佳的单元格。
我已经尝试重新创建和使用启发式算法 I return 但我没有取得太大进展。不管是哪一层,它似乎都有同样的问题。
密码是here.
相关部分是 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 = True
def 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 个。
原来临时测试的动作没有被替换。因此,我将集合换成标准列表,并在每个 move/undo 之后对列表进行排序,并完全解决了我的问题。
我正在尝试为 3D 井字游戏实现带有 Alpha-beta 剪枝的 Minimax。但是,该算法似乎选择了次优路径。
例如,您只需 运行 直接穿过立方体的中间或穿过一块棋盘即可获胜。 AI 似乎会选择在 下一个 回合而不是当前回合最佳的单元格。
我已经尝试重新创建和使用启发式算法 I return 但我没有取得太大进展。不管是哪一层,它似乎都有同样的问题。
密码是here.
相关部分是 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 = True
def 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 个。
原来临时测试的动作没有被替换。因此,我将集合换成标准列表,并在每个 move/undo 之后对列表进行排序,并完全解决了我的问题。