Python国际象棋引擎Negamax算法异常:主动弃子等错误走棋问题排查
国际象棋Negamax引擎走棋逻辑异常修复
问题表现
基于Python chess库开发的极简国际象棋引擎固定执黑,参考Negamax算法实现、4层搜索深度,仅使用子力价值作为评估函数,但会出现主动弃兵等明显不符合子力最优的走法,问题点集中在Negamax递归逻辑、终局判断、走法存储三个部分,具体问题和修复方案如下:
核心错误点
- 全局走法存储字典未初始化且存在覆盖问题:
scoreMovePair是全局字典,每次搜索前没有清空,上次搜索的残留数据会干扰本次结果;同时多个路径返回相同分值时,新值会覆盖旧值,无法保证存储的是根节点最优首步。 - 递归终止条件顺序错误:原代码先判断搜索深度是否到4层,再判断是否将死,会导致已经触发将死的局面反而走子力评估,忽略了将死是最高优先级的终局状态。
- 终局返回值视角错误:将死的返回值没有适配Negamax的当前玩家视角,
1000*colorMap(board.turn)的计算逻辑和递归层的color参数脱节,导致分值符号完全错位。 - 代码转义错误:原代码里的
a >= b是HTML转义错误,实际应为a >= b,同时主函数里global scoreMovepair大小写和全局变量scoreMovePair不一致,全局变量声明无效。 - 子力价值计算错误:原
pieceMap函数对国王的返回值为6,国王不存在被吃的可能,不应计入子力价值统计。
修复后完整代码
import chess import time from time import sleep from chessboard import display def colorMap(color): if color == True: return -1 return 1 def pieceMap(pieceNum): if pieceNum == 1: return 1 elif pieceNum == 2: return 3 elif pieceNum == 3: return 3 elif pieceNum == 4: return 5 elif pieceNum == 5: return 9 return 0 # 国王不计入子力价值 def posEval(board): score = 0 for i in range(0, 64): piece = board.piece_at(i) if piece != None: score += pieceMap(piece.piece_type)*colorMap(piece.color) return score def search(board, level, a, b, color, best_move): # 优先判断终局状态 if board.is_checkmate(): return 10000 * color if board.is_stalemate() or board.is_insufficient_material(): return 0 if level == 4: return posEval(board) * color value = -100000 for move in board.legal_moves: board.push(move) current_value = -search(board, level + 1, -b, -a, -color, best_move) board.pop() if current_value > value: value = current_value # 仅根节点记录最优走法 if level == 0: best_move[0] = move a = max(a, value) if a >= b: break return value def main(): board = chess.Board() display.start(board.fen()) while not display.checkForQuit(): validMoves = list(board.legal_moves) if len(validMoves) == 0: break move = input("Enter move: ") t0 = time.time() move = str(move) # 兼容UCI和SAN两种走法输入格式 try: myMove = chess.Move.from_uci(move) except: try: myMove = board.parse_san(move) except: print("非法走法,请重新输入") continue if myMove in validMoves: board.push(myMove) best_move = [None] value = search(board, 0, -100000, 100000, 1, best_move) print(f"最优走法分值:{value}") board.push(best_move[0]) print(board.fen()) display.update(board.fen()) sleep(1) t1 = time.time() print(f"搜索耗时:{t1-t0}s") else: print("非法走法,请重新输入") display.terminate() if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

