我实现了一个带有alpha-beta剪枝的极小极大算法。为了找到最佳走法,我通过rootAlphaBeta
函数调用了alpha-beta算法。然而,在rootAlphaBeta
函数中,我发现了非常奇怪的行为。当我以4为ply
值调用rootAlphaBeta
函数时,它大约进行了20,000次调用,但当我直接调用alphaBeta
函数时,仅进行了大约2000次调用。我似乎找不到问题所在,因为调用次数应该是相同的。
两种算法最终找到的走法应该是相同的,对吗?我认为是这样,至少走法的得分是相同的,我无法知道直接调用alphaBeta
函数而不通过rootAlphaBeta
时,它选择的走法是什么。
def alphaBeta(self, board, rules, alpha, beta, ply, player):
"""实现带有alpha-beta剪枝的极小极大算法。"""
if ply == 0:
return self.positionEvaluation(board, rules, player)
move_list = board.generateMoves(rules, player)
for move in move_list:
board.makeMove(move, player)
current_eval = -self.alphaBeta(board, rules, -beta, -alpha, ply - 1,
board.getOtherPlayer(player))
board.unmakeMove(move, player)
if current_eval >= beta:
return beta
if current_eval > alpha:
alpha = current_eval
return alpha
def rootAlphaBeta(self, board, rules, ply, player):
"""调用alphaBeta函数。返回给定ply值下玩家的最佳走法。"""
best_move = None
max_eval = float('-infinity')
move_list = board.generateMoves(rules, player)
for move in move_list:
board.makeMove(move, player)
current_eval = -self.alphaBeta(board, rules, float('-infinity'),
float('infinity'), ply - 1,
board.getOtherPlayer(player))
board.unmakeMove(move, player)
if current_eval > max_eval:
max_eval = current_eval
best_move = move
return best_move
回答:
你的rootAlphaBeta
函数没有更新alpha
值。它对所有子节点都使用了完整的范围(-inf, inf),而实际上它本可以缩小除第一个子节点之外的所有子节点的范围。这将阻止一些对最终得分没有影响的分支被剪枝,从而增加了节点数量。