2011-05-04 108 views
2

我正在写一个国际象棋程序,我有一个名为Pieces摘要类。我用我的主类此抽象类使用指针,就像这样:Pieces * newset = currentboard[][];创建一个抽象类的克隆

如果我让该板的举动实际上是由移动。我想分析该板的当前状态,因此创建该板的副本。我怎么做?

Piece类和什么我做下面给出的样品。

class Piece 
{ 
    public: 
    Piece(char cColor) : mcColor(cColor) {} 
    ~Piece() {} 
    virtual char GetPiece() = 0; 
    virtual int GetValue() = 0; 
    virtual int GetPieceActionValue() = 0; 
    char GetColor() { 
     return mcColor; 
    } 
    bool IsLegalMove(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) { 
     Piece* qpDest = NewBoard[DestRow][DestCol]; 
     if ((qpDest == 0) || (mcColor != qpDest->GetColor())) { 
      return LegalSquares(CurrentRow, CurrentCol, DestRow, DestCol, NewBoard); 
     } 
     return false; 
    } 

    private: 
    virtual bool LegalSquares(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) = 0; 
    char mcColor; 
}; 

这里是一个派生类的一个示例:

class Bishop 
{ 
    public: 
    Bishop(char cColor) : Piece(cColor) {} 
    ~Bishop() {} 

    private: 
    virtual char GetPiece() { 
     return 'B'; 
    } 
    virtual int GetValue() { 
     return 325; 
    } 
    virtual int GetPieceActionValue() { 
     return 3; 
    } 
    bool LegalSquares(int CurrentRow, int CurrentCol, int DestRow, int DestCol, Piece* NewBoard[8][8]) { 
     if ((DestCol - CurrentCol == DestRow - CurrentRow) || (DestCol - CurrentCol == CurrentRow - DestRow)) { 
      // Make sure that all invervening squares are empty 
      int iRowOffset = (DestRow - CurrentRow > 0) ? 1 : -1; 
      int iColOffset = (DestCol - CurrentCol > 0) ? 1 : -1; 
      int iCheckRow; 
      int iCheckCol; 
      for (iCheckRow = CurrentRow + iRowOffset, iCheckCol = CurrentCol + iColOffset; 
       iCheckRow != DestRow; 
       iCheckRow = iCheckRow + iRowOffset, iCheckCol = iCheckCol + iColOffset) 
      { 
       if (NewBoard[iCheckRow][iCheckCol] != 0) { 
        return false; 
       } 
      } 
      return true; 
     } 
     return false; 
    } 
}; 

使用类出招:

if (qpCurrPiece->IsLegalMove(StartRow, StartCol, EndRow, EndCol, NewBoard)) { 

    // Make the move 
    Piece* qpTemp = NewBoard[EndRow][EndCol]; 
    NewBoard[EndRow][EndCol] = NewBoard[StartRow][StartCol]; 
    NewBoard[StartRow][StartCol] = 0; 

    // Make sure that the current player is not in check 
    if (!GameBoard.IsInCheck(mcPlayerTurn)) { 
    delete qpTemp; 
    bValidMove = true; 
    } else { 

    // Undo the last move 
    NewBoard[StartRow][StartCol] = NewBoard[EndRow][EndCol]; 
    NewBoard[EndRow][EndCol] = qpTemp; 
    } 
} 

我希望能够引用此类不使用的指针所以董事会不会做出永久的变更。

回答

2

你需要有一个抽象方法

Piece *Piece::Duplicate() 

,然后执行它的子类,即

class Bishop { 
    Bishop(const Bishop &b) { ... } // copy constructor 
    Piece *Duplicate() { Bishop *n = new Bishop(*this); // calls copy constructor 
    return n; } 
} 
4

您需要提供与虚拟克隆()函数,它为每个类毕晓普看起来像:

Piece * Bishop :: Clone() { 
    return new Bishop(* this); 
} 

现在克隆董事会从OldBoard像这样:

Board newboard; // assume board is 8x8 matrix of Piece * 

for (int i = 0; i < 8; i++) { 
    for (int j = 0; j < 8; j++) { 
     newboard[i][j] = OldBoard[i][j]->Clone(); 
    } 
} 
+0

+1从我这里。有一两件事值得一提的是,这可能是有用的使用上克隆方法协变返回类型,即在主教功能可以返回主教*(即一个没有投当一个人有一个主教实例)。另外,拷贝构造函数和赋值运算符应可能保护 – ds27680 2011-05-04 10:47:10

+1

我很抱歉要扫兴,但发挥真正的电脑下棋,你将不得不这样做一对夫妇的每秒百万次。克隆片段动态记忆是不实际的,除了作为一个练习。也许你应该看看[chessprogramming.wikispaces.com](http://chessprogramming.wikispaces.com/)? – 2011-05-04 15:33:11

1

或者你可以写一个拷贝构造函数毕晓普类又实现了深拷贝假设你currentBoard是主教类的一个实例。