C++ 在堆栈中存储 class 个包含多态属性的对象

C++ Store class objects which contain polymorphic properties in a stack

我正在尝试从头开始制作国际象棋游戏,并在过去几个月取得了重大进展。但是,我最近遇到了一个我无法解决的问题。

CODE (UPDATED)

由于源码太大,post放在这里,我觉得最好留一个link到我的GitHub账号,在那里可以找到:https://github.com/lbragile/chessCAMO

DESCRIPTION

国际象棋

包含相关的游戏标志和回合跟踪,并保留 棋盘位置堆栈 以允许玩家撤消移动。

包含作品的:

片类型classes

包括:

这些继承自基础class (Piece)

QUESTION

有了这个设置,ChessPiece 是分开的 classes(一个不是从另一个派生的) . 但是,为了跟踪堆栈中的棋盘位置,Chess class 使用成员变量:

stack<vector<Piece*>> board_positions;

这实际上让我可以撤消头寸,甚至可以在之后进行操作。然而,在 运行 我的算法通过我的测试用例之后,我注意到它在涉及 检查、双重检查、将死和僵持 标志的情况下失败了。当我检查我的 GUI 时,这已得到确认。例如, 进行导致检查的移动,然后“撤消”该移动,然后再次重复该移动。由于未存储先前位置的检查标志,因此失败。

这导致了一个明显的结论,即我必须在每次移动时存储整个 Chess 对象,以便我同时获得 棋盘表示 相应的必要标志。我只是不知道如何在 class Chess 中有一个成员变量可以将 Chess 对象存储在堆栈中。主要原因是 Chess 本身包含 Piece 对象,这些对象是 polymorphic (虚函数)和两个 class 是 分开的 .

任何关于如何进行的建议或有用的提示将不胜感激。

EDIT #1

我根据提供的建议更新了代码。然而,我目前的问题是板 flags 似乎没有在堆栈上更新。这似乎源于~Chess()。我认为它实际上并没有破坏对象指针,而是简单地弹出它们。我尝试在 if 语句的 pushInfo() 函数中使用 std::move()makeMove(int src, int dest, istream &in) 中的资源从 temp_chess 中移动,并删除析构函数中的 game_info 指针,但是这似乎无法解决问题。

EDIT #2

请参阅下面的答案,我使用 Chess 对象的 serialization/de-serialization 解决了问题。

我设法通过 serializing/de-serializing 将 Chess 对象的私有成员添加到文件来解决问题。

我这样做的方法是创建一个单独的文件夹来存储这些文件,并向 Chess 添加一个移动计数私人成员。然后我使用重载的提取和插入运算符添加了序列化功能:

chess.h

class Chess
{
public:
    // previous functions
    
    // Accessor/mutator functions for number of moves made
    int getNumMoves() { return num_moves;}
    void setNumMoves(int num_moves) {this->num_moves = num_moves;}        

    // to serialize (write the object to a file)
    friend ostream & operator << (ostream &out, const Chess &chess_object);

    // to de-serialize (read in the object from a file)
    friend istream & operator >> (istream &in, Chess &chess_object);

private:
    // previous members
    
    int num_moves;
};

chess.cpp

// puts each member field on a new line
ostream & operator << (ostream &out, const Chess &chess_object)
{
    for(const auto & elem : chess_object.getBoard())
        out << elem->getPieceType() << endl << elem->getPieceSquare() << endl << elem->getPieceColor() << endl
            << elem->getPieceMoveInfo() << endl << elem->getEnPassantLeft() << endl << elem->getEnPassantRight() << endl;

    out << chess_object.getCheck() << endl << chess_object.getDoubleCheck() << endl << chess_object.getCheckmate() << endl << chess_object.getStalemate() << endl;

    out << chess_object.getTurn() << endl;

    return out;
}


istream & operator >> (istream &in, Chess &chess_object)
{
    // delete the allocated memory and restore new data
    vector<Piece*> board = chess_object.getBoard();
    for(unsigned int i = 0; i < board.size(); i++)
        delete board[i];
    // board.clear();

    string input;
    for(auto & elem : board)
    {
        in >> input;
        switch(input[0] - '0')
        {
            case 0:
                elem = new Pawn(0, PAWN, NEUTRAL);
                break;
            case 1:
                elem = new Knight(0, KNIGHT, NEUTRAL);
                break;
            case 2:
                elem = new Bishop(0, BISHOP, NEUTRAL);
                break;
            case 3:
                elem = new Rook(0, ROOK, NEUTRAL);
                break;
            case 4:
                elem = new Queen(0, QUEEN, NEUTRAL);
                break;
            case 5:
                elem = new King(0, KING, NEUTRAL);
                break;
            default:
                elem = new Empty(0, EMPTY, NEUTRAL);    
        }

        in >> input;
        elem->setPieceSquare(stoi(input));
        in >> input;
        elem->setPieceColor((pieceColor) (input[0] - '0'));
        in >> input;
        elem->setPieceMoveInfo(input == "1");
        in >> input;
        elem->setEnPassantLeft(input == "1");
        in >> input;
        elem->setEnPassantRight(input == "1");
    }

    chess_object.setBoard(board);

    in >> input;
    chess_object.setCheck(input == "1");
    in >> input;
    chess_object.setDoubleCheck(input == "1");
    in >> input;
    chess_object.setCheckmate(input == "1");
    in >> input;
    chess_object.setStalemate(input == "1");

    in >> input;
    chess_object.setTurn((pieceColor) (input[0] - '0'));

    return in;
}

感谢大家提供的帮助!