c# – 我是否正确实现了这个minimax功能?

这是一个跳棋游戏.请参阅旧版代码的修订历史记录.

    private static Move GetBestMove(Color color, Board board, int depth)
    {
        var bestMoves = new List<Move>();
        var validMoves = board.GetValidMoves(color);
        int highestScore = int.MinValue;
        Board boardAfterMove;
        int tmpScore;
        var rand = new Random();

        Debug.WriteLine("{0}'s Moves:", color);

        foreach (var move in validMoves)
        {
            boardAfterMove = board.Clone().ApplyMove(move);

            if(move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any())
                tmpScore = NegaMax(color, boardAfterMove, depth);
            else
                tmpScore = -NegaMax(Board.Opposite(color), boardAfterMove, depth);

            Debug.WriteLine("{0}: {1}", move, tmpScore);

            if (tmpScore > highestScore)
            {
                bestMoves.Clear();
                bestMoves.Add(move);
                highestScore = tmpScore;
            }
            else if (tmpScore == highestScore)
            {
                bestMoves.Add(move);
            }
        }

        return bestMoves[rand.Next(bestMoves.Count)];
    }

    private static int NegaMax(Color color, Board board, int depth)
    {
        var validMoves = board.GetValidMoves(color);
        int highestScore = int.MinValue;
        Board boardAfterMove;

        if (depth <= 0 || !validMoves.Any())
            return BoardScore(color, board);

        foreach (var move in validMoves)
        {
            boardAfterMove = board.Clone().ApplyMove(move);

            if(move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any())
                highestScore = Math.Max(highestScore, NegaMax(color, boardAfterMove, depth));
            else
                highestScore = Math.Max(highestScore, -NegaMax(Board.Opposite(color), boardAfterMove, depth - 1));
        }

        return highestScore;
    }

    private static int BoardScore(Color color, Board board)
    {
        if (!board.GetValidMoves(color).Any()) return -1000;
        return board.OfType<Checker>().Sum(c => (c.Color == color ? 1 : -1) * (c.Class == Class.Man ? 2 : 3));
    }

我正在尝试深度为0,并且大约一半比赛的分数是正确的,然后突然间它开始搞砸了.其中一名球员将开始宣称他的得分高于实际得分.为什么它只适用于半场比赛?!

最佳答案 有趣的方法,我第一次看到MaxiMax.但我在这里看到一个问题:

var minMove = GetBestMove(... board.Clone().ApplyMove(move), ...);
float score = ... BoardScore(color, board.Clone().ApplyMove(minMove));

在此代码中,move和minMove是针对不同方面的移动,但您在此处同等地应用它们.第二行应该是这样的:

float score = ... BoardScore(... board.Clone().ApplyMove(move).ApplyMove(minMove));

您当然可以存储和重新使用board.Clone().ApplyMove(移动)部分.

但是你仍然会丢失信息:在深度100处,你会在深度99过滤掉最好的boardScore,但你没有/使用98..0级别的任何东西,除非没有移动(null),但你注意到自己部分出错了.

Tried looking at some pseudo
algorithms, but all the seem to return
a score. That confuses me, because I
don’t really want to get a score back,
I want to get a Move back.

不过,这是要走的路.树搜索的主要结果是最佳分支的值.此举本身只是根本层面必不可少的.保留它直到你开始实现alpha / beta,然后你就可以将最好的分支存储在一个表中.

我会建议切换到常规的NegaMax,
也见this SO question.

点赞