Создание клона абстрактного класса - PullRequest
2 голосов
/ 04 мая 2011

Я пишу шахматную программу, и у меня есть аннотация класс с именем 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;
  }
}

Я хочу иметь возможность ссылаться на этот класс без использования указателя, чтобы не вносить постоянные изменения в доску.

Ответы [ 3 ]

4 голосов
/ 04 мая 2011

Вам нужно предоставить каждому классу виртуальную функцию Clone (), которая для Бишопа будет выглядеть так:

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();
    }
}
2 голосов
/ 04 мая 2011

Вам нужен абстрактный метод

 Piece *Piece::Duplicate()

, а затем реализовать его в подклассах, т.е.

 class Bishop {
   Bishop(const Bishop &b) { ... } // copy constructor
   Piece *Duplicate() { Bishop *n = new Bishop(*this); // calls copy constructor
     return n; }
 }
1 голос
/ 04 мая 2011

Или вы можете написать конструктор копирования в классе Bishop, который, в свою очередь, реализует глубокое копирование, предполагая, что currentBoard является экземпляром класса Bishop.

...