home *** CD-ROM | disk | FTP | other *** search
/ Beginning C++ Through Gam…rogramming (2nd Edition) / BCGP2E.ISO / source / chapter06 / tic-tac-toe.cpp < prev   
Encoding:
C/C++ Source or Header  |  2004-04-11  |  7.1 KB  |  265 lines

  1. // Tic-Tac-Toe
  2. // Plays the game of tic-tac-toe against a human opponent
  3.  
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7. #include <algorithm>
  8.  
  9. using namespace std;
  10.  
  11. // global constants
  12. const char X = 'X';
  13. const char O = 'O';
  14. const char EMPTY = ' ';
  15. const char TIE = 'T';
  16. const char NO_ONE = 'N';
  17.  
  18. // function prototypes
  19. void instructions();
  20. char askYesNo(string question);
  21. int askNumber(string question, int high, int low = 0);
  22. char humanPiece();
  23. char opponent(char piece);
  24. void displayBoard(const vector<char>& board);
  25. char winner(const vector<char>& board);
  26. bool isLegal(const vector<char>& board, int move);
  27. int humanMove(const vector<char>& board, char human);
  28. int computerMove(vector<char> board, char computer);
  29. void announceWinner(char winner, char computer, char human);
  30.  
  31. // main function
  32. int main()
  33. {
  34.     int move;
  35.     const int NUM_SQUARES = 9;
  36.     vector<char> board(NUM_SQUARES, EMPTY);
  37.  
  38.     instructions();
  39.     char human = humanPiece();
  40.     char computer = opponent(human);
  41.     char turn = X;
  42.     displayBoard(board);
  43.  
  44.     while (winner(board) == NO_ONE)
  45.     {
  46.         if (turn == human)
  47.         {
  48.             move = humanMove(board, human);
  49.             board[move] = human;
  50.         }
  51.         else
  52.         {
  53.             move = computerMove(board, computer);
  54.             board[move] = computer;
  55.         }
  56.         displayBoard(board);
  57.         turn = opponent(turn);
  58.     }
  59.  
  60.     announceWinner(winner(board), computer, human);
  61.  
  62.     return 0;
  63. }
  64.  
  65. // functions
  66. void instructions()
  67. {
  68.     cout << "Welcome to the ultimate man-machine showdown: Tic-Tac-Toe.\n";
  69.     cout << "--where human brain is pit against silicon processor\n\n";
  70.  
  71.     cout << "Make your move known by entering a number, 0 - 8.  The number\n";
  72.     cout << "corresponds to the desired board position, as illustrated:\n\n";
  73.     
  74.     cout << "       0 | 1 | 2\n";
  75.     cout << "       ---------\n";
  76.     cout << "       3 | 4 | 5\n";
  77.     cout << "       ---------\n";
  78.     cout << "       6 | 7 | 8\n\n";
  79.  
  80.     cout << "Prepare yourself, human.  The battle is about to begin.\n\n";
  81. }
  82.  
  83. char askYesNo(string question)
  84. {
  85.     char response;
  86.     do
  87.     {
  88.         cout << question << " (y/n): ";
  89.         cin >> response;
  90.     } while (response != 'y' && response != 'n');
  91.  
  92.     return response;
  93. }
  94.  
  95. int askNumber(string question, int high, int low)
  96. {
  97.     int number;
  98.     do
  99.     {
  100.         cout << question << " (" << low << " - " << high << "): ";
  101.         cin >> number;
  102.     } while (number > high || number < low);
  103.  
  104.     return number;
  105. }
  106.  
  107. char humanPiece()
  108. {
  109.     char go_first = askYesNo("Do you require the first move?");
  110.     if (go_first == 'y')
  111.     {
  112.         cout << "\nThen take the first move.  You will need it.\n";
  113.         return X;
  114.     }
  115.     else
  116.     {
  117.         cout << "\nYour bravery will be your undoing... I will go first.\n";
  118.         return O;
  119.     }
  120. }
  121.  
  122. char opponent(char piece)
  123. {
  124.     if (piece == X)
  125.         return O;
  126.     else
  127.         return X;
  128. }
  129.  
  130. void displayBoard(const vector<char>& board)
  131. {
  132.     cout << "\n\t" << board[0] << " | " << board[1] << " | " << board[2];
  133.     cout << "\n\t" << "---------";
  134.     cout << "\n\t" << board[3] << " | " << board[4] << " | " << board[5];
  135.     cout << "\n\t" << "---------";
  136.     cout << "\n\t" << board[6] << " | " << board[7] << " | " << board[8];
  137.     cout << "\n\n";
  138. }
  139.  
  140. char winner(const vector<char>& board)
  141. {
  142.     // all possible winning rows
  143.     const int WINNING_ROWS[8][3] = { {0, 1, 2},
  144.                                      {3, 4, 5},
  145.                                      {6, 7, 8},
  146.                                      {0, 3, 6},
  147.                                      {1, 4, 7},
  148.                                      {2, 5, 8},
  149.                                      {0, 4, 8},
  150.                                      {2, 4, 6} };
  151.     const int TOTAL_ROWS = 8;
  152.  
  153.     // if any winning row has three values that are the same (and not EMPTY),
  154.     // then we have a winner
  155.     for(int row = 0; row < TOTAL_ROWS; ++row)
  156.     {
  157.         if ( (board[WINNING_ROWS[row][0]] != EMPTY) &&
  158.              (board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) &&
  159.              (board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]]) )
  160.         {
  161.             return board[WINNING_ROWS[row][0]];
  162.         }
  163.     }
  164.  
  165.     // since nobody has won, check for a tie (no empty squares left)
  166.     if (count(board.begin(), board.end(), EMPTY) == 0)
  167.         return TIE;
  168.  
  169.     // since nobody has won and it isn't a tie, the game ain't over
  170.     return NO_ONE;
  171. }
  172.  
  173. inline bool isLegal(int move, const vector<char>& board)
  174. {
  175.     return (board[move] == EMPTY);
  176. }
  177.  
  178. int humanMove(const vector<char>& board, char human)
  179. {
  180.     int move = askNumber("Where will you move?", (board.size() - 1));
  181.     while (!isLegal(move, board))
  182.     {
  183.         cout << "\nThat square is already occupied, foolish human.\n";
  184.         move = askNumber("Where will you move?", (board.size() - 1));
  185.     }
  186.     cout << "Fine...\n";
  187.     return move;
  188. }
  189.  
  190. int computerMove(vector<char> board, char computer)
  191. {
  192.     cout << "I shall take square number ";
  193.     
  194.     // if computer can win on next move, make that move
  195.     for(int move = 0; move < board.size(); ++move)
  196.     {
  197.         if (isLegal(move, board))
  198.         {
  199.             board[move] = computer;
  200.             if (winner(board) == computer)
  201.             {
  202.                 cout << move << endl;
  203.                 return move;
  204.             }
  205.             // done checking this move, undo it
  206.             board[move] = EMPTY;
  207.         }
  208.     }
  209.         
  210.     // if human can win on next move, block that move
  211.     char human = opponent(computer);
  212.     for(int move = 0; move < board.size(); ++move)
  213.     {
  214.         if (isLegal(move, board))
  215.         {
  216.             board[move] = human;
  217.             if (winner(board) == human)
  218.             {
  219.                 cout << move << endl;
  220.                 return move;
  221.             }
  222.             // done checking this move, undo it
  223.             board[move] = EMPTY;
  224.         }
  225.     }
  226.  
  227.     // the best moves to make, in order
  228.     const int BEST_MOVES[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
  229.     // since no one can win on next move, pick best open square
  230.     for(int i = 0; i < board.size(); ++i)
  231.     {
  232.         int move = BEST_MOVES[i];
  233.         if (isLegal(move, board))
  234.         {
  235.             cout << move << endl;
  236.             return move;
  237.         }
  238.     }
  239. }
  240.  
  241. void announceWinner(char winner, char computer, char human)
  242. {
  243.     if (winner == computer)
  244.     {
  245.         cout << winner << "'s won!\n";
  246.         cout << "As I predicted, human, I am triumphant once more -- proof\n";
  247.         cout << "that computers are superior to humans in all regards.\n";
  248.     }
  249.  
  250.     else if (winner == human)
  251.     {
  252.         cout << winner << "'s won!\n";
  253.         cout << "No, no!  It cannot be!  Somehow you tricked me, human.\n";
  254.         cout << "But never again!  I, the computer, so swear it!\n";
  255.     }
  256.  
  257.     else
  258.     {
  259.         cout << "It's a tie.\n";
  260.         cout << "You were most lucky, human, and somehow managed to tie me.\n";
  261.         cout << "Celebrate... for this is the best you will ever achieve.\n";
  262.     }
  263. }
  264.  
  265.