使用向量作为键和自定义类作为值创建地图时出现问题

4
我创建了下面的抽象类来评估简单游戏的棋盘位置。每个派生类都会覆盖抽象类,以便只在game.h中定义evaluate函数。
我试图通过使用记忆化使我的程序更加高效,但我不能正确地使用我的映射。编译器为'results[board] = best'这一行抛出错误。该行代码试图将映射到当前棋盘(int向量)的值设置为该位置的最佳移动。Move是我创建的一个类,它只包含一个分数、一个要删除的数字以制作下一个棋盘和要从中删除数字的索引(堆)。
'results[board] = best'的编译器错误说没有匹配的函数调用move::move()。我不理解这个错误,因为我不想创建一个新的move,只是存储当前的最佳move。我已经尝试创建一个临时的move并将其存储,所以我知道那不正确。
最后一点 - 代码在没有该行代码的情况下可以完美地编译和运行,所以我知道算法和所有子类都正常工作。任何帮助都将不胜感激!
// 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
  }

私有的: // 数据成员

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

};


请查看以下链接:https://dev59.com/CnRB5IYBdhLWcg3wLkxM - a1ex07
2个回答

3

在使用[]运算符将类作为映射值使用时,必须能够使用默认构造函数创建该类。

results[ board ] = best;

将执行以下操作:

  1. 创建一个带有键名为 board默认 move()
  2. 返回该地址的引用。
  3. 通过将 best 赋值给它,覆盖默认移动。

您没有完成第1步。


1
只有当你使用 operator[] 时,才需要默认构造函数。你可以使用 find 和 insert 来使用一个没有默认构造函数的类作为值。 - SebastianK
那么我只需要为移动定义一个默认构造函数吗?这将允许创建一个临时的移动,然后最好将其存储在这个位置,对吗? - Mike
谢谢Akusete!我创建了默认构造函数,它完美地工作了。 - Mike
@Mike:很高兴它起作用了,但如果你不想让 Move 有一个默认构造函数,你可以使用 map 函数 put()。 - Akusete

2

如果您使用operator[],则需要默认构造函数。

如果map不包含键为board的元素,则map的operator[]构造一个新的默认对象并将其插入到map中。只有在此之后,才会进行best的赋值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接