7 SQUARE g_sComputerPlays = O_MARK; // what side comp plays
9 //+----------------------------------------------------------------------------
11 // Function: SquareContentsToChar
13 // Synopsis: Helper function for DrawBoard
15 // Arguments: IN SQUARE s - a square to return a char to represent
17 // Returns: char - character representing square
19 //+----------------------------------------------------------------------------
20 char SquareContentsToChar(IN SQUARE s)
38 //+----------------------------------------------------------------------------
40 // Function: DrawBoard
42 // Synopsis: Draw the board
44 // Arguments: IN POSITION *p - pointer to a position whose board to draw
48 //+----------------------------------------------------------------------------
49 void DrawBoard(IN POSITION *p)
53 for (y = 0; y < BOARD_SIZE; y++)
55 for (x = 0; x < BOARD_SIZE; x++)
57 printf("%c ", SquareContentsToChar(p->sBoard[y][x]));
61 printf("\n%c to move.\n", SquareContentsToChar(p->sWhoseTurn));
64 //+----------------------------------------------------------------------------
66 // Function: ClearBoard
68 // Synopsis: Clear the board
70 // Arguments: IN OUT POSITION *p - pointer to position whose board to clear
74 //+----------------------------------------------------------------------------
75 void ClearBoard(IN OUT POSITION *p)
77 memset(p->sBoard, 0, sizeof(p->sBoard));
78 p->sWhoseTurn = X_MARK;
79 p->uNumEmpty = (BOARD_SIZE * BOARD_SIZE);
82 //+----------------------------------------------------------------------------
84 // Function: IsLegalMove
86 // Synopsis: Determine if a given move is legal on a given board
88 // Arguments: IN POSITION *p - the board to play the move on
89 // IN MOVE *m - the move in question
91 // Returns: BOOL - TRUE if it's legal, FALSE otherwise
93 //+----------------------------------------------------------------------------
94 BOOL IsLegalMove(IN POSITION *p, IN MOVE *m)
96 if ((m->cVpos < BOARD_SIZE) && (m->cHpos < BOARD_SIZE))
98 if (IS_SQUARE_EMPTY(p->sBoard[m->cVpos][m->cHpos]))
106 //+----------------------------------------------------------------------------
108 // Function: GetHumanMove
110 // Synopsis: Ask the human for a move
112 // Arguments: IN POSITION *p - the current board
113 // OUT MOVE *m - the move the human made; this struct is populated
114 // as a side-effect of this function.
116 // Returns: void* (populates the move struct)
118 //+----------------------------------------------------------------------------
119 void GetHumanMove(IN POSITION *p, OUT MOVE *m)
125 printf("Enter your move number: ");
128 m->cHpos = (x % BOARD_SIZE);
129 m->cVpos = (x / BOARD_SIZE);
130 m->sMark = g_sComputerPlays * -1;
132 while(FALSE == IsLegalMove(p, m));
135 //+----------------------------------------------------------------------------
137 // Function: SearchForComputerMove
139 // Synopsis: Use our sophisticated search algorithm to find a computer
142 // Arguments: IN POSITION *p - the current board
143 // OUT MOVE *m - the move the computer chooses; this move struct
144 // is populated as a side-effect of this function.
146 // Returns: void* (populates move struct)
148 //+----------------------------------------------------------------------------
149 void SearchForComputerMove(IN POSITION *p, OUT MOVE *m)
155 x = rand() % (BOARD_SIZE * BOARD_SIZE);
156 m->cHpos = (x % BOARD_SIZE);
157 m->cVpos = (x / BOARD_SIZE);
158 m->sMark = g_sComputerPlays;
160 while(FALSE == IsLegalMove(p, m));
163 //+----------------------------------------------------------------------------
165 // Function: MakeMove
167 // Synopsis: Make a move on a board
169 // Arguments: IN OUT POSITION *p - the board
170 // IN MOVE *m - the move
174 //+----------------------------------------------------------------------------
175 void MakeMove(IN OUT POSITION *p, IN MOVE *m)
177 if (TRUE == IsLegalMove(p, m))
179 p->sBoard[m->cVpos][m->cHpos] = m->sMark;
185 //+----------------------------------------------------------------------------
187 // Function: GameOver
189 // Synopsis: Is the game over?
191 // Arguments: IN POSITION *p - the board
192 // OUT SQUARE *psWhoWon - who won the game (if it's over)
194 // Returns: TRUE if the game is over. Also sets psWhoWon telling
195 // which side one if the game is over.
197 // FALSE if the game is not over.
199 //+----------------------------------------------------------------------------
200 BOOL GameOver(IN POSITION *p, OUT SQUARE *psWhoWon)
205 for (x = 0; x < BOARD_SIZE; x++)
209 for (y = 0; y < BOARD_SIZE; y++)
211 iSum += p->sBoard[x][y];
213 if (abs(iSum) == BOARD_SIZE) goto winner;
216 for (y = 0; y < BOARD_SIZE; y++)
220 for (x = 0; x < BOARD_SIZE; x++)
222 iSum += p->sBoard[x][y];
224 if (abs(iSum) == BOARD_SIZE) goto winner;
228 for (x = 0; x < BOARD_SIZE; x++)
230 iSum += p->sBoard[x][x];
232 if (abs(iSum) == BOARD_SIZE) goto winner;
235 for (x = 0; x < BOARD_SIZE; x++)
237 iSum += p->sBoard[x][(BOARD_SIZE - 1 - x)];
239 if (abs(iSum) == BOARD_SIZE) goto winner;
242 if (p->uNumEmpty == 0)
252 *psWhoWon = (iSum / BOARD_SIZE);
256 //+----------------------------------------------------------------------------
260 // Synopsis: The program entry point and main game loop.
266 //+----------------------------------------------------------------------------
274 // Randomize: the random numbers returned by rand() will be based on
275 // the system clock when the program starts up.
280 // Setup the board and draw it once.
291 // See whose turn it is -- the human's or the computers -- and
292 // get a move from whoever's turn it is.
294 if (p.sWhoseTurn == g_sComputerPlays)
296 SearchForComputerMove(&p, &mv);
300 GetHumanMove(&p, &mv);
304 // Make the move on the board and draw the board again.
309 while(FALSE == GameOver(&p, &sResult));
312 // If we get here the game is over... see what happened.
317 printf("\nX's win.\n");
320 printf("\nO's win.\n");
323 printf("Tie (what a surprise)\n");