Assignment Last: Tic Tac Toe Game


In this assigment – our last – we want to create a computer program that allows two people to play a variation of "Tic Tac Toc" with each other.

The rules are simple: Tic Tac Toe is played on an N by N grid. Two players play, one can place X’s on the board, the other O’s. The player who obtains N X’s (or N O’s) in a row – vertical, horizontal, or diagonal – wins. The program should be able to handle N =3, 4, 5, …, 8.

The computer’s job is to keep track of the moves that the players make, inform them if anyone has won, and prevent them from making incorrect moves. It should first ask player "one" to make a move, asking for the row and column of where the "X" is to be placed. Then it should do the same for player "two", placing an "O" in the appropriate row and column. It should alternately ask the players, checking after each move if a player has won (or if the game is over because there’s no more room let to place a piece).


Here is a suggested outline of the ingredients that might make up a successful program. However, as always you are welcome to follow these suggestions or to come up with your own design for this program:

Constants:

const char EMPTY = '.';
const char PLAYER1 = 'X';
const char PLAYER2 = 'O';
const int DIM = 4;

Types:

typedef char Board[DIM][DIM];

Functions:

void initBoard(Board board)

Initializes the board so that each cell contains the EMPTY character.

void showBoard(Board board)

Displays the board on the screen

int isRowFull(Board board, int row, char player)

Checks whether the row row contains DIM pieces of type player. Returns 1 (true) if there are DIM pieces of type player in row row, or 0 (false) otherwise. As we’ve discussed in class, a possible implementation of this function could be:

int isRowFull(Board board, int row, char player)
{
   int sum = 0;
   for (int col = 0; col < DIM; col++)
      if (board[row][col] == player)
         sum++;
   return (sum == DIM);
}
 int isColFull(Board board, int col, char player)

Checks whether the column col contains DIM pieces of type player. Returns 1 (true) if there are DIM pieces of type player in column col, or 0 (false) otherwise.

int isAnyRowFull(Board board, char player)

Checks whether any of the DIM rows are full by using the function isRowFull. Returns 1 (true) if any row contains DIM pieces of type player, or 0 (false) otherwise. As discussed in class, a possible implementation of this function might be:

int isAnyRowFull(Board board, char player) 
{ 
   for (int row = 0; row < DIM; row++) 
      if (isRowFull(board, row, player)) 
         return 1; 
   return 0; 
}
int isAnyColFull(Board board, char player)

Checks whether any of the DIM columns are full by using the function isColFull. Returns 1 (true) if any column contains DIM pieces of type player, or 0 (false) otherwise.

int isMajorDiagFull(Board board, char player)

Checks whether the major diagonal is full. Returns 1 (true) if the major diagonal contains DIM pieces of type player, 0 (false) otherwise.

int isMinorDiagFull(Board board, char player)

Checks whether the minor diagonal is full. Returns 1 (true) if the minor diagonal contains DIM pieces of type player, 0 (false) otherwise. As discussed in class, this function might look like this:
 

int isMinorDiagFull(Board board, char player) 
{ 
   int sum = 0; 
   for (int i = 0; i < DIM; i++) 
      if (board[i][DIM-i-1] == player)
         sum++; 
   return (sum == DIM); 
}
int hasPlayerWon(Board board, char player)

Checks if the player player has won. Returns 1 if player player has DIM pieces in a row, horizontally, vertically, or diagonally. Consists basically of an if – else if … – else statement, using the previous functions isAnyRowFull, isAnyColFull, isMajorDiagFull, and isMinorDiagFull.

int isBoardFull(Board board)

Checks if there are any empty spots left on the board. Returns 1 if there are no more empty spots left, 0 otherwise. The function basically counts the number of EMPTY pieces in the table. If that sum is 0, no free spots are left (and the function consequently returns 1).

void getMove(Board board, char player)

Asks the player player to enter an integer for the row and for the column. Then – if it’s legal to do so – places the piece corresponding to player at that spot in the board and calls the "showBoard" function to display the new board. The function should check:

whether the spot the user has chosen is still empty
whether the spot the user has chosen is actually on the board

The function should continue to ask for input until a valid move has been entered by the user.


Once these functions are defined, the main function of the board could follow this algorithm to complete the program:

int main(void)
{

// define a variable board of type Board and initialize it
// show the empty board to start the game
// while (neither PLAYER1 nor PLAYER2 have won, and the board is not full)
// {
//      get player PLAYER1 to make a move (note that tge function getMove also displays the board again)
//      if (PLAYER1 has not won and the board is not full)
//         get player PLAYER2 to make a move (note again that getMove again displays the board)
// }

// Note: if the loop is over, either a player has won or the board is full, so:
// if (player PLAYER1 has won), say so
// else if (player PLAYER2 has won), say so
// else the board must be full and the game ends in a tie.

         return 0;
}


The program is due at the same time we take our final.