1 最大最小策略
MAX层,希望在下一层子树节点中取最大值(从本方视角);MIN层希望在下一层子树节点中选择最小值(对方视角)。
因此,通过最大化最小化策略来选择最优动作.
2 裁剪策略
在进行深度优先搜索时,记录已知的最大值alpha(本方希望走这步的分数最大)和最小值beta(对方希望走这步分数最小)。
因此,MIN层进行更新beta值;MAX层更新alpha值。
当在MIN层,子树的值(子树所在层为MAX层)比父节点的beta值还大,则不需要进行搜索了。
当在MAX层,子树的值(子树所在层在MIN层)比父节点的alpha值还小,则不需要进行搜索了。
在实现的时候,统一MIN层和MAX层,注意到子节点的β值是 父节点的 -α值。
使用相同的选择最有利位置的条件:MAX层 和 MIN层 都选择最大的评分;
相同的剪枝判断条件:MAX层 和 MIN层 都在 α值 ≥ β值时 ,剪掉该节点的所有未搜索子节点。
这里,alpha值初始化是-∞;beta初始化的值时+∞。
int AlphaBeta(int depth, int alpha, int beta) {
if (depth == 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = -AlphaBeta(depth - 1, -beta, -alpha);
UnmakeMove();
if (val >= beta) {
return beta;
}
if (val > alpha) {
alpha = val;
}
}
return alpha;
}
val = AlphaBeta(5, -INFINITY, INFINITY);
如果某个着法的结果大于Alpha但小于Beta,那么这个着法就是走棋一方可以考虑走的,因为比alpha值小,比beta大,本方和对方都不会走这步。
这里就可以获得,深度优先搜索时,走一步的alpha值。
def __search(self, board, turn, depth, alpha = SCORE_MIN, beta = SCORE_MAX):
score = self.evaluate(board, turn)
if depth <= 0 or abs(score) >= SCORE_FIVE:
return score
moves = self.genmove(board, turn)
bestmove = None
self.alpha += len(moves)
# if there are no moves, just return the score
if len(moves) == 0:
return score
for _, x, y in moves:
board[y][x] = turn
if turn == MAP_ENTRY_TYPE.MAP_PLAYER_ONE:
op_turn = MAP_ENTRY_TYPE.MAP_PLAYER_TWO
else:
op_turn = MAP_ENTRY_TYPE.MAP_PLAYER_ONE
score = - self.__search(board, op_turn, depth - 1, -beta, -alpha)
board[y][x] = 0
self.belta += 1
# alpha/beta pruning
if score > alpha:
alpha = score
bestmove = (x, y)
if alpha >= beta:
break
if depth == self.maxdepth and bestmove:
self.bestmove = bestmove
return alpha
————————————————
版权声明:本文为CSDN博主「marble_xu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/marble_xu/article/details/90647361
参考: