/* TTTGame.cpp * * * Written February, 2004 by Pat Troy for CS 422 */ #include "TTTGame.h" #include using namespace std; int posArray[8][3] = { {1,2,3}, /* positions in the first row */ {4,5,6}, /* positions in the second row */ {7,8,9}, /* positions in the third row */ {1,4,7}, /* positions in the first column */ {2,5,8}, /* positions in the second column */ {3,6,9}, /* positions in the third column */ {1,5,9}, /* positions in the first diagonal */ {3,5,7}}; /* positions in the second diagonal */ /* There is also a static pointer to TTTGame to keep track of the single instance of the class. */ TTTGame *TTTGame::game = NULL; /* The constructors will be protected to force the use of the static createTTTGame method. */ TTTGame::TTTGame() { /* set the game statistics to zero */ turn = 0; startingPlayer = 0; moveNumber = 0; numStarted = 0; numWon = 0; numLost = 0; numCats = 0; /* A "Cat's Game" is a game with no winner */ /* initialize the board */ for (int i = 0; i < 10; ++i) board[i] = '0' + i; } /* These static methods will create and/or return the instance of the game maintained in the static pointer */ TTTGame *TTTGame::createTTTGame ( void ) { if (!game) game = new TTTGame (); return game; } TTTGame *TTTGame::getGame ( void ) { return game; } /* Here are the normal methods of the class */ int TTTGame::newGame (int startPlayer) { /* initialize the board */ for (int i = 0; i < 10; ++i) board[i] = '0' + i; /* Initialize the other values */ moveNumber = 0; if ((startPlayer == USERPLAYER) || (startPlayer == COMPUTERPLAYER)) startingPlayer = startPlayer; else if (startingPlayer == USERPLAYER) startingPlayer = COMPUTERPLAYER; else startingPlayer = USERPLAYER; turn = startingPlayer; /* increment the number started statistic */ ++numStarted; /* return the value of startingPlayer */ return startingPlayer; } char TTTGame::getPosition ( int pos ) { return board[pos]; } int TTTGame::userMove (char move) { /* check for Cats's Game */ if (moveNumber >= 9) { ++ numCats; return CATSGAME; } /* invalid or off-board move */ if ((move < '1') || move > '9') return INVALIDMOVE; /* check if position is already in use */ if (board[move-'0'] != move) return POSITIONINUSE; board[move-'0'] = 'X'; ++ moveNumber; turn = COMPUTERPLAYER; /* check for 3 in a row */ if ( isGameWon() >= 0) { ++ numWon; return WINGAME; } else if (moveNumber >= 9) { ++ numCats; return CATSGAME; } else return VALIDMOVE; } int TTTGame::isGameWon() { int i; for (i = 0; i < 8; i++) { if ((board[posArray[i][0]] == board[posArray[i][1]]) && (board[posArray[i][0]] == board[posArray[i][2]])) return i; } return -1; } int TTTGame::findWinningMove (char player, int posOrCount) { int count = 0; int i,j; char value[3]; /* loop for each row in posArray */ for (i = 0; i < 8; ++i) { for (j = 0; j < 3; ++j) value[j] = board[posArray[i][j]]; for (j = 0; j < 3; ++j) { if ((isdigit(value[j])) && (value[(j+1)%3] == player) && (value[(j+2)%3] == player)) { if (posOrCount == POS) return (value[j] - '0'); else ++count; } } } if (posOrCount == POS) return 0; else return count; } int TTTGame::determineComputerMove() { int move; int i; int pos, count; /* check for a winning move by the computer */ move = findWinningMove ('O', POS); if (move > 0) return move; /* check for a blocking move */ move = findWinningMove ('X', POS); if (move > 0) return move; /* check to set-up a possible winning move */ pos = 0; count = 0; for (i = 1; i <= 9; ++i) if (board[i] == (i + '0')) { board[i] = 'O'; move = findWinningMove ('O', COUNT); if (move > count) { pos = i; count = move; } board[i] = i + '0'; } if (pos != 0) return pos; /* make another move */ if (board[5] == '5') return 5; else if (board[1] == '1') return 1; else if (board[3] == '3') return 3; else if (board[7] == '7') return 7; else if (board[9] == '9') return 9; else if (board[2] == '2') return 2; else if (board[4] == '4') return 4; else if (board[6] == '6') return 6; else if (board[8] == '8') return 8; } int TTTGame::computerMove ( void ) { int move; /* check for Cats's Game */ if (moveNumber >= 9) { ++ numCats; return CATSGAME; } /* make move by the computer */ move = determineComputerMove(); board[move] = 'O'; ++ moveNumber; turn = USERPLAYER; /* check for 3 in a row */ if ( isGameWon() >= 0) { ++ numLost; return LOSEGAME; } /* check for Cats's Game */ else if (moveNumber >= 9) { ++ numCats; return CATSGAME; } else { return VALIDMOVE; } } int TTTGame::getTurn ( void ) { return turn; } int TTTGame::getNumStarted ( void ) { return numStarted; } int TTTGame::getNumWon ( void ) { return numWon; } int TTTGame::getNumLost ( void ) { return numLost; } int TTTGame::getNumCats ( void ) { return numCats; }