Domanda

Ho cercato Google e StackOverflow per questa domanda, ma io ancora non capisco come una funzione minimax lavori.

Ho trovato la voce di Wikipedia ha una versione pseudocodice della funzione:

function integer minimax(node, depth)
    if node is a terminal node or depth <= 0:
        return the heuristic value of node
    α = -∞
    for child in node:                       # evaluation is identical for both players 
        α = max(α, -minimax(child, depth-1))
    return α

Diverse altre funzioni minimax ho trovato con Google sono fondamentalmente la stessa cosa; Sto cercando di implementare questo in C ++, e questo è quello che ho messo a punto finora:

double miniMax(Board eval, int iterations)
{
    //I evaluate the board from both players' point of view and subtract the difference
    if(iterations == 0)
        return boardEval(eval, playerNumber) - boardEval(eval, opponentSide());

    /*Here, playerTurn tells the findPossibleMoves function whose turn it is;
    I mean, how do you generate a list of possible moves if you don't even know
    whose turn it's supposed to be? But the problem is, I don't see where I can
    get playerTurn from, as there are only 2 parameters in all the examples of
    minimax I've seen*/
    vector<int> moves = eval.findPossibleMoves(playerTurn);

    //I'm assuming -∞ in the wikipedia article means a very low number?
    int result = -999999999;

    //Now I run this loop to evaluate each possible move
    /*Also, the Lua example in the wiki article has
      alpha = node.player==1 and math.max(alpha,score) or math.min(alpha,score)
      Is alpha a boolean there?!*/
    for(int i = 0; i * 2 < moves.size(); i++)
    {
        //I make a copy of the board...
        Board temp = eval;

        /*and make the next possible move... once again playerTurn crops up, and I
        don't know where I can get that variable from*/
        temp.putPiece(moves[i * 2], moves[i * 2 + 1], playerTurn);

        /*So do I create a function max that returns the bigger of two doubles?*/
        result = max(result, -miniMax(temp, iterations - 1));
    }

    return result;
    /*So now I've returned the maximum score from all possible moves within a certain
    # of moves; so how do I know which move to make? I have the score; how do I know
    which sequence of moves that score belongs to?*/
}

Come si può vedere, sono abbastanza confuso su questa funzione minimax. Si prega di almeno darmi qualche suggerimento per aiutarmi con questo.

Grazie! :)

È stato utile?

Soluzione

Questo esempio da Wikipedia sta facendo negamax con l'alfa / beta potatura .

Si può essere aiutato da ottenere la denominazione dritto:

  • La base è MiniMax, un'implementazione letterale comporterebbe 2 metodi che si alternano (mutuamente ricorsive), 1 per ogni lato.

  • programmatori pigri trasformano questo in negamax, un metodo con un operatore - posizione strategica.

  • Alpha / potatura Beta è tenere traccia di una finestra di mosse migliori (su più profondità) per rilevare rami secchi.

Il playerTurn viene utilizzato per determinare chi è il turno. In negamax è possibile derivare questo dalla profondità (iterazioni) essendo pari o dispari. Ma sarebbe più facile da usare 2 parametri (Mycolor, otherColor) e passare ad ogni livello.

Altri suggerimenti

Funzione

Il tuo miniMax () dovrebbe ricordare la migliore mossa che ha trovato finora. Così, invece di questo codice:


  /*So do I create a function max that returns the bigger of two doubles?*/
  result = max(result, -miniMax(temp, iterations - 1));

Si dovrebbe fare qualcosa di simile:


  /*So do I create a function max that returns the bigger of two doubles?*/
  double score = -miniMax(temp, iterations - 1);
  if (score > result)
  {
     result = score;
     bestMove = i;
  }

Naturalmente, è necessario una variabile "bestMove" e un modo per restituire la mossa migliore trovata al chiamante.

Aggiungere la variabile playerTurn come argomento per miniMax, e chiamata miniMax che la mossa del giocatore di turno inizialmente e in modo ricorsivo.

Inoltre, le esigenze opponentSide ad una funzione di playerTurn.

Un buon posto per iniziare con l'albero di gioco di ricerca è il scacchi programmazione wiki . Per le tue domande su movimento: Penso che sia più comune avere due max-funzioni. La differenza tra le due funzioni max è che si ritorna solo il punteggio e gli altri ritorna il punteggio e la mossa migliore. Un ordine di chiamata ricorsiva sarebbe come segue:

maxWithBestMoveReturn(...) --> min(...) --> max(...) --> min(...)

Ci sono alcune carte buone con pseudocodice per l'algoritmo di Alpha Beta:

Per la tua domanda nel commento:?! e Math.max (alfa, punteggio) o Math.min (alfa, punteggio) c'è alfa un valore booleano

Non alfa è una finestra legato in un algoritmo alpha beta. Il valore alfa viene aggiornata con un nuovo valore. Perché alfa e beta vengono scambiati con la chiamata ricorsiva del negamax-Function la variabile alfa si riferisce alla variabile beta nella prossima chiamata ricorsiva.

Una nota alla variabile playerTurn: L'algoritmo minimax o alfa-beta non ha bisogno di queste informazioni. Quindi mi sento di dare le informazioni - chi è il prossimo -, nel Board-Structure. Le funzioni e le findPossibleMoves boardEval ottenere tutte le informazioni di cui hanno bisogno dal Board-struttura.

Una nota alla condizione di interruzione ricorsivo: se ho ben capito il codice giusto, allora hai solo quello con iterations == o. Credo che questo mezzo l'algoritmo ha raggiunto la profondità desiderata. Ma cosa succede se non ci sono possibili mosse a sinistra befor l'algoritmo raggiunge questa profondità. Forse si dovrebbe scrivere seguente:

vector<int> moves = findPossibleMoves(...);
if (!moves.size())
    return boardEval(...);

Nel vostro pseudocodice, la variabile nodo deve contenere tutte le informazioni relative alla posizione attuale consiglio (o qualsiasi altra cosa). Questa informazione dovrebbe includere chi è il turno di muoversi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top