2010-10-17 17 views
4

J'ai créé la classe abstraite ci-dessous pour évaluer la position d'un tableau de jeux simples. La classe abstraite est remplacée par chaque classe dérivée afin que seule la fonction d'évaluation soit définie dans game.hProblème lors de la création d'une carte avec un vecteur comme clé et une classe personnalisée comme valeur

J'essaie de rendre mon programme plus efficace en utilisant la mémorisation, mais je n'arrive pas à faire fonctionner ma carte correctement. Le compilateur génère une erreur pour les résultats de la ligne [board] = best. Cette ligne tente de définir la valeur qui correspond au tableau courant (vecteur d'ints) pour le meilleur mouvement possible à partir de cette position. Move est une classe que j'ai créée qui contient simplement un score, un nombre à supprimer pour faire le tableau suivant, et l'indice (pile) pour retirer le nombre. L'erreur de compilation pour 'results [board] = best' indique qu'il n'y a pas d'appel de fonction correspondant à move :: move(). Je ne comprends pas cette erreur parce que je n'essaie pas de créer un nouveau mouvement, il suffit de stocker le meilleur mouvement actuel. J'ai essayé de créer un mouvement temporaire et de le stocker aussi, donc je sais que ce n'est pas correct.

Un dernier point - le code compile et s'exécute parfaitement sans cette ligne de code, donc je sais que l'algorithme et toutes les sous-classes fonctionnent correctement. Toute aide serait appréciée!

// VIRTUAL FUNCS 
// All virtual functions must be overridden by subclasses 

virtual ~game(){ } 

// initialize 
virtual void initialize(int numPlayers, std::vector<int> board) = 0; 


// gameHasEnded 
virtual bool gameHasEnded(std::vector<int> board) const = 0; 

// display 
virtual void display(std::vector<int> board) const = 0; 

// makeNewBoard 
virtual std::vector<int> makeNewBoard(std::vector<int> currBoard, move m) = 0; 

// generateMoves 
virtual std::vector<move> generateMoves(std::vector<int> currBoard) = 0; 

// compare 
virtual move compare(std::vector<int> board1, std::vector<int> board2) = 0; 

// NON-VIRTUAL FUNCS 

// 
// Name:   evaluate 
// Description: Evaluates a given board position. Determines whether 
//     or not the current position is a winning position 
//     or a losing position. A winning position is 
//     designated by a 1, a losing by a -1. 
// Modifies:  The board and the score. 
// Returns:  The best possible move from this position. 
//     
move evaluate( std::vector<int> board, int multiplier = 1, int currScore = -100) { 

    // Base case is defined by subclasses 
    if(gameHasEnded(board)) { 
    move toReturn(multiplier, 0); 
    return toReturn; 
    } // end-if 

    // If game is not over 
    else { 

    std::map<std::vector<int>,move>::iterator iter = results.find(board); 
    if(iter != results.end()) { 
     return iter->second; 
    } 
    else { 

     move best(-2,0); // Just a place holder. Is overridden later. 
     int s = 0; // Stores the score 

     std::vector<move> nextMove; 
     // generate all possible boards from this position - defined by subclass 
     nextMove = generateMoves(board); 

     // For each board position 
     for(int i = 0; i < ((int)nextMove.size()); ++i) { 
     std::vector<int> newBoard; 

     // Create a new possible board state 
     newBoard = makeNewBoard(board, nextMove[i]); 

     move dif = compare(board, newBoard); // Get the move that was made 
     move m(0,0); // place holder 
     m = evaluate(newBoard, multiplier*-1, currScore); // recurse through all positions 
     s += m.getScore(); 
     // If this is the best score so far 
     if(m.getScore() > currScore) { 

      m.setNumTake(dif.getNumTake()); // get the move 
      m.setPile(dif.getPile()); 
      best = m; // store the move 
      currScore = m.getScore(); // update the score 

     } 

     } 
     best.setScore(s); 

     ////////////////////////////// THIS IS THE LINE THAT THROWS A COMPILER ERROR 

     results[ board ] = best; 

     ////////////////////////////////// 

     return best; // return best move 
    } 
    } 
    return move(2,2); // dummy return. should never happen 
    } 

privé: // membres de données

std::map<std::vector<int>,move> results; 

};

+0

Vérifier http://stackoverflow.com/questions/695645/why-does-the-c-map-type-argument-require-an-empty-constructor- when-using – a1ex07

Répondre

2

Le constructeur par défaut est nécessaire si vous utilisez l'opérateur [].

Si la carte ne contient pas d'élément pour la clé board, l'opérateur [] de la carte construit un nouvel objet par défaut et l'insère dans la carte. Seulement alors il fait l'affectation de best

3

Toute classe que vous utilisez comme valeur dans une carte avec l'opérateur [] doit pouvoir être créée en utilisant le constructeur par défaut.

results[ board ] = best; 

va effectuer les opérations suivantes

  1. Créer une par défautmove() avec la touche board
  2. renvoie une référence à cette adresse
  3. écraser le mouvement par défaut en affectant best à lui.

Vous étape échouez 1.

+1

Seulement si vous utilisez l'opérateur [] le constructeur par défaut est nécessaire. Vous pouvez utiliser find et insert pour utiliser une classe comme valeur sans constructeur par défaut. – SebastianK

+0

Alors j'ai juste besoin de définir un constructeur par défaut pour le déplacement? Cela permettra de créer un mouvement temporaire et de mieux le stocker, n'est-ce pas? – Mike

+0

@SebastianK: Merci, j'ai corrigé la réponse. – Akusete