I've been learning C++ on my own and working solo on trying to implement some of the concepts I've been reading.
I'm wondering if this is the correct group to get someone to point me to other info regarding the code I've wrote or if I'm getting the concepts right.
I've tried to build Tic Tac Toe using a class system. I've implemented 2 ENUMS: PLAYER
to manage the current player and populate the board with data. and also BOARDSTATUS
to ease of access to the current state of the board internal for the Board Class.
I've created a STRUCT: BoardMove
that contains all the information needed to place a move in the board. This way I can use it via the AI Class that has it's on Board for recursivelycheck the possible moves and also it can be accessed by the Game itself to submit player moves.
Here is the Board class header file:
#define ROWS 3
#define COLS 3
#define CHECKS 3
enum class PLAYER { BLANK = ' ', PLAYER1 = 'X', PLAYER2 = 'O' };
struct BoardMove
{
int row;
int col;
PLAYER playerTurn;
};
class Board
{
public:
enum class BOARDSTATUS { CLEAR, WINPLAYER1, WINPLAYER2, DRAW };
Board();
~Board();
void PrintBoard();
bool InsertMove(BoardMove newMove);
inline BOARDSTATUS GetBoardStatus() { return this->boardState; }
PLAYER board[ROWS][COLS];
private:
BOARDSTATUS boardState;
void ClearBoard();
void CheckStatus(PLAYER player);
bool AllFieldsTheSame(unsigned int startRows, unsigned int startCols, unsigned int deltaRow, unsigned int deltaCol);
unsigned int numberOfPlays = 0;
};
Here is the Board Class implementation:
Board::Board()
{
this->ClearBoard();
}
Board::~Board()
{}
//
// Foud good solution here:
// https://stackoverflow.com/questions/1056316/algorithm-for-determining-tic-tac-toe-game-over
//
void Board::CheckStatus(PLAYER player)
{
bool win = false;
for(int i = 0; i < ROWS; i++)
{
if(AllFieldsTheSame(i, 0, 1, 0))
win = true;
}
for(int i = 0; i < COLS; i++)
{
if(AllFieldsTheSame(0, i, 0, 1))
win = true;
}
if(AllFieldsTheSame(0, 0, 1,1))
win = true;
if(AllFieldsTheSame(2, 0, -1, 1))
win = true;
if(win == true)
this->boardState = (player == PLAYER::PLAYER1) ? BOARDSTATUS::WINPLAYER1 : BOARDSTATUS::WINPLAYER2;
else if(this->numberOfPlays == 8)
this->boardState = BOARDSTATUS::DRAW;
}
//
// Foud good solution here:
// https://stackoverflow.com/questions/1056316/algorithm-for-determining-tic-tac-toe-game-over
//
bool Board::AllFieldsTheSame(unsigned int startRows, unsigned int startCols, unsigned int deltaRow, unsigned int deltaCol)
{
PLAYER firstField = this->board[startRows][startCols];
if(firstField == PLAYER::BLANK)
{
return false;
}
for(int i = 0; i < CHECKS; i++)
{
int y = startCols + deltaCol * i;
int x = startRows + deltaRow * i;
if(this->board[y][x] != firstField)
{
return false;
}
}
return true;
}
void Board::PrintBoard()
{
for(int i = 0; i < ROWS; i++)
{
for(int j = 0; j < COLS; j++)
{
std::cout << " " << static_cast<char>(this->board[i][j]) << PLAYER::BLANK;
std::cout << " | ";
if(j == 2)
std::cout << "\n";
}
if(i < 2)
std::cout << "--------------\n";
}
}
bool Board::InsertMove(BoardMove newMove)
{
if(this->board[newMove.row][newMove.col] == PLAYER::BLANK)
{
this->board[newMove.row][newMove.col] = newMove.playerTurn;
this->numberOfPlays++;
this->CheckStatus(newMove.playerTurn);
return true;
}
return false;
}
void Board::ClearBoard()
{
for(int i = 0; i < ROWS; i++)
{
for(int j = 0; j < COLS; j++)
{
this->board[i][j] = PLAYER::BLANK;
}
}
this->boardState = BOARDSTATUS::CLEAR;
}
I've made PLAYER
and BoardMove
publicly available because I call them directly from the my Game and AI classes. Should I make sure that they are only accessible from the Board Class and have functions to get that info?