This month’s Exercise may seem like a repeat of the Exercise “We Have a Winnah!” from July of 2013. It’s not.
The July 2013 Exercise involved solving a tic-tac-toe like grid. Alas, the grid was filled with ones and zeros and only one grid pattern was presented. In a true game of tic-tac-toe, three characters occupy the grid: X, O, and blank. Further, multiple possibilities must be tested to assure a victory, which is why I’m presenting this, updated challenge.
For this month’s Exercise, your task is to determine whether a completed and valid tic-tac-toe game grid holds a winning combination, which is three Xs or three Os across, down, or diagonal. To help meet this goal, I’ve provided a program skeleton available below as well as on GitHub.
Something I learned while researching this project is that you can’t randomly pack an array and expect it to represent realistic game play. Therefore, each string in the game[]
array represents a valid 3-by-3 game grid as a string of x, o, and space characters:
char *game[6] = {
"xxoooxxox",
"o x xox ",
"xx oxxooo",
"o xooox x",
" xo ox o",
"x oxo xox"
};
Each string lays out as rows and columns: "xxoooxxox"
stands for the completed game shown in Figure 1.
The six strings in the array represent various possible solutions to a game of tic-tac-toe, along with some cat’s games (no winner). The code skeleton provided below contains the game[]
array, the output_grid() function to display the array as a tic-tac-toe game, but the code is missing the is_winner() function that evaluates each string for a winner and returns the winning token character.
#include <stdio.h> /* generate the tic-tac-toe grid */ void output_grid( char *g ) { int row; for( row=0; row<3; row++) { printf(" %c %c %c\n", *(g+(3*row)), *(g+(3*row)+1), *(g+(3*row)+2) ); } } /* determine whether the game was won */ char is_winner( char *g ) { return(' '); } int main() { char *game[6] = { "xxoooxxox", "o x xox ", "xx oxxooo", "o xooox x", " xo ox o", "x oxo xox" }; int x,r; /* examine all five game results */ for( x=0; x<6; x++ ) { output_grid( game[x] ); printf("Game %d: ",x+1); r = is_winner( game[x] ); switch(r) { case ' ': puts("No winner\n"); break; case 'x': puts("X wins!\n"); break; case 'o': puts("O wins!\n"); break; default: puts("Unknown value\n"); } } return(0); }
Your task for the Exercise is to code the is_winner() function. Ensure that it evaluates all possible solutions and returns the winning token character, ‘x’ or ‘o’, or ‘ ‘ (space) for no winner. Click here to view my solution.
/* determine whether the game was won
Assumes only 1 win possible and picks first one found
Check for only char ‘x’ or ‘o’ for possible wins
Assumes the input string will only contain ‘x’,’o’,’ ‘
*/
char is_winner( char *g )
{
//Assume no winner response
char results = ‘ ‘;
// Create table 8 possible win vectors
const int wv[8][3] = {{0,1,2},{0,4,8},{0,3,6},{1,4,7},{2,4,6},{2,5,8},{3,4,5},{6,7,8}};
//Loop through all possible
for(int loop=0; loop < 8; loop++)
{
// calcluate the sum of the scalars of one of the win vectors
int win = g[wv[loop][0]]+g[wv[loop][1]]+g[wv[loop][2]];
// Some debug to help see what is happening
printf("%d:win=%d – %d %d %d\n", loop, win, wv[loop][0],wv[loop][1], wv[loop][2]);
//Check for either all 'x' or all 'o'
if('x'*3 == win)
{
results = 'x';
break;
}
if('o'*3 == win)
{
results = 'o';
break;
}
}
return(results);
}
That’s frickin’ brilliant! I wish I would have thought of it…