2015-08-14 9 views
9

I zostały wdrożone w grę figur w ° C, o następujących strukturach:obliczeniowe wynik przesuwania w Minimax Drzewo pewnej głębokości

ruch - która oznacza przejście od (a, b) do (c, d) na tablicy char [8] [8] (szachownica)

move - która jest połączoną listą ruchów z głową i ogonem.

Zmienne: playing_color to "W" lub "B". minimax_depth to minimalna głębokość ustawiona wcześniej.

Oto mój kod funkcji Minimax o algorytm alfa-beta i funkcją getMoveScore która powinna zwracać wynik ruchu w Minimax Drzewo pewnym minimax_depth który został ustawiony wcześniej.

Korzystam również z funkcji getBestMoves, którą tu również będę wymieniał, w zasadzie odnajduje najlepsze ruchy podczas algorytmu Minimax i zapisuje je w zmiennej globalnej, dzięki czemu będę mógł z nich korzystać później.

Muszę dodać, że wszystkie funkcje, które są wymienione w ciągu trzech funkcji że dodam tutaj pracują prawidłowo i zostały przetestowane więc problem jest albo problem logiczny algorytm alphabetaMax lub realizacja getBestMoves/getMoveScore.

Problem polega głównie na tym, że kiedy dostaję moje najlepsze ruchy na głębokości N (które również nie są obliczane właściwie), a następnie sprawdzam ich wynik na tej samej głębokości za pomocą funkcji getMoveScore, otrzymuję różne wyniki pasuje do wyniku rzeczywistych najlepszych ruchów. Spędziłem wiele godzin na debugowaniu tego i nie widziałem błędu, mam nadzieję, że może ktoś mógłby dać mi wskazówkę na temat znalezienia problemu.

Oto kod:

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

Jak Eugene wskazał-jestem dodanie przykład tutaj: http://imageshack.com/a/img910/4643/fmQvlm.png

Jestem obecnie biały gracz, mam tylko król-k i królowa-q, przeciwny kolor ma króla-K i wieżę-R. Oczywiście moim najlepszym posunięciem jest zjedzenie wieży lub przynajmniej sprawdzenie. Ruchy elementów są testowane i działają dobrze. Chociaż, gdy wywołuję funkcję get_best_moves na głębokości 3, otrzymuję wiele niepotrzebnych ruchów i negatywnych wyników dla nich na tej głębokości. Może teraz jest to trochę bardziej przejrzyste. Dzięki!

+0

Bez MCVE, bez spodziewanego zachowania, bez faktycznego zachowania. Mamy z tym trochę wspólnego. –

+0

@EugeneSh. Dodałem teraz dokładny przykład, czy powinienem dodać coś jeszcze? –

+1

@EvgenyA .: Podrzuciłaś +1 za konstruktywną współpracę w innym miejscu. Potrzebujesz tego bardziej niż ja. ;-) – DevSolar

Odpowiedz

0

Bez debugowania całego kodu, przynajmniej JEDEN z problemów jest fakt, że twoja ocena wyniku może działać z algorytmem minimaks, ale nie z Alpha-Beta. Poniższy problem:

Funkcja getMoveScore() musi rozpoczynać się od otwartego okna AB.

Funkcja getBestMoves() jednak wywołuje funkcję getMoveScore() z już zamkniętym oknem AB.

Tak więc w przypadku getBestMoves, mogą być przycinane gałęzie, które nie są przycinane w funkcji getMoveScore(), dlatego wynik nie jest dokładny, i to jest powodem (lub przynajmniej JEDNYM z nich), dlaczego te wartości mogą się różnić .

+0

Nie bardzo rozumiem, co masz na myśli przez zamknięte okno AB, masz na myśli, że powinienem nazwać funkcję alphabeta w getMoveScore z OppositeColor, ale jako gracz maksymalizujący? Jak to rozumiem, w getMoveScore wykonuję ruch, więc powinienem nazwać alfabetem przeciwnika, ale czy powinien on zminimalizować lub zmaksymalizować? –

+0

Okno AB nie ma nic wspólnego z min. Lub maks. Okno Alfa Beta to na przykład -300 +100, reprezentujące wartości alfa i beta. Z powodu odcięć, różne wartości Alfa lub Beta często powodują różne wartości ruchów. – xXliolauXx

+0

W porządku Rozumiem i co rozumiesz przez otwarte okno AB? Jakie wartości powinienem spróbować? Albo jak mogę obliczyć, jakie wartości potrzebuję? Nawiasem mówiąc, getBestMoves nie nazywa getMoveScore, są niezależne. –

Powiązane problemy