Skip to main content
Tweeted twitter.com/StackCodeReview/status/1503566676490608644
Became Hot Network Question
More descriptive title
Link
Toby Speight
  • 81.7k
  • 14
  • 101
  • 308

Learning C++ checking usage of ENUM Tic-tac-toe game with Board class and STRUCTenum for players

edited tags
Link
user673679
  • 11.9k
  • 2
  • 33
  • 65
Source Link

Learning C++ checking usage of ENUM and STRUCT

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: PLAYERto 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?