尽管深度为 3,国际象棋 AI 仍无法评估超过 1 步的进展

问题描述 投票:0回答:1

我一直在研究国际象棋机器人,并且已经完成了极小极大函数的草稿,但它似乎完全忽略了第一步之后的任何最小化或最大化。为了让它决定导致最佳评估的移动,我使用了一个称为“move”的结构,它有一个名为“algebraicMove”的成员字符串(它存储实际的移动)和一个成员double 称为“eval”,它存储移动的评估。这是函数:

AI_Player::move AI_Player::chooseMoveHelper(int depth, std::string maximizingPlayer, Board currBoard, std::string moveMadeToGetHere /*null move*/) { //the "actual AI" algorithm
    //initializing current node -- O(1)
    move currentNode{moveMadeToGetHere, currBoard.evaluatePosition()};

    //creting a copy of the board so we don't mess up the actual board
    Board boardCpy = currBoard;

    //determine remaining pieces based on color -- O(1)
    std::vector<Board::square> piecesRemaining;
    maximizingPlayer == "white" ? piecesRemaining = boardCpy.piecesLeft("white") : piecesRemaining = boardCpy.piecesLeft("black");

    //base case -- O(1)
    if (depth == 0 /*OR checkmate, which hasn't been coded in yet*/)
        return currentNode;

    if (maximizingPlayer == "white") {
        move maxEvalMove{ "/////", -999999999 };
        for (int piece = 0; piece < piecesRemaining.size(); piece++) {
            std::string squareOfPiece = piecesRemaining[piece].file + std::to_string(piecesRemaining[piece].rank);
            std::vector<std::string> moves = playerBoard->legalMoves(squareOfPiece);
            for (int i = 0; i < moves.size(); i++) {
                boardCpy.makeMove(squareOfPiece + ":" + moves[i]);
                move nextEval{squareOfPiece + ":" + moves[i], chooseMoveHelper(depth - 1, "black", boardCpy, squareOfPiece + ":" + moves[i]).eval};

                //call function to adjust evaluation based on piece placement
                nextEval.eval += boardCpy.adjustEvalByPiecePlacement(boardCpy[moves[i]]->piece, moves[i]);

                if (nextEval.eval > maxEvalMove.eval)
                    maxEvalMove = nextEval;
                boardCpy.makeMove(moves[i] + ":" + squareOfPiece);
            }
        }
        return maxEvalMove;
    }
    else {
        move minEvalMove{ "/////", 999999999 };
        for (int piece = 0; piece < piecesRemaining.size(); piece++) {
            std::string squareOfPiece = piecesRemaining[piece].file + std::to_string(piecesRemaining[piece].rank);
            std::vector<std::string> moves = playerBoard->legalMoves(squareOfPiece);
            for (int i = 0; i < moves.size(); i++) {
                //store current piece on square we'll move to:
                char capturedPiece = boardCpy[moves[i]]->piece;

                boardCpy.makeMove(squareOfPiece + ":" + moves[i]);
                move nextEval{ squareOfPiece + ":" + moves[i], chooseMoveHelper(depth - 1, "white", boardCpy, squareOfPiece + ":" + moves[i]).eval };

                //call function to adjust evaluation based on piece placement
                nextEval.eval -= boardCpy.adjustEvalByPiecePlacement(boardCpy[moves[i]]->piece, moves[i]);

                if (nextEval.eval < minEvalMove.eval)
                    minEvalMove = nextEval;
                boardCpy.makeMove(moves[i] + ":" + squareOfPiece);
                boardCpy.editSquare(boardCpy[moves[i]], capturedPiece);
            }
        }
        return minEvalMove;
    }

}

为了测试我的情况,目前,我已经给机器人这个起始位置:

r  n  b  .  k  b  n  r
p  p  p  .  p  p  p  p
.  .  .  .  .  .  .  .
.  .  .  q  .  .  .  .
.  .  .  .  .  .  .  .
.  .  N  .  .  .  .  .
P  P  P  P  .  P  P  P
R  .  B  Q  K  B  N  R

如果您不太熟悉国际象棋,主要思想是第四行的黑皇后(用小写 q 表示)有一个非常明确的目标:远离棋盘上的马(又名“马”)。第 6 行是针对它的。然而,当我给出 minimax thsi 棋盘时,它计算出黑棋的最佳走法是在黑皇后(用大写 P 表示)前面 3 个格子处拿走白棋,尽管这使得黑皇后很容易被捕捉下一步动作的 3 种不同方式。我完全不知道为什么会发生这种情况,并且我已经使用断点和调试器运行了我的代码一百万次,但我似乎无法追踪错误,并且我确信我的逻辑中的某些内容是错误的。

c++ artificial-intelligence chess minimax minmax
1个回答
0
投票

没有递归的原因只有一个,那就是代码从不执行递归。如果 for 循环没有触发,这是可能的唯一方法,所以我会检查pieceRemaining 或legalMoves 以确保它们具有您实际期望的结果。

(顺便说一句,代码的分解很糟糕,因此您应该将一些代码移动到单独的函数中并传递所有变量)

© www.soinside.com 2019 - 2024. All rights reserved.