Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.16 KB | None | 0 0
  1. #include <random> //for the first strategy
  2. #include <time.h> //for the first strategy
  3. #include "Player.h"
  4.  
  5. Player::Player(const char symbol, unsigned int strategy)
  6.     :mSymbol(symbol)
  7.     ,strategy(strategy)
  8. {
  9.     srand(time(NULL)); //in order to choose random places when playing the first strategy
  10. }
  11.  
  12. void Player::play(char**& board) const
  13. {
  14.     if (strategy == 1)
  15.         playFirstStrategy(board);
  16.     else if (strategy == 2)
  17.         playSecondStrategy(board);
  18.     else if (strategy == 3)
  19.         playThirdStrategy(board);
  20.     else if (strategy == 4)
  21.         playFourthStrategy(board);
  22. }
  23.  
  24. bool Player::hasWon(char **& board) const
  25. {
  26.     if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] == mSymbol) //first diagonal
  27.         || (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] == mSymbol) //second diagonal
  28.         || wonLine(board, 1) || wonLine(board, 0))  //we check if we have 3 of the same in a row and then in a col
  29.         return true;
  30.     return false;
  31. }
  32.  
  33. void Player::playFirstStrategy(char**& board) const
  34. {
  35.     unsigned int row;
  36.     unsigned int col;
  37.     do
  38.     {
  39.         row = rand() % ROWSNUM;
  40.         col = rand() % COLSNUM;
  41.     } while (board[row][col] != ' ');
  42.  
  43.     board[row][col] = mSymbol;
  44. }
  45.  
  46. void Player::playSecondStrategy(char **& board) const
  47. {
  48.     char oppSymbol = getOppSymbol();
  49.     if (!canWin(board, oppSymbol, true))
  50.         playFirstStrategy(board);
  51. }
  52.  
  53. void Player::playThirdStrategy(char **& board) const
  54. {
  55.     if (!canWin(board, mSymbol, true)) //first we try to win directly
  56.     {
  57.         //then we just need to create a pair with another one of our symbols without being blocked by the opponent
  58.         if (!canPlayToWin(board))
  59.             playFirstStrategy(board); //if we cannot create a good pair, we just play at random
  60.     }
  61. }
  62.  
  63. void Player::playFourthStrategy(char **& board) const
  64. {
  65.     char oppSymbol = getOppSymbol();
  66.     if (!canWin(board, oppSymbol, true)) //if the opponent cannot beat us, we try to beat him
  67.         playThirdStrategy(board);
  68. }
  69.  
  70. bool Player::canPlayToWin(char **& board) const
  71. {
  72.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  73.         for (unsigned int j = 0; j < COLSNUM; ++j)
  74.             if (board[i][j] == mSymbol)
  75.                 if (findPlace(board, i, j)) //whenever we find a symbol of ours, we try to find a pair for it
  76.                     return true;
  77.     return false;
  78. }
  79.  
  80. bool Player::findPlace(char**& board, int row, int col) const
  81. {
  82.     char oppSymbol = getOppSymbol();
  83.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  84.     {
  85.         //we can create a pair on a row
  86.         if (!rowContainsSymbol(board, row, oppSymbol) && rowContainsSymbol(board, row, ' '))
  87.         {
  88.             placeSymbolInRow(board, i);
  89.             return true;
  90.         }
  91.         //on a column
  92.         else if (!colContainsSymbol(board, col, oppSymbol) && colContainsSymbol(board, col, ' '))
  93.         {
  94.             placeSymbolInCol(board, i);
  95.             return true;
  96.         }
  97.         //or on a diagonal
  98.         else if (i > 0 && !diagContainsSymbol(board, i, oppSymbol) && diagContainsSymbol(board, i, ' '))
  99.         {
  100.             placeSymbolInDiag(board, i);
  101.             return true;
  102.         }
  103.     }
  104.     return false;
  105. }
  106.  
  107. bool Player::canWin(char**& board, char symbol, bool putSymbol) const
  108. {
  109.     //we use this method both for our player and the opponent
  110.     //the putSymbol variable lets us know if we have to react and place our symbol
  111.     //which will either guarantee us the win or prevent the opponent from winning
  112.     for (int i = 0; i < ROWSNUM; ++i)
  113.         for (int j = 0; j < COLSNUM; ++j)
  114.             if (board[i][j] == symbol)
  115.                 if (checkTileWin(board, i, j, symbol, putSymbol))
  116.                     return true;
  117.     return false;
  118. }
  119.  
  120. bool Player::checkTileWin(char**& board, int row, int col, char symbol, bool putSymbol) const
  121. {
  122.     //we avoid checking the center tile because we cover it in the other cases
  123.     if (isCornerTile(row, col))
  124.         return checkCornerTileWin(board, row, col, symbol, putSymbol);
  125.     else if (isMiddleTile(row, col))
  126.         return checkMiddleTileWin(board, row, col, symbol, putSymbol);
  127.     return false;
  128. }
  129.  
  130. bool Player::checkMiddleTileWin(char**& board, int row, int col, char symbol, bool putSymbol) const
  131. {
  132.     int rowM, colM, rowAddition, colAddition;
  133.     rowAddition = colAddition = 0;
  134.  
  135.     if (row == 0)
  136.         rowM = 1;
  137.     else if (row == 1)
  138.         rowM = 0;
  139.     else
  140.         rowM = -1;
  141.  
  142.     if (col == 0)
  143.         colM = 1;
  144.     else if (col == 1)
  145.         colM = 0;
  146.     else
  147.         colM = -1;
  148.  
  149.     //we only have 1 row and col which do not involve corner tiles so we have only 2 cases
  150.     if (board[row][col] == board[row + 1 * rowM][col + 1 * colM]
  151.         && board[row + 2 * rowM][col + 2 * colM] == ' ')
  152.     {
  153.         rowAddition = 2 * rowM;
  154.         colAddition = 2 * colM;
  155.     }
  156.     else if (board[row][col] == board[row + 2 * rowM][col + 2 * colM]
  157.         && board[row + 1 * rowM][col + 1 * colM] == ' ')
  158.     {
  159.         rowAddition = 1 * rowM;
  160.         colAddition = 1 * colM;
  161.     }
  162.     else
  163.         return false;
  164.     if (putSymbol)
  165.         board[row + rowAddition][col + colAddition] = mSymbol;
  166.     return true;
  167.  
  168. }
  169.  
  170. bool Player::checkCornerTileWin(char**& board, int row, int col, char symbol, bool putSymbol) const
  171. {
  172.     //depending on the position of the tile, we need to add or subtract the same values
  173.     int rowM, colM, rowAddition, colAddition;
  174.     rowAddition = colAddition = 0;
  175.     row == 0 ? rowM = 1 : rowM = -1;
  176.     col == 0 ? colM = 1 : colM = -1;
  177.  
  178.     //for every corner tile we have 2 possible pairs on the same row, 2 on the same column
  179.     //and 2 on the same diagonal = 6 cases
  180.     if (board[row][col + 1 * colM] == symbol && board[row][col + 2 * colM] == ' ')
  181.         colAddition = 2 * colM;
  182.     else if (board[row][col + 2 * colM] == symbol && board[row][col + 1 * colM] == ' ')
  183.         colAddition = 1 * colM;
  184.     else if (board[row + 2 * rowM][col] == symbol && board[row + 1 * rowM][col] == ' ')
  185.         rowAddition = 1 * rowM;
  186.     else if (board[row + 1 * rowM][col] == symbol && board[row + 2 * rowM][col] == ' ')
  187.         rowAddition = 2 * rowM;
  188.     else if (board[row + 1 * rowM][col + 1 * colM] == symbol && board[row + 2 * rowM][col + 2 * colM] == ' ')
  189.     {
  190.         rowAddition = 2 * rowM;
  191.         colAddition = 2 * colM;
  192.     }
  193.     else if (board[row + 2 * rowM][col + 2 * colM] == symbol && board[row + 1 * rowM][col + 1 * colM] == ' ')
  194.     {
  195.         rowAddition = 1 * rowM;
  196.         colAddition = 1 * colM;
  197.     }
  198.     else
  199.         return false;
  200.  
  201.     if (putSymbol)
  202.         board[row + rowAddition][col + colAddition] = mSymbol;
  203.     return true;
  204. }
  205.  
  206. bool Player::wonLine(char**& board, bool checkRow) const
  207. {
  208.     bool flag;
  209.  
  210.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  211.     {
  212.         flag = true;
  213.         for (unsigned int j = 1; j < COLSNUM; ++j)
  214.         {
  215.             //we are eliminating possible winning lines by checking if 2 nearby tiles are different
  216.             //or if they are not both our symbol
  217.             if (checkRow && (board[i][j] != board[i][j - 1] || board[i][j] != mSymbol))
  218.                 flag = false;
  219.             else if (!checkRow && (board[j][i] != board[j - 1][i] || board[j][i] != mSymbol))
  220.                 flag = false;
  221.         }
  222.         if (flag)
  223.             return true;
  224.     }
  225.     return false;
  226. }
  227.  
  228. char Player::getOppSymbol() const
  229. {
  230.     return 'X' == mSymbol ? 'O' : 'X';
  231. }
  232.  
  233. bool Player::isCornerTile(int row, int col) const
  234. {
  235.     //the sum of the rows and cols of a corner tile is always an even number
  236.     //we don't include the center tile by making sure that the row and col are not both 1s
  237.     if ((row + col) % 2 == 0 && row != 1 && col != 1)
  238.         return true;
  239.     return false;
  240. }
  241.  
  242. bool Player::isMiddleTile(int row, int col) const
  243. {
  244.     if (!isCornerTile(row, col) && (row + col) != 2) //we check their sum in order to exclude the center piece
  245.         return true;
  246.     return false;
  247. }
  248.  
  249. bool Player::rowContainsSymbol(char**& board, int row, char symbol) const
  250. {
  251.     for (unsigned int i = 0; i < COLSNUM; ++i)
  252.         if (board[row][i] == symbol)
  253.             return true;
  254.     return false;
  255. }
  256.  
  257. bool Player::colContainsSymbol(char**& board, int col, char symbol) const
  258. {
  259.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  260.         if (board[i][col] == symbol)
  261.             return true;
  262.     return false;
  263. }
  264.  
  265. bool Player::diagContainsSymbol(char**& board, int diag, char symbol) const
  266. {
  267.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  268.     {
  269.         if (diag == 1 && board[i][i] == symbol)
  270.             return true;
  271.         else if (diag == 2 && board[ROWSNUM - i - 1][ROWSNUM - i - 1] == symbol)
  272.             return true;
  273.     }
  274.     return false;
  275. }
  276.  
  277. void Player::placeSymbolInRow(char**& board, int row) const
  278. {
  279.     for (unsigned int i = 0; i < COLSNUM; ++i)
  280.     {
  281.         if (board[row][i] == ' ')
  282.         {
  283.             board[row][i] = mSymbol;
  284.             if (canWin(board, mSymbol, false))
  285.                 break;
  286.             else //if we are not making a valuable pair, we should try another
  287.                 board[row][i] = ' ';
  288.         }
  289.     }
  290. }
  291.  
  292. void Player::placeSymbolInCol(char**& board, int col) const
  293. {
  294.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  295.     {
  296.         if (board[i][col] == ' ')
  297.         {
  298.             board[i][col] = mSymbol;
  299.             if (canWin(board, mSymbol, false))
  300.                 break;
  301.             else //if we are not making a valuable pair, we should try another
  302.                 board[i][col] = ' ';
  303.         }
  304.     }
  305. }
  306.  
  307. void Player::placeSymbolInDiag(char**& board, int diag) const
  308. {
  309.     for (unsigned int i = 0; i < ROWSNUM; ++i)
  310.     {
  311.         if (diag == 1 && board[i][i] == ' ')
  312.         {
  313.             board[i][i] = mSymbol;
  314.             if (canWin(board, mSymbol, false))
  315.                 return;
  316.             else //if we are not making a valuable pair, we should try another
  317.                 board[i][i] = ' ';
  318.         }
  319.         else if (diag == 2 && board[ROWSNUM - i - 1][ROWSNUM - i - 1] == ' ')
  320.         {
  321.             board[ROWSNUM - i - 1][ROWSNUM - i - 1] = mSymbol;
  322.             if (canWin(board, mSymbol, false))
  323.                 return;
  324.             else //if we are not making a valuable pair, we should try another
  325.                 board[ROWSNUM - i - 1][ROWSNUM - i - 1] = ' ';
  326.         }
  327.     }
  328. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement