繁体   English   中英

为什么我的国际象棋 Minimax 算法需要这么长时间来评估一步棋?

[英]Why is my Minimax algorithm for chess taking so long to evaluate a move?

我正在尝试在 C# 中创建一个简单的国际象棋 AI,到目前为止,使用带有 alpha-beta 修剪的极小极大算法在一定程度上取得了成功。 但是,使用下面的代码,它实际上需要大约 5 秒的时间来评估深度 3 的移动,如果可能的话,我希望它更快。 我已经对它进行了几个小时的修补,我对它所做的任何更改似乎都会破坏 ai。 任何帮助是极大的赞赏!

private void makeAIMove(Piece[,] board)
{
    Move bestMove;
    int score;

    List<Piece[,]> possiblePositions = getAllPossiblePositions(board, Team.Black);
    List<Move> possibleMoves = getAllPossibleMoves(board, Team.Black);

    bestMove = possibleMoves[0];
    score = evaluatePosition(possiblePositions[0], int.MinValue, int.MaxValue, DEPTH, Team.White);
    if (numTurns > 0)
    {
        for (int i = 1; i < possiblePositions.Count; i++)
        {
            int pos = evaluatePosition(possiblePositions[i], int.MinValue, int.MaxValue, DEPTH, Team.White);
            if (pos >= score)
            {
                bestMove = possibleMoves[i];
                score = pos;
            }
        }
    }
    else
    {
        bestMove = possibleMoves[Random.Range(0, possibleMoves.Count)];
    }
    numTurns += 1;
    updateBoard(bestMove);
}

private int evaluatePosition(Piece[,] board1, int alpha, int beta, int depth, int team)
{
    Piece[,] board = (Piece[,])board1.Clone();
    if (depth == 0)
    {
        return evaluate(board);
    }
    if (team == Team.White)
    {
        List<Move> moves = getAllPossibleMoves(board, team);
        int newBeta = beta;
        foreach (Move moveName in moves)
        {
            fastMove(board, board[moveName.start.y, moveName.start.x], moveName);
            newBeta = Mathf.Min(newBeta, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team)));
            if (newBeta <= alpha) break;
        }
        return newBeta;
    }
    else
    {
        List<Move> moves = getAllPossibleMoves(board, team);
        int newAlpha = alpha;
        foreach (Move moveName in moves)
        {
            fastMove(board, board[moveName.start.y, moveName.start.x], moveName);
            newAlpha = Mathf.Max(newAlpha, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team)));
            if (beta <= newAlpha) break;
        }
        return newAlpha;
    }
}

很难确切地说出原因,因为我们没有看到您的全部代码,但这里有一些关于从哪里开始寻找的建议:

  1. 您的移动生成代码可能很慢。 尝试对某些位置进行性能测试,看看你得到了多少个节点。 如果你有一个写得很好的代码,它应该是数百万。

  2. 您的评估可能很慢。 尝试先做一个简单的评估,您只计算每一面的材料。

  3. 奇怪的是你有“if team == Team.White”。 这是否意味着你总是有 AI 来扮演黑人? 在伪代码中使用 as 而不是 alpha/beta,在 if 语句中使用最大化播放器。

  4. 您在最小化播放器循环(第一个 if 语句)中设置 newBeta = beta。 在这里你应该设置 newBeta = someLargeValue。 else 语句中的 alpha 也是如此。 另外,我认为在这两种情况下都使用术语分数会更好,以使其更清楚。

  5. 您忘记设置新的 alpha 和 beta 值。 在第一种情况下,它应该是这样的:

     newBeta = Mathf.Min(newBeta, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team))); if (newBeta <= alpha) break; beta = Mathf.Min(beta, newBeta);

请查看伪代码并尝试尽可能接近地实现,这将使它更简单: https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning 还可以考虑改为使用 Negamax,这将进一步简化逻辑: https://en.wikipedia.org/wiki/Negamax 这是进一步优化的必要条件。

当你让一切都按预期工作时,你可以开始做其他事情来提高性能,例如移动顺序和不同的修剪技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM