Instructions
Requirements and Specifications
#include
#include //time()
#include //srand() and rand()
typedef struct
{
int occupied; // 0 means unoccupied, 1 means occupied
char symbol; //’X’ or ’O’ or ’ ’
} Cell;
typedef struct
{
Cell cells[3][3]; // 9 spaces in our board
int winner; // 1 if the currentPlayer has won, 0 otherwise
int counter; // for how many turns have been played in total
int size; // should match the dimensions of the ‘cells‘ array
int currentPlayer; // 0 for ’O’s and 1 for ’X’s
} Board;
// In function prototypes, just the type of each argument is sufficient.
Cell initializeCell(char, int);
void getPosition(Board, int[2]);
Board updateBoard(int, int, Board);
int isWinningMove(int, int, Board);
void printBoard(Board);
int main(void)
{
srand(time(NULL));
Board mainBoard;
// TODO: Initialize the members (except for ‘cells‘) of the mainBoard
// to appropriate values. You must choose a random player to start.
// TODO: Initialize each cell in the mainBoard to an unoccupied cell
// with a single space for the symbol. Note that you’ll need a nested
// for loop to do this, since the ‘cells‘ array inside mainBoard is 2D.
// Use your initializeCell() function in the body of the nested for
// loop to do this.
while ((mainBoard.winner == 0) && (mainBoard.counter < 9))
{
// TODO:
// 1) Alternate the mainBoard.currentPlayer
// 2) Create an array that holds 2 ints called ‘position‘
// 3) call the getPosition() function, passing in the ‘mainBoard‘
// and the ‘position‘ array. getPosition() "returns" two
// values by using this array to hold the output values.
// 4) call updateBoard(), passing in the row and column which
// were stored in the ‘position‘ array by getPosition() and
// the ‘mainBoard‘. Assign its return value to mainBoard, effectively
// updating main()’s local mainBoard variable.
// 5) set ‘mainBoard.winner‘ to the return value of isWinningMove().
// Pass in the row and column of the cell that was just played
// and the ‘mainBoard‘.
// 6) call printBoard()
}
if (mainBoard.winner==0)
printf("Tie Game\n");
else
printf("Player %d won\n", mainBoard.currentPlayer);
return 0; }
void printBoard(Board board)
{
// Don’t touch this function. It already prints things nicely for you.
// Note that here, I’m using the first index of the cells array
// as the row, and the second as the column.
for (int row = 0; row < board.size; row++)
{
printf("| ");
for (int column = 0; column < board.size; column++)
{
printf("%c | ", board.cells[row][column].symbol);
}
printf("\n");
}
printf("\n");
}
Cell initializeCell(char sym, int isOccupied)
{
// TODO:
// 1) Create a local variable of type Cell and initialize its
// members according to the arguments passed into this function.
// 2) Return the local variable.
//
// This function is here mainly to show you that you can return structs
// from a function.
}
void getPosition(Board board, int pos[2])
{
int r, c; // Remember, these are local variables to the function
do
{
printf("Enter the row and column: ");
scanf("%d%d", &r, &c);
} while (/*insert condition here*/);
// TODO: Fill in the condition of the while loop above. It should continue
// to ask the user for a row and column as long as the row and column
// the user has asked for is out of bounds OR if the cell is already
// occupied in the board.
// TODO: Assign the desired row ‘r‘ to pos[0] and the desired column ‘c‘
// to pos[1]. Here we’re using the ‘pos‘ array to "return" two values
// back to main(), more specifically the row and column of the cell the user
// wants to play their symbol in.
}
Board updateBoard(int r, int c, Board board)
{
// TODO:
// 1) Set the cell associated with the row ‘r‘ and column ‘c‘ to
// occupied.
// 2) Incremenet the board counter, since a move has just been made.
// 3) Set the symbol of the cell associated with ‘r‘ and ‘c‘ to
// the symbol of the currentPlayer (let player 0 be ’O’s and
// player ‘ be ’X’s.
// 4) Return the board.
int isWinningMove(int r, int c, Board board)
{
int possibleWin = 0;
// TODO: Create a char variable called ‘playerSymbol‘ and set
// it to either ’X’ or ’O’ depending on the current player.
// The code below checks to see if there is a 3-in-a-row in the
// row that was just played in (‘r‘ is the row that was just played in).
// Do not change this. It is provided to help you with the other
// checks below. For full credit, you must use a for loop (like below)
// for each check.
for (int column = 0; column < board.size; column++)
{
if (board.cells[r][column].symbol == playerSymbol)
possibleWin = 1;
else
{
possibleWin = 0;
break; }
}
if (possibleWin == 1)
{
// possibleWin can only be a 1 if all 3 symbols in the row matched
// so we have a winner!
return possibleWin;
}
// TODO: Using the above example on how to check for a 3-in-a-row in
// the row that was just played in, check for a 3-in-a-row in the
// column that was just played in. Again, you should do this using
// a single for loop, and after it, returning ‘possibleWin‘ if
// ‘possibleWin‘ is a 1.
// Now we have to check for diagonal 3-in-a-rows, but only if the
// most recent move was in a diagonal. Let’s check the main diagonal
// first (top left to bottom right). We can tell if the most recent move
// is part of the main diagonal if the row and column of the most recent
// move are identical.
if (c == r)
{
// TODO: Check for a 3-in-a-row in the main diagonal of the board.
// Use the example for checking for a 3-in-a-row in the row that
// was just played in.
}
// Now we check for the off-diagonal (bottom left to top right).
if (c == board.size - 1 - r)
{
// TODO: Check for a 3-in-a-row in the off diagonal of the board.
}
// If we haven’t returned a 1 at this point after all the checks, then the
// current player did not just win, so we return a 0 (indicating no one has
// won yet).
return 0;
}
}
Screenshots of output
Source Code
#include
#include //time()
#include //srand() and rand()
typedef struct
{
int occupied; // 0 means unoccupied, 1 means occupied
char symbol; //’X’ or ’O’ or ’ ’
} Cell;
typedef struct
{
Cell cells[3][3]; // 9 spaces in our board
int winner; // 1 if the currentPlayer has won, 0 otherwise
int counter; // for how many turns have been played in total
int size; // should match the dimensions of the ‘cells‘ array
int currentPlayer; // 0 for ’O’s and 1 for ’X’s
} Board;
// In function prototypes, just the type of each argument is sufficient.
Cell initializeCell(char, int);
void getPosition(Board, int[2]);
Board updateBoard(int, int, Board);
int isWinningMove(int, int, Board);
void printBoard(Board);
int main(void)
{
srand(time(NULL));
Board mainBoard;
// TODO: Initialize the members (except for ‘cells‘) of the mainBoard
// to appropriate values. You must choose a random player to start.
mainBoard.winner = 0;
mainBoard.counter = 0;
mainBoard.size = 3;
mainBoard.currentPlayer = rand() % 2;
// TODO: Initialize each cell in the mainBoard to an unoccupied cell
// with a single space for the symbol. Note that you’ll need a nested
// for loop to do this, since the ‘cells‘ array inside mainBoard is 2D.
// Use your initializeCell() function in the body of the nested for
// loop to do this.
for (int row = 0; row < mainBoard.size; row++)
for (int col = 0; col < mainBoard.size; col++)
mainBoard.cells[row][col] = initializeCell(' ', 0);
while ((mainBoard.winner == 0) && (mainBoard.counter < 9))
{
// TODO:
// 1) Alternate the mainBoard.currentPlayer
if (mainBoard.currentPlayer == 0)
mainBoard.currentPlayer = 1;
else
mainBoard.currentPlayer = 0;
// 2) Create an array that holds 2 ints called ‘position‘
int position[2];
// 3) call the getPosition() function, passing in the ‘mainBoard‘
// and the ‘position‘ array. getPosition() "returns" two
// values by using this array to hold the output values.
getPosition(mainBoard, position);
// 4) call updateBoard(), passing in the row and column which
// were stored in the ‘position‘ array by getPosition() and
// the ‘mainBoard‘. Assign its return value to mainBoard, effectively
// updating main()’s local mainBoard variable.
mainBoard = updateBoard(position[0], position[1], mainBoard);
// 5) set ‘mainBoard.winner‘ to the return value of isWinningMove().
// Pass in the row and column of the cell that was just played
// and the ‘mainBoard‘.
mainBoard.winner = isWinningMove(position[0], position[1], mainBoard);
// 6) call printBoard()
printBoard(mainBoard);
}
if (mainBoard.winner==0)
printf("Tie Game\n");
else
printf("Player %d won\n", mainBoard.currentPlayer);
return 0;
}
void printBoard(Board board)
{
// Don’t touch this function. It already prints things nicely for you.
// Note that here, I’m using the first index of the cells array
// as the row, and the second as the column.
for (int row = 0; row < board.size; row++)
{
printf("| ");
for (int column = 0; column < board.size; column++)
{
printf("%c | ", board.cells[row][column].symbol);
}
printf("\n");
}
printf("\n");
}
Cell initializeCell(char sym, int isOccupied)
{
// TODO:
// 1) Create a local variable of type Cell and initialize its
// members according to the arguments passed into this function.
// 2) Return the local variable.
//
// This function is here mainly to show you that you can return structs
// from a function.
Cell cell;
cell.occupied = isOccupied;
cell.symbol = sym;
return cell;
}
void getPosition(Board board, int pos[2])
{
int r, c; // Remember, these are local variables to the function
do
{
printf("Enter the row and column: ");
scanf("%d%d", &r, &c);
} while (r < 0 || r >= board.size || c < 0 || c >= board.size || board.cells[r][c].occupied);
// TODO: Fill in the condition of the while loop above. It should continue
// to ask the user for a row and column as long as the row and column
// the user has asked for is out of bounds OR if the cell is already
// occupied in the board.
// TODO: Assign the desired row ‘r‘ to pos[0] and the desired column ‘c‘
// to pos[1]. Here we’re using the ‘pos‘ array to "return" two values
// back to main(), more specifically the row and column of the cell the user
// wants to play their symbol in.
pos[0] = r;
pos[1] = c;
}
Board updateBoard(int r, int c, Board board)
{
// TODO:
// 1) Set the cell associated with the row ‘r‘ and column ‘c‘ to
// occupied.
board.cells[r][c].occupied = 1;
// 2) Increment the board counter, since a move has just been made.
board.counter++;
// 3) Set the symbol of the cell associated with ‘r‘ and ‘c‘ to
// the symbol of the currentPlayer (let player 0 be ’O’s and
// player ‘ be ’X’s.
if (board.currentPlayer == 0)
board.cells[r][c].symbol = 'O';
else
board.cells[r][c].symbol = 'X';
// 4) Return the board.
return board;
}
int isWinningMove(int r, int c, Board board)
{
int possibleWin = 0;
// TODO: Create a char variable called ‘playerSymbol‘ and set
// it to either ’X’ or ’O’ depending on the current player.
char playerSymbol;
if (board.currentPlayer == 0)
playerSymbol = 'O';
else
playerSymbol = 'X';
// The code below checks to see if there is a 3-in-a-row in the
// row that was just played in (‘r‘ is the row that was just played in).
// Do not change this. It is provided to help you with the other
// checks below. For full credit, you must use a for loop (like below)
// for each check.
for (int column = 0; column < board.size; column++)
{
if (board.cells[r][column].symbol == playerSymbol)
possibleWin = 1;
else
{
possibleWin = 0;
break;
}
}
if (possibleWin == 1)
{
// possibleWin can only be a 1 if all 3 symbols in the row matched
// so we have a winner!
return possibleWin;
}
// TODO: Using the above example on how to check for a 3-in-a-row in
// the row that was just played in, check for a 3-in-a-row in the
// column that was just played in. Again, you should do this using
// a single for loop, and after it, returning ‘possibleWin‘ if
// ‘possibleWin‘ is a 1.
for (int row = 0; row < board.size; row++)
{
if (board.cells[row][c].symbol == playerSymbol)
possibleWin = 1;
else
{
possibleWin = 0;
break;
}
}
if (possibleWin == 1)
{
return possibleWin;
}
// Now we have to check for diagonal 3-in-a-rows, but only if the
// most recent move was in a diagonal. Let’s check the main diagonal
// first (top left to bottom right). We can tell if the most recent move
// is part of the main diagonal if the row and column of the most recent
// move are identical.
if (c == r)
{
// TODO: Check for a 3-in-a-row in the main diagonal of the board.
// Use the example for checking for a 3-in-a-row in the row that
// was just played in.
for (int row = 0; row < board.size; row++)
{
if (board.cells[row][row].symbol == playerSymbol)
possibleWin = 1;
else
{
possibleWin = 0;
break;
}
}
if (possibleWin == 1)
{
return possibleWin;
}
}
// Now we check for the off-diagonal (bottom left to top right).
if (c == board.size - 1 - r)
{
// TODO: Check for a 3-in-a-row in the off diagonal of the board.
for (int row = 0; row < board.size; row++)
{
if (board.cells[row][board.size - 1 - row].symbol == playerSymbol)
possibleWin = 1;
else
{
possibleWin = 0;
break;
}
}
if (possibleWin == 1)
{
return possibleWin;
}
}
// If we haven’t returned a 1 at this point after all the checks, then the
// current player did not just win, so we return a 0 (indicating no one has
// won yet).
return 0;
}