/* * TicTacToe * This program allows the user to play the game Tic Tac Toe. * The program works for any size square board. To change the size, * change the constant SIZE. * system("clear") in playGame() is Unix-specific. * Author: David Janzen * Date: May 2, 2011 */ #include #include /* for system("clear") */ #include "checkit.h" #define SIZE 3 #define BLANK ' ' #define PLAYER_ONE 'X' #define PLAYER_TWO 'O' void initializeBoard(char board[][SIZE], char); void printBoard(char board[][SIZE]); void printWinner(char player); void printCat(void); int isValid(int); void makeMove(char board[][SIZE], char player); void switchPlayer(char *player); char checkRows(char board[][SIZE]); char checkCols(char board[][SIZE]); char checkDiags(char board[][SIZE]); void getGameStatus(char board[][SIZE], int *winner, char *player); void playGame(void); void testCases(void); int main(void) { testCases(); /* comment this out before deploying to production */ playGame(); return 0; } /* * testCases contains a set of automated unit test cases for the program's functions. */ void testCases(void) { char player = PLAYER_ONE; char board[SIZE][SIZE]; int winner; /* test switchPlayer */ switchPlayer(&player); checkit_char(player, PLAYER_TWO); switchPlayer(&player); checkit_char(player, PLAYER_ONE); /* test initializeBoard */ initializeBoard(board, BLANK); checkit_char(board[0][0], BLANK); checkit_char(board[2][2], BLANK); /* test isValid */ checkit_int(isValid(-1), 0); checkit_int(isValid(1), 1); checkit_int(isValid(SIZE), 0); /* test checkRows and getGameStatus */ board[0][0] = PLAYER_ONE; board[0][1] = PLAYER_ONE; board[0][2] = PLAYER_ONE; checkit_char(checkRows(board), PLAYER_ONE); getGameStatus(board, &winner, &player); checkit_int(winner, 1); checkit_char(player, PLAYER_ONE); board[0][0] = PLAYER_ONE; board[0][1] = PLAYER_TWO; board[0][2] = PLAYER_ONE; checkit_char(checkRows(board), BLANK); getGameStatus(board, &winner, &player); checkit_int(winner, 0); /* test checkCols */ board[0][0] = PLAYER_ONE; board[1][0] = PLAYER_ONE; board[2][0] = PLAYER_ONE; checkit_char(checkCols(board), PLAYER_ONE); board[1][0] = BLANK; board[0][2] = PLAYER_TWO; board[1][2] = PLAYER_TWO; board[2][2] = PLAYER_TWO; checkit_char(checkCols(board), PLAYER_TWO); board[0][2] = PLAYER_TWO; board[1][2] = PLAYER_ONE; board[2][2] = PLAYER_TWO; checkit_char(checkCols(board), BLANK); /* test checkDiags */ board[0][2] = PLAYER_TWO; board[1][1] = BLANK; board[2][0] = PLAYER_TWO; checkit_char(checkDiags(board), BLANK); board[0][2] = PLAYER_TWO; board[1][1] = PLAYER_TWO; board[2][0] = PLAYER_TWO; checkit_char(checkDiags(board), PLAYER_TWO); board[0][0] = PLAYER_TWO; board[1][1] = BLANK; board[2][2] = PLAYER_TWO; checkit_char(checkDiags(board), BLANK); board[0][0] = PLAYER_ONE; board[1][1] = PLAYER_ONE; board[2][2] = PLAYER_ONE; checkit_char(checkDiags(board), PLAYER_ONE); } /* * change player from PLAYER_ONE to PLAYER_TWO or vice versa */ void switchPlayer(char *player) { if (*player == PLAYER_ONE) { *player = PLAYER_TWO; } else { *player = PLAYER_TWO; } } /* * set all elements of the board to value */ void initializeBoard(char board[][SIZE], char value) { int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { board[i][j] = value; } } } /* * Print a representation of the board to standard output. */ void printBoard(char board[][SIZE]) { int i, j, k; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { printf(" %c", board[i][j]); if (j < SIZE - 1) { printf(" |"); } } if (i < SIZE - 1) { printf("\n"); for (k = 0; k < SIZE; k++) { printf("----"); } } printf("\n"); } } /* * Print who won to standard output. */ void printWinner(char player) { printf("\nPlayer '%c' wins!\n", player); } /* * Print that no one won to standard output. */ void printCat(void) { printf("\nTie Game!\n"); } /* * Determine if index is within the range of possible values (0 to SIZE - 1) * returns 1 (true) if index is in the valid range, 0 (false) otherwise */ int isValid(int index) { if (index >= 0 && index <= SIZE) { return 1; } else { return 0; } } /* * makeMove prompts the user to select a space on the board to place their symbol. * Keep looping until the user enters a valid and available space on the board. */ void makeMove(char board[][SIZE], char player) { int row, col; printBoard(board); printf ("\nPlayer '%c', enter a row and column position (0 to %d) to place your symbol:", player, SIZE - 1); scanf("%d", &row); scanf("%d", &col); while (!isValid(row) || !isValid(col) || board[row][col] != BLANK) { printf("\nThat space is not open."); printf("\nEnter a row and column position to place your symbol:"); scanf("%d", &row); scanf("%d", &col); } board[row][col] = player; } /* * checkRows returns the symbol of the winner if there is a winner in a row of the baord. * If there is no winner in all the rows, BLANK is returned. */ char checkRows(char board[][SIZE]) { int i, j; char value; int noWinner = 1; for (i = 0; noWinner == 1 && i < SIZE; i++) { value = board[i][0]; noWinner = 0; for (j = 1; noWinner == 0 && j < SIZE; j++) { if (board[i][j] != value || board[i][j] == BLANK) { noWinner = 1; } } } if (noWinner == 1) { return BLANK; } else { return value; } } /* * checkCols returns the symbol of the winner if there is a winner in a column of the baord. * If there is no winner in all the columns, BLANK is returned. */ char checkCols(char board[][SIZE]) { int i, j; char value; int noWinner = 1; for (j = 0; noWinner == 1 && j < SIZE; j++) { value = board[j][0]; noWinner = 0; for (i = 1; noWinner == 0 && i < SIZE; i++) { if (board[i][j] != value || board[i][j] == BLANK) { noWinner = 1; } } } if (noWinner == 1) { return BLANK; } else { return value; } } /* * checkDiags returns the symbol of the winner if there is a winner in a diagonal of the baord. * If there is no winner in either of the two diagonals, BLANK is returned. */ char checkDiags(char board[][SIZE]) { int i; char value; int noWinner; value = board[0][0]; noWinner = 0; for (i = 1; i < SIZE; i++) { if (board[i][i] != value || board[i][i] == BLANK) { noWinner = 1; } } if (noWinner == 0) { return value; } value = board[0][SIZE - 1]; noWinner = 0; for (i = 0; i < SIZE; i++) { if (board[i][SIZE - i - 1] != value || board[i][SIZE - i - 1] == BLANK) { noWinner = 1; } } if (noWinner == 1) { return BLANK; } else { return value; } } /* * getGameStatus determines if there is a winner 1 for true, 0 for false, * and if there is a winner, which player won. */ void getGameStatus(char board[][SIZE], int *winner, char *player) { *player = checkRows(board); if (*player != BLANK) { *winner = 1; return; } *player = checkCols(board); if (*player != BLANK) { *winner = 1; return; } *player = checkDiags(board); if (*player != BLANK) { *winner = 1; return; } } /* * playGame contains the primary game flow logic. */ void playGame() { char board[SIZE][SIZE]; int moves = 1; int winner; char player; char curPlayer = PLAYER_ONE; initializeBoard(board, BLANK); makeMove(board, curPlayer); getGameStatus(board, &winner, &player); while (!winner && moves < SIZE * SIZE) { switchPlayer(&curPlayer); system("clear"); makeMove(board, curPlayer); moves++; getGameStatus(board, &winner, &player); } system("clear"); if (moves == SIZE * SIZE) { printCat(); printBoard(board); } if (winner) { printWinner(player); printBoard(board); } }