Advertisement
Random_Coder_59

C++ - Tic Tac Toe minmax not working

Sep 28th, 2021
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.12 KB | None | 0 0
  1. #include <iostream>
  2. #include <list>
  3. #include <algorithm>
  4.  
  5. class TicTacToe;
  6. class AI;
  7. void play_game(TicTacToe game);
  8.  
  9. class TicTacToe
  10. {
  11. private:
  12.     char board[9] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
  13.     char current_turn = 'X';
  14.     char winner = ' '; // ' ' refers to None
  15.     int state = -1;    // -1 refers to running
  16.     std::list<int> move_stack;
  17.  
  18. public:
  19.     friend class AI;
  20.     friend void play_game(TicTacToe game);
  21.     void print_board() const;
  22.     void swap_turn();
  23.     int update_state();
  24.     int play_move(int index);
  25.     int undo_move();
  26.     std::list<int> get_possible_moves();
  27. };
  28.  
  29. class AI
  30. {
  31. private:
  32.     int max(TicTacToe board, char max_symbol, int depth);
  33.     int min(TicTacToe board, char max_symbol, int depth);
  34.  
  35. public:
  36.     int minmax(TicTacToe board, char max_symbol);
  37. };
  38.  
  39. int main()
  40. {
  41.     TicTacToe game;
  42.     play_game(game);
  43.     return 0;
  44. }
  45.  
  46. void play_game(TicTacToe game)
  47. {
  48.     bool playing = true;
  49.     int input;
  50.     AI my_ai;
  51.  
  52.     while (playing)
  53.     {
  54.         game.print_board();
  55.         std::cout<<my_ai.minmax(game, game.current_turn);
  56.         // std::cout << "AI suggested move: " << move << "\n";
  57.         int move = 0;
  58.         game.play_move(move);
  59.         // if (game.play_move(move) == 0)
  60.         // {
  61.         //     std::cout << "Box already occupied\n";
  62.         //     continue;
  63.         // }
  64.         if (game.state == 1)
  65.         {
  66.             game.print_board();
  67.             std::cout << game.winner << " wins the game!\n";
  68.             playing = false;
  69.         }
  70.         else if (game.state == 0)
  71.         {
  72.             game.print_board();
  73.             std::cout << "Draw!\n";
  74.             playing = false;
  75.         };
  76.     };
  77. };
  78.  
  79. void TicTacToe::print_board() const
  80. {
  81.     for (int i = 0; i < 9; ++i)
  82.     {
  83.         if (i % 3)
  84.         {
  85.             std::cout << " | ";
  86.         }
  87.         std::cout << board[i];
  88.         if (i == 2 || i == 5)
  89.         {
  90.             std::cout << "\n";
  91.             std::cout << "---------"
  92.                       << "\n";
  93.         }
  94.     }
  95.     std::cout << "\n";
  96. };
  97.  
  98. void TicTacToe::swap_turn()
  99. {
  100.     current_turn = (current_turn == 'X') ? 'O' : 'X';
  101. }
  102.  
  103. int TicTacToe::play_move(int index)
  104. {
  105.     if (index >= 0 && index < 9)
  106.     {
  107.         if (board[index] == ' ')
  108.         {
  109.             board[index] = current_turn;
  110.             move_stack.push_back(index);
  111.             update_state();
  112.             swap_turn();
  113.             return 1;
  114.         }
  115.     }
  116.     return 0;
  117. };
  118.  
  119. int TicTacToe::undo_move()
  120. {
  121.     move_stack.pop_back();
  122.     update_state();
  123.     swap_turn();
  124. };
  125.  
  126. std::list<int> TicTacToe::get_possible_moves()
  127. {
  128.     std::list<int> possible_moves;
  129.     for (int i = 0; i < 9; ++i)
  130.     {
  131.         bool found = (std::find(move_stack.begin(), move_stack.end(), i) != move_stack.end());
  132.         if (!found)
  133.         {
  134.             possible_moves.push_back(i);
  135.         }
  136.     }
  137.     return possible_moves;
  138. }
  139.  
  140. int TicTacToe::update_state()
  141. {
  142.     if (
  143.         // Horizontal checks
  144.         (board[0] == current_turn && board[1] == current_turn && board[2] == current_turn) ||
  145.         (board[3] == current_turn && board[4] == current_turn && board[5] == current_turn) ||
  146.         (board[6] == current_turn && board[7] == current_turn && board[8] == current_turn) ||
  147.         // Vertical Checks
  148.         (board[0] == current_turn && board[3] == current_turn && board[6] == current_turn) ||
  149.         (board[1] == current_turn && board[4] == current_turn && board[7] == current_turn) ||
  150.         (board[2] == current_turn && board[5] == current_turn && board[8] == current_turn) ||
  151.         // Diagonal Checks
  152.         (board[0] == current_turn && board[4] == current_turn && board[8] == current_turn) ||
  153.         (board[2] == current_turn && board[4] == current_turn && board[6] == current_turn))
  154.     {
  155.         state = 1;
  156.         winner = current_turn;
  157.     }
  158.     else
  159.     {
  160.         bool draw = true;
  161.         for (int i = 0; i < 9; ++i)
  162.         {
  163.             if (board[i] == ' ')
  164.             {
  165.                 draw = false;
  166.                 break;
  167.             }
  168.         };
  169.         if (draw)
  170.         {
  171.             state = 0;
  172.         }
  173.         else
  174.         {
  175.             winner = ' ';
  176.             state = -1;
  177.         }
  178.     }
  179. };
  180.  
  181. int AI::minmax(TicTacToe board, char max_symbol)
  182. {
  183.     std::cout << "In minmax\n";
  184.     int best_score = -100;
  185.     int best_move = -1; // -1 refers to none
  186.  
  187.     for (auto move : board.get_possible_moves())
  188.     {
  189.         board.play_move(move);
  190.         int score = AI::min(board, max_symbol, 0);
  191.         std::cout << "Move: " << move << " Score: " << best_score << "\n";
  192.         if (score > best_score)
  193.         {
  194.             best_score = score;
  195.             best_move = move;
  196.         }
  197.         board.undo_move();
  198.     }
  199.     std::cout << best_move << "\n";
  200.     return best_move;
  201. }
  202.  
  203. int AI::max(TicTacToe board, char max_symbol, int depth)
  204. {
  205.     if (board.state == 1)
  206.     {
  207.         if (board.winner == max_symbol)
  208.         {
  209.             return 10 - depth;
  210.         }
  211.         else
  212.         {
  213.             return -10 + depth;
  214.         }
  215.     }
  216.     else if (board.state == 0)
  217.     {
  218.         return 0;
  219.     }
  220.  
  221.     int best_score = -100;
  222.  
  223.     for (auto move : board.get_possible_moves())
  224.     {
  225.         board.play_move(move);
  226.         int score = AI::min(board, max_symbol, depth + 1);
  227.         if (score > best_score)
  228.         {
  229.             best_score = score;
  230.         }
  231.         board.undo_move();
  232.     }
  233.     return best_score;
  234. }
  235.  
  236. int AI::min(TicTacToe board, char max_symbol, int depth)
  237. {
  238.     if (board.state == 1)
  239.     {
  240.         if (board.winner == max_symbol)
  241.         {
  242.             return 10 - depth;
  243.         }
  244.         else
  245.         {
  246.             return -10 + depth;
  247.         }
  248.     }
  249.     else if (board.state == 0)
  250.     {
  251.         return 0;
  252.     }
  253.  
  254.     int best_score = 100;
  255.  
  256.     for (auto move : board.get_possible_moves())
  257.     {
  258.         board.play_move(move);
  259.         int score = AI::max(board, max_symbol, depth + 1);
  260.         if (score < best_score)
  261.         {
  262.             best_score = score;
  263.         }
  264.         board.undo_move();
  265.     }
  266.     return best_score;
  267. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement