diff --git a/ms_board.c b/ms_board.c index bdd525b..02a2dad 100644 --- a/ms_board.c +++ b/ms_board.c @@ -14,6 +14,100 @@ #include "config.h" -/** Implementation of Mine Sweeper board data */ +struct MsBoardData { + Count column_count; + Count row_count; + MsCell cells[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; +}; -/** The private singleton instance of the board data. */ +static MsBoard the_board = 0; + +/** + * Provides the instance of the 'Mine Sweeper' board. + * Exactly one instance is supported. The board state + * is not affected by this function. + * + * @return The board instance. + */ +MsBoard msb_get_board() { + if (the_board == 0) { + the_board = (MsBoard)GC_MALLOC(sizeof(struct MsBoardData)); + } + return the_board; +} + +/** + * Initializes the only Mine Sweeper board: + * + Defines the actual size of the board (columns and rows) up to the configured values. + * + Initializes all cells as 'empty' and 'covered'. + * The number of columns and rows shall be clipped to MAX_BOARD_SIZE. + * + * @param board The board instance in focus. + * @param column_count The number of cell columns of the board. + * @param row_count The number of cell row of the board. + */ +void msb_init_board(MsBoard board, Count column_count, Count row_count) { + if (board == 0) { + return; + } + + board->column_count = column_count > MAX_BOARD_SIZE ? MAX_BOARD_SIZE : column_count; + board->row_count = row_count > MAX_BOARD_SIZE ? MAX_BOARD_SIZE : row_count; + + for (int row = 0; row < board->row_count; row++) { + for (int col = 0; col < board->column_count; col++) { + board->cells[col][row] = msc_produce_cell(); + } + } +} + +/** + * Determines whether or not the given board is valid. + * A board is NOT valid + * + if it is 0, + * + or if it has a size of 0 (0 columns or 0 rows). + * + * @param board The board instance in focus. + * @return True if the given board is valid, false otherwise. + */ +bool msb_is_valid(MsBoard board) { + return board != 0 && board->column_count > 0 && board->row_count > 0; +} + +/** + * Provides the cell at the given coordinates. + * + * @param board The board instance in focus. + * @param col_idx The index of the column of the addressed cell. + * @param row_idx The index of the row of the addressed cell. + * @return The addressed cell or 0, if the coordinates are not in range. + */ +MsCell msb_get_cell(MsBoard board, CellIdx col_idx, CellIdx row_idx) { + if (!msb_is_valid(board) || col_idx >= board->column_count || row_idx >= board->row_count) { + return 0; + } + + return board->cells[col_idx][row_idx]; +} + +/** + * Provides the number of columns used by the current game (of the 'active' area). + * + * @param board The board instance in focus. + * @return The number of columns used for the current board configuration or 0, + * if the board is not configured or invalid. + */ +Count msb_get_column_count(MsBoard board) { + return msb_is_valid(board) ? board->column_count : 0; +} + +/** + * Provides the number of rows used by the current game (of the 'active' area). + * + * @param board The board instance in focus. + * @return The number of columns used for the current board configuration or 0, + * if the board is not configured or invalid. + */ +Count msb_get_row_count(MsBoard board) { + return msb_is_valid(board) ? board->row_count : 0; +} \ No newline at end of file