簡體   English   中英

negamax算法..怎么了?

[英]The negamax algorithm..what's wrong?

我正在嘗試編寫一個國際象棋游戲,並花了幾天時間嘗試修復該代碼。 我什至嘗試了min max,但結果卻相同。 AI總是從拐角處開始,將棋子移開,然后車子每轉一圈就來回移動。 如果被食用,則AI將每一塊從一側移到另一側,直到全部吃掉。 您知道以下代碼有什么問題嗎?

public Move MakeMove(int depth)
{
    bestmove.reset();
    bestscore = 0;
    score = 0;
    int maxDepth = depth;
    negaMax(depth, maxDepth);
    return bestmove;
}


public int EvalGame() //calculates the score from all the pieces on the board
{
    int score = 0;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            if (AIboard[i, j].getPiece() != GRID.BLANK)
            {
                score += EvalPiece(AIboard[i, j].getPiece());
            }
        }
    }

    return score;
}

private int negaMax(int depth, int maxDepth)
{
    if (depth <= 0)
    {
        return EvalGame();
    }

    int max = -200000000;

    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            for (int k = 0; k < 8; k++)
            {
                for (int l = 0; l < 8; l++)
                {
                    if(GenerateMove(i, j, k, l)) //generates all possible moves
                    {
                        //code to move the piece on the board
                        board.makemove(nextmove);
                        score = -negaMax(depth - 1, maxDepth);

                        if( score > max )
                        {
                            max = score;

                            if (depth == maxDepth)
                            {
                                bestmove = nextmove;
                            }
                        }

                        //code to undo the move
                        board.undomove;
                    }
                }
            }
        }
    }

    return max;
}

public bool GenerateMove(int i, int j, int k, int l)
{
    Move move;
    move.moveFrom.X = i;
    move.moveFrom.Y = j;
    move.moveTo.X = k;
    move.moveTo.Y = l;

    if (checkLegalMoves(move.moveTo, move.moveFrom)) //if a legal move
    {
        nextMove = move;
        return true;
    }

    return false;
}

這段代碼:

public Move MakeMove(int depth)
{
    bestscore = 0;
    score = 0;
    int maxDepth = depth;
    negaMax(depth, maxDepth);
    return bestmove;
}

請注意,永遠不會設置最佳動作! negaMax的返回得分與移動替代negaMax進行比較。 您甚至沒有循環可能的動作。

另外,當您提交的代碼不完全一致時,很難發現錯誤。 negaMax方法在代碼negaMax兩個參數放在一個位置,然后在遞歸調用中將四個參數放在一個位置?

我還建議在代碼中使用更好的抽象。 單獨的板表示,移動表示,移動生成和搜索算法。 這將對您有很大幫助。 例如:為什么在移動生成中需要深度計數器?

Østein

您有兩個可能的問題:

  1. 因為您沒有向我們展示您的變量聲明,所以它有點模棱兩可,但是我認為您使用了太多的全局變量。 Negamax通過計算每個節點上的最佳移動來工作,因此在搜索值時,移動應該是局部的。 無論如何,優良作法是保持變量的范圍盡可能緊湊。 當遍歷游戲樹更改了如此多的變量時,很難對代碼進行推理。 但是,您的搜索看起來應該返回正確的值。

  2. 您的評估似乎無法區分是哪一方。 我不知道EvalPiece是否EvalPiece處理此事,但是無論如何,評估應該從當前有權移動的一方的角度進行。

您還遇到其他與您的問題不直接相關的問題:

  1. 您的舉動令人恐懼。 您要成對遍歷板上的每對可能的從/到正方形。 這是非常低效的,我什至不知道這種方法如何工作。 您只需要遍歷板上的所有塊,或者以較慢的方法遍歷板上的每個正方形(而不是4096正方形)。

  2. MakeMove似乎可能是根節點的位置。 現在,您的方案起作用了,因為搜索退出的最后一個節點將是root。 但是,通常在根目錄使用特殊例程(例如迭代加深),因此在根目錄使用單獨的循環可能會很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM