2015-08-14 8 views
9

Ho implementato una partita a scacchi in C, con le seguenti struct:Computing un punteggio mossa in un albero Minimax di una certa profondità

mossa - che rappresenta un passaggio da (a, b) a (c, d) su una scheda char [8] [8] (scacchiera)

mosse - che è un elenco collegato di mosse con testa e coda.

Variabili: playing_color è 'W' o 'B'. minimax_depth è una profondità minima minima precedentemente impostata.

Ecco il mio codice della funzione Minimax con alfa-beta potatura e la funzione getMoveScore che dovrebbe restituire il punteggio di movimento in Minimax Albero di una certa minimax_depth che è stato impostato prima.

Inoltre sto utilizzando la funzione getBestMoves che elencherò anche qui, in modo semplice trova le mosse migliori durante l'algoritmo Minimax e le salva in una variabile globale in modo che io possa usarle in seguito.

devo aggiungere che tutte le funzioni elencate all'interno delle tre funzioni che lo aggiungerò qui funzionano correttamente e sono stati testati, quindi il problema è o un problema logica dell'algoritmo alphabetaMax o l'attuazione di getBestMoves/getMoveScore.

Il problema principalmente è che quando ricevo i miei migliori mosse in profondità N (che non vengono calcolate anche somewhy destra) e quindi controllare il loro punteggio sulla stessa profondità con funzione di getMoveScore, sto ottenendo diversi punteggi che don Corrisponde al punteggio di quelle mosse migliori effettive. Ho passato ore a eseguire il debug di questo problema e non sono riuscito a vedere l'errore, spero che qualcuno possa darmi un consiglio su come trovare il problema.

Ecco il codice:

/* 
* 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; 
    } 
} 

Come Eugene ha sottolineato-io sono l'aggiunta di un esempio qui: http://imageshack.com/a/img910/4643/fmQvlm.png

Sono attualmente il giocatore bianco, ho ottenuto solo king-k e queen-q, il colore opposto ha re-K e rook-R. Ovviamente la mia miglior mossa qui è mangiare una torre o fare almeno un assegno. Le mosse dei pezzi sono testate e funzionano bene. Anche se quando chiamo la funzione get_best_moves alla profondità 3, sto ricevendo molte mosse non necessarie e punteggi negativi per loro a quella profondità. Forse ora è un po 'più chiaro. Grazie!

+0

Nessun MCVE, nessun comportamento previsto, nessun comportamento effettivo. Abbiamo un po 'a che fare con questo. –

+0

@EugeneSh. Ho aggiunto un esempio dettagliato ora, dovrei aggiungere qualcos'altro? –

+1

@EvgenyA .: ti ha fatto +1 su una collaborazione costruttiva altrove. Ne hai bisogno più di me. ;-) – DevSolar

risposta

0

Senza eseguire il debug dell'intero codice, almeno uno dei problemi è il fatto che la scoreverificazione potrebbe funzionare con un algoritmo minimax, ma non con una Alpha-Beta. Problema successivo:

La funzione getMoveScore() deve iniziare con una finestra AB aperta.

I getBestMoves() tuttavia richiamano getMoveScore() con una finestra AB già chiusa.

Quindi, nel caso di getBestMoves, possono essere potati rami che non vengono tagliati in getMoveScore(), quindi il punteggio non è esatto, e questo è il motivo (o almeno UNO di essi) perché questi valori possono differire .

+0

Non capisco cosa intendi per finestra chiusa AB, vuoi dire che dovrei chiamare la funzione alphabeta in getMoveScore con OppositeColor ma come player massimizzante? Come ho capito, in getMoveScore faccio una mossa, quindi dovrei chiamare alphabeta per l'avversario, ma dovrebbe minimizzare o massimizzare? –

+0

La finestra AB non ha nulla a che fare con min o max. Ad esempio, una finestra Alpha Beta è -300 +100, che rappresenta i valori alfa e beta. A causa dei limiti, i valori di Alfa o Beta diversi spesso determinano valori di movimento diversi. – xXliolauXx

+0

Va bene, capisco, e cosa intendi con AB Window aperto? Quali valori dovrei provare? O come posso calcolare quali valori ho bisogno? A proposito, getBestMoves non chiama getMoveScore, sono indipendenti. –

Problemi correlati