You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 16:24:04