I'm doing a console checkers in C++. The problem is I can't refer to methods of forward-declared class.
Here's a header of Board class.
#define BOARD_H
#include "Square.h"
#include <vector>
#include <map>
class Man;
typedef std::vector<Square*> Column;
class Board
{
const int BOARD_SIZE = 8;
std::vector<Column> squares;
std::map<Location, Square*> locationSquareMap; //still kinda secret for me
public:
Board();
~Board();
//Board(Board& board);
void printBoard();
std::map<Location, Square*> getLocationSquareMap();
};
#endif
And it's implementation.
Here (printBoard()) I try to access man object via pointer, but I cannot do this because of incomplete type error.
#include "Board.h"
Board::Board()
{ //white black
for (int row = 0; row < BOARD_SIZE; row++)
{
squares.push_back(Column());
for (int column = 0; column < BOARD_SIZE; column++)
{
Location currentLocation(File(column), row);
SquareColor currentSquareColor = SquareColor::WHITE;
if ((column + row) % 2 == 0) //lol the bug was here, forgot about brackets
{
currentSquareColor = SquareColor::BLACK;
}
Square* currentSquare = new Square(currentLocation, currentSquareColor);
locationSquareMap.insert(std::make_pair(currentSquare->getLocation(), currentSquare));
squares.at(row).push_back(currentSquare);
}
}
}
Board::~Board()
{
}
void Board::printBoard()
{
for (int i = squares.size() - 1; i != -1; i--)
{
for (int g = squares.at(i).size() - 1; g != -1; g--)
{
std::cout << *(squares.at(i).at(g)) << std::endl;
}
}
std::cout << " ";
for (int i = 0; i < BOARD_SIZE; i++)
{
switch (File(i))
{
case File::A : std::cout << "A "; break;
case File::B : std::cout << "B "; break;
case File::C : std::cout << "C "; break;
case File::D : std::cout << "D "; break;
case File::E : std::cout << "E "; break;
case File::F : std::cout << "F "; break;
case File::G : std::cout << "G "; break;
case File::H : std::cout << "H "; break;
default: std::cout << " "; break;
}
}
std::cout << std::endl << std::endl;
for (int i = squares.size() - 1; i != -1; i--)
{
std::cout << i << " ";
for(int g = 0; g < squares.at(i).size(); g++)
{
Man* currentMan;
if (squares.at(i).at(g)->getIsOccupied())
{
currentMan = squares.at(i).at(g)->getCurrentMan();
//currentMan-> can't refer to methods
}
else
{
std::cout << "_ ";
}
}
std::cout << std::endl;
}
}
std::map<Location, Square*> Board::getLocationSquareMap()
{
return locationSquareMap;
}
Man's header:
#ifndef MAN_H
#define MAN_H
#include "ManColorEnum.cpp"
#include "Square.h"
#include <iostream>
#include <string>
#include <vector>
#include "LocationFactory.h"
#include "Board.h"
class Man
{
ManColor color;
Square* currentSquare;
bool isKing;
public:
Man(ManColor color, Square* square);
~Man();
//Man(Man& man);
Square* getCurrentSquare();
void setCurrentSquare(Square* square);
bool getIsKing();
void setIsKing();
ManColor getColor();
void makeMove(Square* square);
std::vector<Location> getValidMoves(Board* board);
friend std::ostream& operator<<(std::ostream& ostream, const Man& man);
};
#endif
Man's .cpp file:
#include "Man.h"
Man::Man(ManColor color, Square* square)
{
this->color = color;
this->currentSquare = square;
this->isKing = false;
}
Man::~Man()
{
//dtor
}
ManColor Man::getColor()
{
return color;
}
std::vector<Location> Man::getValidMoves(Board* board)
{
std::vector<Location> moveCandidates{};
if (!isKing)
{
Location currentLocation = this->currentSquare->getLocation();
std::map<Location, Square*> squareMap = board->getLocationSquareMap();
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 1, 1)); //move one right forward
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -1, 1)); //move one left forward
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, 2)); //capture forward right
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, 2)); //capture forward left
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, -2)); //capture backwards right
moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, -2)); //capture backwards left
//TODO have to capture
for (int i = 0; i < moveCandidates.size(); i++)
{
//here I filter for moves to exist on the board
if (squareMap.count(moveCandidates.at(i)) == 0)
{
moveCandidates.erase(moveCandidates.begin() + i);
}
//here I filter occupied squares
if (squareMap[moveCandidates.at(i)]->getIsOccupied())
{
moveCandidates.erase(moveCandidates.begin() + i);
}
//here I filter capture moves
File currentFile = moveCandidates.at(i).getFile();
int currentRank = moveCandidates.at(i).getRank();
Square* preSquare = nullptr;
for (std::map<Location, Square*>::iterator it = squareMap.begin(); it != squareMap.end(); it++)
{
//check capture forward right
if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank + 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank + 1)
{
preSquare = itr->second;
break; //check to be careful here
}
}
//if (it->second->getIsOccupied()
// || (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
// || (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
//{
// moveCandidates.erase(moveCandidates.begin() + i);
// break; //check to be careful here
//}
}
//check capture backward right
else if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank - 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank - 1)
{
preSquare = itr->second;
break;
}
}
}
//check capture forward left
else if (int(it->first.getFile()) == int(currentFile) -2 && it->first.getRank() == currentRank + 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank + 1)
{
preSquare = itr->second;
break;
}
}
}
//check capture backwards left
else if (int(it->first.getFile()) == int(currentFile) - 2 && it->first.getRank() == currentRank - 2)
{
for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
{
if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank - 1)
{
preSquare = itr->second;
break;
}
}
}
if (it->second->getIsOccupied()
|| (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
|| (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
{
moveCandidates.erase(moveCandidates.begin() + i);
break; //check to be careful here
}
}
}
}
return moveCandidates;
}
Square* Man::getCurrentSquare()
{
return currentSquare;
}
void Man::setCurrentSquare(Square* square)
{
this->currentSquare = square;
}
bool Man::getIsKing()
{
return isKing;
}
void Man::setIsKing()
{
isKing = true;
}
void Man::makeMove(Square* square)
{
this->currentSquare->reset();
this->currentSquare = square;
}
std::ostream& operator<<(std::ostream& ostream, const Man& man)
{
std::string colorStr;
switch (man.color)
{
case ManColor::BLACK: colorStr = "BLACK"; break;
case ManColor::WHITE: colorStr = "WHITE"; break;
default: colorStr = "COLOR";
}
return std::cout << "Man { color=" << colorStr << " } " << std::endl;
}