Reputation: 8122
I am attempting to make a chess game from scratch and made significant progress over the past couple of months. However, I recently got stuck on a problem that I just cannot figure out how to solve.
CODE (UPDATED)
Since the source code is too large to post here, I think it is best to leave a link to my GitHub account where it can be found: https://github.com/lbragile/chessCAMO
DESCRIPTION
Chess
Contains relevant game flags and turn tracking, as well as keeps a stack of the board positions to allow a player to undo moves.
Piece
Contains the piece's:
Piece Type classes
Includes:
These inherit from the base class (Piece)
QUESTION
With this set up, Chess and Piece are separate classes (one is not derived from the other). However, to keep track of the board positions in a stack, the Chess class uses the member variable:
stack<vector<Piece*>> board_positions;
This does in fact allow me to undo the position and even make moves afterwards. However, after running my algorithm through my test cases, I noticed that it fails the cases involving flags for check, double check, checkmate, and stalemate. When I checked with my GUI, this was confirmed. For example, making a move which causes a check, then "undoing" that move, and repeating the move again. This fails since the check flag of the previous position is not stored.
This leads to the obvious conclusion that I must store the entire Chess object at each move so that I get both the board representation and the corresponding necessary flags. I just cannot figure out how to have a member variable in the class Chess that can store Chess objects in a stack. The main reason is that Chess itself contains Piece objects in it which are polymorphic (virtual functions) and the two classes are separate.
Any suggestions or helpful tips as to how to proceed would be much appreciated.
EDIT #1
I updated the code using the suggestions provided. However, my current problem is that the board flags do not seem to update on the stack. This seems to stem from the ~Chess()
. I think it is not actually destroying the object pointers but rather simply popping them. I attempted using std::move()
to move the resources in makeMove(int src, int dest, istream &in)
from temp_chess
in the pushInfo()
function of the if statement and deleting the game_info
pointer in the destructor, however this doesn't seem to fix the issue.
EDIT #2
See my answer below, I solved the problem using serialization/de-serialization of the Chess
object.
Upvotes: 2
Views: 460
Reputation: 8122
I managed to solve the problem by serializing/de-serializing the Chess
object's private members to a file.
The way I did this was by making a separate folder which stores these files and added a move counting private member to Chess
. Then I added the serializing functionality using the overloaded extraction and insertion operators:
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;
}
Thank you to all for the help you provided!
Upvotes: 2