首页 > 解决方案 > C++ 将包含多态属性的类对象存储在堆栈中

问题描述

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

代码(更新)

由于源代码太大,无法在此处发布,我认为最好留下我的 GitHub 帐户的链接,在那里可以找到它:https ://github.com/lbragile/chessCAMO

描述

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

包含作品的:

片类型类

包括:

这些继承自基类(Piece

问题

通过这种设置,ChessPiece是独立的类(一个不是从另一个派生的)。但是,为了跟踪堆栈中的棋盘位置,Chess类使用成员变量:

stack<vector<Piece*>> board_positions;

事实上,这确实允许我撤消该位置,甚至在之后进行移动。但是,在通过我的测试用例运行我的算法之后,我注意到它在涉及check、double check、checkmate 和 stalemate 标志的情况下失败了。当我检查我的 GUI 时,这一点得到了证实。例如,做出一个导致检查的动作,然后“撤消”该动作,并再次重复该动作。这失败了,因为没有存储前一个位置的检查标志。

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

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

编辑#1

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

编辑#2

请参阅下面的答案,我使用Chess对象的序列化/反序列化解决了问题。

标签: c++oopchess

解决方案


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;
};

国际象棋.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;
}

感谢大家提供的帮助!


推荐阅读