The Board class design

Coordinator
Sep 23, 2013 at 8:04 AM
I'm making this discussion public so that project participants and non-project members can share their ideas and propose better ways of executing the concept(s) presented in the topic.

As the overall design of the program improves, we'll start decomposing the objects in the game, isolate and flesh out each one, starting with (arguably) the simplest: the game board. When you think of a game board, you usually focus on the context in which the board object is used. For example, it doesn't makes sense to set all board blocks of a chessboard to full/empty, because there is not a single instance in a game of chess where the board is completely full/empty. Likewise, different games involving board have different set of governing rules and thus, different starting conditions. Obviously, although boards are pretty much drawn in one specific way, the details pertaining to different kinds of boards can vary. So, when thinking in terms of top down approach to an object and encapsulating all these varying behaviours, along with the fact that it must be relatively simple (at least at the initial phases), this is one way to represent a conceptually generic board in C++
class IGameBoard
{
public: 
    virtual ~IGameBoard() {}; 

    virtual void Draw() const = 0; 
    virtual void Init() = 0; 
}; 
As you can see, this is a simple interface class. Because we're primarily interested in representing a tic tac toe board, the extension of this class can be represented
// Allow the creation of 3+ sized square boards where 
// B - denotes board
// r - denotes rows/columns
template <class B = Mark, size_t r = 3> 
class TicTacToeBoard : public IGameBoard 
{
    TicTacToeBoard() { Init(); } 
    
    virtual ~TicTacToeBoard() {}

    virtual void Draw() const; 
    virtual void Init(); 

    bool Victory(Mark m) const; 
    bool Tie() const; 
    void Update(Position p, Mark m); 
    
    bool isEmpty(Position p) const; 
    bool isFull() const; 

private: 
    Mark board[r][r]; 
}; 

template <class B, size_t r> 
void TicTacToeBoard<B, r>::Draw() const
{
    // Unspecified and subject to modification if it needs 
    // to interact with other components 
    ...
}


template <class B, size_t r> 
void TicTacToeBoard<B, r>::Init()
{
    for (size_t i = 0; i < r; ++i)
        for (size_t j = 0; j < r; ++j)
            board[i][j] = EMPTY; 
}

template <class B, size_t r> 
inline bool TicTacToeBoard<B, r>::isEmpty(Position p) const 
{
    return board[p.row][p.col] == EMPTY; 
}
...
where Position represents a particular set of coordinates (for a board or a button) and Mark
is just an old style enum for all possible states of a given board block. Now, it is clear that the board uses a stack-based representation, but this can change with relative ease. It would be nice to discuss the other options, like vector of vectors and the different trade-offs, so feel free to state and explain your suggestions. In a typical session, the board will be instantiated like this
TicTacToeBoard <> board; 
 
You can change the internal representation of course, by replacing Mark with a suitable substitute.