13

次の構造体を使用して、C でチェス ゲームを実装しました。

move - char board[8][8] (チェス盤) 上の (a,b) から (c,d) への動きを表します

動き - 頭と尾を持つ動きのリンクされたリストです。

変数: playing_color は 'W' または 'B' です。minimax_depth は、以前に設定されたミニマックス深度です。

これは、以前に設定された特定の minimax_depth の Minimax ツリーで移動のスコアを返す必要がある、アルファ ベータ プルーニングと getMoveScore 関数を使用した Minimax 関数の私のコードです。

同様に、ここにもリストする getBestMoves 関数を使用しています。これは基本的に、Minimax アルゴリズム中に最適な動きを見つけて、それらを後で使用できるようにグローバル変数に保存します。

ここに追加する 3 つの関数内にリストされている関数はすべて正常に動作し、テストされていることを付け加えなければなりません。したがって、問題はalphabetaMax アルゴリズムの論理的な問題か、getBestMoves/getMoveScore の実装のいずれかです。

主な問題は、深さ N で最高の動きを取得し (これも何らかの理由で正しく計算されません)、getMoveScore 関数を使用して同じ深さでスコアをチェックすると、スコアと一致しない異なるスコアが得られることです。それらの実際のベストムーブ。これをデバッグするのに何時間も費やしましたが、エラーが表示されませんでした。誰かが問題を見つけるためのヒントを教えてくれることを願っています.

コードは次のとおりです。

/*
* Getting best possible moves for the playing color with the minimax algorithm
*/
moves* getBestMoves(char playing_color){
    //Allocate memory for the best_moves which is a global variable to fill it in   a minimax algorithm//
    best_moves = calloc(1, sizeof(moves));
    //Call an alpha-beta pruned minimax to compute the best moves//
    alphabeta(playing_color, board, minimax_depth, INT_MIN, INT_MAX, 1);
    return best_moves;
}

/*
* Getting the score of a given move for a current player
*/
int getMoveScore(char playing_color, move* curr_move){
    //Allocate memory for best_moves although its not used so its just freed    later//
    best_moves = calloc(1, sizeof(moves));
    int score;
    char board_cpy[BOARD_SIZE][BOARD_SIZE];
    //Copying a a current board and making a move on that board which score I   want to compute//
    boardCopy(board, board_cpy);
    actualBoardUpdate(curr_move, board_cpy, playing_color);
    //Calling the alphabeta Minimax now with the opposite color , a board after     a given move and as a minimizing player, because basicly I made my move so  its now the opponents turn and he is the minimizing player//
    score = alphabeta(OppositeColor(playing_color), board_cpy, minimax_depth, INT_MIN, INT_MAX, 0);
    freeMoves(best_moves->head);
    free(best_moves);
    return score;
}

/*
* Minimax function - finding the score of the best move possible from the input board
*/
int alphabeta(char playing_color, char curr_board[BOARD_SIZE][BOARD_SIZE], int depth,int alpha,int beta, int maximizing) {
    if (depth == 0){
        //If I'm at depth 0 I'm evaluating the current board with my scoring            function//
        return scoringFunc(curr_board, playing_color);
    }
    int score;
    int max_score;
    char board_cpy[BOARD_SIZE][BOARD_SIZE];
    //I'm getting all the possible legal moves for the playing color//
    moves * all_moves = getMoves(playing_color, curr_board);
    move* curr_move = all_moves->head;
    //If its terminating move I'm evaluating board as well, its separate from depth == 0 because    only here I want to free memory//
    if (curr_move == NULL){
        free(all_moves);
        return scoringFunc(curr_board,playing_color);
    }
    //If maximizing player is playing//
    if (maximizing) {
        score = INT_MIN;
        max_score = score;
        while (curr_move != NULL){
            //Make the move and call alphabeta with the current board               after the move for opposite color and !maximizing player//
            boardCopy(curr_board, board_cpy);
            actualBoardUpdate(curr_move, board_cpy, playing_color);
            score = alphabeta(OppositeColor(playing_color), board_cpy, depth - 1,alpha,beta, !maximizing);
            
            alpha = MAX(alpha, score);
            if (beta <= alpha){
                break;
            }
            //If I'm at the maximum depth I want to get current player              best moves//
            if (depth == minimax_depth){
                move* best_move;
                //If I found a move with a score that is bigger then                    the max score, I will free all previous moves and                   append him, and update the max_score//
                if (score > max_score){
                    max_score = score;
                    freeMoves(best_moves->head);
                    free(best_moves);
                    best_moves = calloc(1, sizeof(moves));
                    best_move = copyMove(curr_move);
                    concatMoves(best_moves, best_move);
                }
                //If I have found a move with the same score and want                   to concatenate it to a list of best moves//
                else if (score == max_score){
                    best_move = copyMove(curr_move);
                    concatMoves(best_moves, best_move);
                }
                
            }
            //Move to the next move//
            curr_move = curr_move->next;
        }
        freeMoves(all_moves->head);
        free(all_moves);
        return alpha;
    }
    else {
        //The same as maximizing just for a minimizing player and I dont want       to look for best moves here because I dont want to minimize my          outcome//
        score = INT_MAX;
        while (curr_move != NULL){
            boardCopy(curr_board, board_cpy);
            actualBoardUpdate(curr_move, board_cpy, playing_color);
            score = alphabeta(OppositeColor(playing_color), board_cpy, depth - 1,alpha,beta, !maximizing);
            beta = MIN(beta, score);
            if (beta <= alpha){
                break;
            }
            curr_move = curr_move->next;
        }
        freeMoves(all_moves->head);
        free(all_moves);
        return beta;
    }
}

Eugene が指摘したように、ここに例を追加します: http://imageshack.com/a/img910/4643/fmQvlm.png

私は現在白のプレーヤーで、キング-K とクイーン-Q しか持っていません。反対の色にはキング-K とルーク-R があります。明らかに、ここでの私の最善の動きは、ルークを食べるか、少なくともチェックを引き起こすことです。ピースの動きがテストされ、正常に動作します。深さ 3 で get_best_moves 関数を呼び出すと、その深さで多くの不要な動きと負のスコアが得られます。多分今それはもう少し明確です。ありがとう!

4

1 に答える 1

0

コード全体をデバッグしないと、少なくとも 1 つの問題は、スコア検証がミニマックス アルゴリズムでは機能する可能性があるが、アルファ ベータでは機能しない可能性があるという事実です。次の問題:

getMoveScore() 関数は、AB ウィンドウを開いた状態で開始する必要があります。

ただし、getBestMoves() は、既に閉じている AB ウィンドウで getMoveScore() を呼び出します。

したがって、getBestMoves の場合、getMoveScore() で枝刈りされていない枝が枝刈りされている可能性があるため、スコアは正確ではありません。これが、これらの値が異なる可能性がある理由 (または少なくとも 1 つ) です。

于 2015-08-14T19:02:11.190 に答える