-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <memory.h>\r
-#include <time.h>\r
-#include "ttt.h"\r
-\r
-SQUARE g_sComputerPlays = O_MARK; // what side comp plays\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: SquareContentsToChar\r
-//\r
-// Synopsis: Helper function for DrawBoard\r
-//\r
-// Arguments: IN SQUARE s - a square to return a char to represent\r
-// \r
-// Returns: char - character representing square\r
-//\r
-//+----------------------------------------------------------------------------\r
-char SquareContentsToChar(IN SQUARE s)\r
-{\r
- static char c;\r
- switch(s)\r
- {\r
- case X_MARK:\r
- c = 'X';\r
- break;\r
- case O_MARK:\r
- c = 'O';\r
- break;\r
- default:\r
- c = '_';\r
- break;\r
- }\r
- return(c);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: DrawBoard\r
-//\r
-// Synopsis: Draw the board\r
-//\r
-// Arguments: IN POSITION *p - pointer to a position whose board to draw\r
-// \r
-// Returns: void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void DrawBoard(IN POSITION *p)\r
-{\r
- COORD x, y;\r
-\r
- for (y = 0; y < BOARD_SIZE; y++)\r
- {\r
- for (x = 0; x < BOARD_SIZE; x++)\r
- {\r
- printf("%c ", SquareContentsToChar(p->sBoard[y][x]));\r
- }\r
- printf("\n");\r
- }\r
- printf("\n%c to move.\n", SquareContentsToChar(p->sWhoseTurn));\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: ClearBoard\r
-//\r
-// Synopsis: Clear the board\r
-//\r
-// Arguments: IN OUT POSITION *p - pointer to position whose board to clear\r
-// \r
-// Returns: void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void ClearBoard(IN OUT POSITION *p)\r
-{\r
- memset(p->sBoard, 0, sizeof(p->sBoard));\r
- p->sWhoseTurn = X_MARK;\r
- p->uNumEmpty = (BOARD_SIZE * BOARD_SIZE);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: IsLegalMove\r
-//\r
-// Synopsis: Determine if a given move is legal on a given board\r
-//\r
-// Arguments: IN POSITION *p - the board to play the move on\r
-// IN MOVE *m - the move in question\r
-// \r
-// Returns: BOOL - TRUE if it's legal, FALSE otherwise\r
-//\r
-//+----------------------------------------------------------------------------\r
-BOOL IsLegalMove(IN POSITION *p, IN MOVE *m)\r
-{\r
- if ((m->cVpos < BOARD_SIZE) && (m->cHpos < BOARD_SIZE))\r
- {\r
- if (IS_SQUARE_EMPTY(p->sBoard[m->cVpos][m->cHpos]))\r
- {\r
- return(TRUE);\r
- }\r
- }\r
- return(FALSE);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: GetHumanMove\r
-//\r
-// Synopsis: Ask the human for a move\r
-//\r
-// Arguments: IN POSITION *p - the current board\r
-// OUT MOVE *m - the move the human made; this struct is populated\r
-// as a side-effect of this function.\r
-// \r
-// Returns: void* (populates the move struct)\r
-//\r
-//+----------------------------------------------------------------------------\r
-void GetHumanMove(IN POSITION *p, OUT MOVE *m)\r
-{\r
- unsigned int x;\r
-\r
- do\r
- {\r
- printf("Enter your move number: ");\r
- scanf("%u", &x);\r
- \r
- m->cHpos = (x % BOARD_SIZE);\r
- m->cVpos = (x / BOARD_SIZE);\r
- m->sMark = g_sComputerPlays * -1;\r
- }\r
- while(FALSE == IsLegalMove(p, m));\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: SearchForComputerMove\r
-//\r
-// Synopsis: Use our sophisticated search algorithm to find a computer\r
-// move\r
-//\r
-// Arguments: IN POSITION *p - the current board\r
-// OUT MOVE *m - the move the computer chooses; this move struct\r
-// is populated as a side-effect of this function.\r
-// \r
-// Returns: void* (populates move struct)\r
-//\r
-//+----------------------------------------------------------------------------\r
-void SearchForComputerMove(IN POSITION *p, OUT MOVE *m)\r
-{\r
- unsigned int x;\r
-\r
- do\r
- {\r
- x = rand() % (BOARD_SIZE * BOARD_SIZE);\r
- m->cHpos = (x % BOARD_SIZE);\r
- m->cVpos = (x / BOARD_SIZE);\r
- m->sMark = g_sComputerPlays;\r
- }\r
- while(FALSE == IsLegalMove(p, m));\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: MakeMove\r
-//\r
-// Synopsis: Make a move on a board \r
-//\r
-// Arguments: IN OUT POSITION *p - the board\r
-// IN MOVE *m - the move\r
-// \r
-// Returns: void\r
-//\r
-//+----------------------------------------------------------------------------\r
-void MakeMove(IN OUT POSITION *p, IN MOVE *m)\r
-{\r
- if (TRUE == IsLegalMove(p, m))\r
- {\r
- p->sBoard[m->cVpos][m->cHpos] = m->sMark;\r
- p->uNumEmpty--;\r
- p->sWhoseTurn *= -1;\r
- }\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: GameOver\r
-//\r
-// Synopsis: Is the game over? \r
-//\r
-// Arguments: IN POSITION *p - the board\r
-// OUT SQUARE *psWhoWon - who won the game (if it's over)\r
-// \r
-// Returns: TRUE if the game is over. Also sets psWhoWon telling\r
-// which side one if the game is over.\r
-// \r
-// FALSE if the game is not over.\r
-//\r
-//+----------------------------------------------------------------------------\r
-BOOL GameOver(IN POSITION *p, OUT SQUARE *psWhoWon)\r
-{\r
- int iSum;\r
- COORD x, y;\r
-\r
- for (x = 0; x < BOARD_SIZE; x++)\r
- {\r
- iSum = 0;\r
-\r
- for (y = 0; y < BOARD_SIZE; y++)\r
- {\r
- iSum += p->sBoard[x][y];\r
- }\r
- if (abs(iSum) == BOARD_SIZE) goto winner;\r
- }\r
-\r
- for (y = 0; y < BOARD_SIZE; y++)\r
- {\r
- iSum = 0;\r
-\r
- for (x = 0; x < BOARD_SIZE; x++)\r
- {\r
- iSum += p->sBoard[x][y];\r
- }\r
- if (abs(iSum) == BOARD_SIZE) goto winner;\r
- }\r
-\r
- iSum = 0;\r
- for (x = 0; x < BOARD_SIZE; x++)\r
- {\r
- iSum += p->sBoard[x][x];\r
- }\r
- if (abs(iSum) == BOARD_SIZE) goto winner;\r
-\r
- iSum = 0;\r
- for (x = 0; x < BOARD_SIZE; x++)\r
- {\r
- iSum += p->sBoard[x][(BOARD_SIZE - 1 - x)];\r
- }\r
- if (abs(iSum) == BOARD_SIZE) goto winner;\r
- \r
- *psWhoWon = EMPTY;\r
- if (p->uNumEmpty == 0)\r
- {\r
- return(TRUE);\r
- }\r
- else\r
- {\r
- return(FALSE);\r
- }\r
-\r
- winner:\r
- *psWhoWon = (iSum / BOARD_SIZE);\r
- return(TRUE);\r
-}\r
-\r
-//+----------------------------------------------------------------------------\r
-//\r
-// Function: main\r
-//\r
-// Synopsis: The program entry point and main game loop.\r
-//\r
-// Arguments: void\r
-// \r
-// Returns: int\r
-//\r
-//+----------------------------------------------------------------------------\r
-int main(void)\r
-{\r
- POSITION p;\r
- MOVE mv;\r
- SQUARE sResult;\r
-\r
- //\r
- // Randomize: the random numbers returned by rand() will be based on\r
- // the system clock when the program starts up.\r
- //\r
- srand(time(0));\r
-\r
- //\r
- // Setup the board and draw it once.\r
- //\r
- ClearBoard(&p);\r
- DrawBoard(&p);\r
-\r
- //\r
- // Main game loop\r
- //\r
- do\r
- {\r
- // \r
- // See whose turn it is -- the human's or the computers -- and\r
- // get a move from whoever's turn it is.\r
- //\r
- if (p.sWhoseTurn == g_sComputerPlays)\r
- {\r
- SearchForComputerMove(&p, &mv);\r
- }\r
- else\r
- {\r
- GetHumanMove(&p, &mv);\r
- }\r
-\r
- //\r
- // Make the move on the board and draw the board again.\r
- //\r
- MakeMove(&p, &mv);\r
- DrawBoard(&p);\r
- }\r
- while(FALSE == GameOver(&p, &sResult));\r
-\r
- //\r
- // If we get here the game is over... see what happened.\r
- //\r
- switch(sResult)\r
- {\r
- case X_MARK:\r
- printf("\nX's win.\n");\r
- break;\r
- case O_MARK:\r
- printf("\nO's win.\n");\r
- break;\r
- default:\r
- printf("Tie (what a surprise)\n");\r
- break;\r
- }\r
-\r
- exit(0);\r
-}\r
-\r
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <time.h>
+#include "ttt.h"
+
+SQUARE g_sComputerPlays = O_MARK; // what side comp plays
+
+//+----------------------------------------------------------------------------
+//
+// Function: SquareContentsToChar
+//
+// Synopsis: Helper function for DrawBoard
+//
+// Arguments: IN SQUARE s - a square to return a char to represent
+//
+// Returns: char - character representing square
+//
+//+----------------------------------------------------------------------------
+char SquareContentsToChar(IN SQUARE s)
+{
+ static char c;
+ switch(s)
+ {
+ case X_MARK:
+ c = 'X';
+ break;
+ case O_MARK:
+ c = 'O';
+ break;
+ default:
+ c = '_';
+ break;
+ }
+ return(c);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: DrawBoard
+//
+// Synopsis: Draw the board
+//
+// Arguments: IN POSITION *p - pointer to a position whose board to draw
+//
+// Returns: void
+//
+//+----------------------------------------------------------------------------
+void DrawBoard(IN POSITION *p)
+{
+ COORD x, y;
+
+ for (y = 0; y < BOARD_SIZE; y++)
+ {
+ for (x = 0; x < BOARD_SIZE; x++)
+ {
+ printf("%c ", SquareContentsToChar(p->sBoard[y][x]));
+ }
+ printf("\n");
+ }
+ printf("\n%c to move.\n", SquareContentsToChar(p->sWhoseTurn));
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: ClearBoard
+//
+// Synopsis: Clear the board
+//
+// Arguments: IN OUT POSITION *p - pointer to position whose board to clear
+//
+// Returns: void
+//
+//+----------------------------------------------------------------------------
+void ClearBoard(IN OUT POSITION *p)
+{
+ memset(p->sBoard, 0, sizeof(p->sBoard));
+ p->sWhoseTurn = X_MARK;
+ p->uNumEmpty = (BOARD_SIZE * BOARD_SIZE);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: IsLegalMove
+//
+// Synopsis: Determine if a given move is legal on a given board
+//
+// Arguments: IN POSITION *p - the board to play the move on
+// IN MOVE *m - the move in question
+//
+// Returns: BOOL - TRUE if it's legal, FALSE otherwise
+//
+//+----------------------------------------------------------------------------
+BOOL IsLegalMove(IN POSITION *p, IN MOVE *m)
+{
+ if ((m->cVpos < BOARD_SIZE) && (m->cHpos < BOARD_SIZE))
+ {
+ if (IS_SQUARE_EMPTY(p->sBoard[m->cVpos][m->cHpos]))
+ {
+ return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: GetHumanMove
+//
+// Synopsis: Ask the human for a move
+//
+// Arguments: IN POSITION *p - the current board
+// OUT MOVE *m - the move the human made; this struct is populated
+// as a side-effect of this function.
+//
+// Returns: void* (populates the move struct)
+//
+//+----------------------------------------------------------------------------
+void GetHumanMove(IN POSITION *p, OUT MOVE *m)
+{
+ unsigned int x;
+
+ do
+ {
+ printf("Enter your move number: ");
+ scanf("%u", &x);
+
+ m->cHpos = (x % BOARD_SIZE);
+ m->cVpos = (x / BOARD_SIZE);
+ m->sMark = g_sComputerPlays * -1;
+ }
+ while(FALSE == IsLegalMove(p, m));
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: SearchForComputerMove
+//
+// Synopsis: Use our sophisticated search algorithm to find a computer
+// move
+//
+// Arguments: IN POSITION *p - the current board
+// OUT MOVE *m - the move the computer chooses; this move struct
+// is populated as a side-effect of this function.
+//
+// Returns: void* (populates move struct)
+//
+//+----------------------------------------------------------------------------
+void SearchForComputerMove(IN POSITION *p, OUT MOVE *m)
+{
+ unsigned int x;
+
+ do
+ {
+ x = rand() % (BOARD_SIZE * BOARD_SIZE);
+ m->cHpos = (x % BOARD_SIZE);
+ m->cVpos = (x / BOARD_SIZE);
+ m->sMark = g_sComputerPlays;
+ }
+ while(FALSE == IsLegalMove(p, m));
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: MakeMove
+//
+// Synopsis: Make a move on a board
+//
+// Arguments: IN OUT POSITION *p - the board
+// IN MOVE *m - the move
+//
+// Returns: void
+//
+//+----------------------------------------------------------------------------
+void MakeMove(IN OUT POSITION *p, IN MOVE *m)
+{
+ if (TRUE == IsLegalMove(p, m))
+ {
+ p->sBoard[m->cVpos][m->cHpos] = m->sMark;
+ p->uNumEmpty--;
+ p->sWhoseTurn *= -1;
+ }
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: GameOver
+//
+// Synopsis: Is the game over?
+//
+// Arguments: IN POSITION *p - the board
+// OUT SQUARE *psWhoWon - who won the game (if it's over)
+//
+// Returns: TRUE if the game is over. Also sets psWhoWon telling
+// which side one if the game is over.
+//
+// FALSE if the game is not over.
+//
+//+----------------------------------------------------------------------------
+BOOL GameOver(IN POSITION *p, OUT SQUARE *psWhoWon)
+{
+ int iSum;
+ COORD x, y;
+
+ for (x = 0; x < BOARD_SIZE; x++)
+ {
+ iSum = 0;
+
+ for (y = 0; y < BOARD_SIZE; y++)
+ {
+ iSum += p->sBoard[x][y];
+ }
+ if (abs(iSum) == BOARD_SIZE) goto winner;
+ }
+
+ for (y = 0; y < BOARD_SIZE; y++)
+ {
+ iSum = 0;
+
+ for (x = 0; x < BOARD_SIZE; x++)
+ {
+ iSum += p->sBoard[x][y];
+ }
+ if (abs(iSum) == BOARD_SIZE) goto winner;
+ }
+
+ iSum = 0;
+ for (x = 0; x < BOARD_SIZE; x++)
+ {
+ iSum += p->sBoard[x][x];
+ }
+ if (abs(iSum) == BOARD_SIZE) goto winner;
+
+ iSum = 0;
+ for (x = 0; x < BOARD_SIZE; x++)
+ {
+ iSum += p->sBoard[x][(BOARD_SIZE - 1 - x)];
+ }
+ if (abs(iSum) == BOARD_SIZE) goto winner;
+
+ *psWhoWon = EMPTY;
+ if (p->uNumEmpty == 0)
+ {
+ return(TRUE);
+ }
+ else
+ {
+ return(FALSE);
+ }
+
+ winner:
+ *psWhoWon = (iSum / BOARD_SIZE);
+ return(TRUE);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function: main
+//
+// Synopsis: The program entry point and main game loop.
+//
+// Arguments: void
+//
+// Returns: int
+//
+//+----------------------------------------------------------------------------
+int main(void)
+{
+ POSITION p;
+ MOVE mv;
+ SQUARE sResult;
+
+ //
+ // Randomize: the random numbers returned by rand() will be based on
+ // the system clock when the program starts up.
+ //
+ srand(time(0));
+
+ //
+ // Setup the board and draw it once.
+ //
+ ClearBoard(&p);
+ DrawBoard(&p);
+
+ //
+ // Main game loop
+ //
+ do
+ {
+ //
+ // See whose turn it is -- the human's or the computers -- and
+ // get a move from whoever's turn it is.
+ //
+ if (p.sWhoseTurn == g_sComputerPlays)
+ {
+ SearchForComputerMove(&p, &mv);
+ }
+ else
+ {
+ GetHumanMove(&p, &mv);
+ }
+
+ //
+ // Make the move on the board and draw the board again.
+ //
+ MakeMove(&p, &mv);
+ DrawBoard(&p);
+ }
+ while(FALSE == GameOver(&p, &sResult));
+
+ //
+ // If we get here the game is over... see what happened.
+ //
+ switch(sResult)
+ {
+ case X_MARK:
+ printf("\nX's win.\n");
+ break;
+ case O_MARK:
+ printf("\nO's win.\n");
+ break;
+ default:
+ printf("Tie (what a surprise)\n");
+ break;
+ }
+
+ exit(0);
+}
+