2011-05-04 107 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是主教類的一個實例。