pabloliva87

TTTPabloOliva

Sep 5th, 2014
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.62 KB | None | 0 0
  1. #define BoardSize 3u // Look at what you made me do, Daniel.
  2. #define WinArraySize 8u
  3.  
  4. typedef unsigned int EncodedValue;
  5.  
  6. enum Cell
  7. {
  8.     Empty,
  9.     Circle,
  10.     Cross
  11. };
  12.  
  13. typedef enum Cell Board[BoardSize][BoardSize];
  14.  
  15. enum BoardClassification
  16. {
  17.     NoWinnersYet,
  18.     Tie,
  19.     CircleWin,
  20.     CrossWin,
  21.     InvalidBoard
  22. };
  23.  
  24. // Tells if there is still room to place new values.
  25. bool spaceAvailable(const Board* board)
  26. {
  27.     bool result = false;
  28.     unsigned int row = 0u;
  29.     unsigned int col = 0u;
  30.  
  31.     while (!result && row < BoardSize)
  32.     {
  33.         while (!result && col < BoardSize)
  34.         {
  35.             result = (*(board[row][col]) == Empty);
  36.             ++col;
  37.         }
  38.         ++row;
  39.     }
  40.     return result;
  41. }
  42.  
  43. // Classifies the board into one of the five BoardClassification categories.
  44. enum BoardClassification chooseClassification(const unsigned int circleWins, const unsigned int crossWins, const bool freeSpace)
  45. {
  46.     enum BoardClassification result;
  47.  
  48.     if (circleWins == 0u && crossWins == 0u)
  49.     {
  50.         if (freeSpace)
  51.         {
  52.             result = NoWinnersYet;
  53.         }
  54.         else // If nobody won and there are no more possible moves, it's a tie.
  55.         {
  56.             result = Tie;
  57.         }
  58.     }
  59.     else if (circleWins == 1u && crossWins == 0u)
  60.     {
  61.         result = CircleWin;
  62.     }
  63.     else if (circleWins == 0u && crossWins == 1u)
  64.     {
  65.         result = CrossWin;
  66.     }
  67.     else // (circleWins + crossWins > 1u)
  68.     {
  69.         result = InvalidBoard;
  70.     }
  71.  
  72.     return result;
  73. }
  74.  
  75.  
  76. // Based on the contents of board[row][col], it ORs result by the corresponding value
  77. // if board[row][col] is a Circle or a Cross; does nothing otherwise.
  78. void encodeCell(const Board* board, const unsigned int row, const unsigned int col, EncodedValue* result)
  79. {
  80.     static const EncodedValue CrossShifts  [BoardSize * BoardSize] = {1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u};
  81.     static const EncodedValue CircleShifts [BoardSize * BoardSize] = {11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u};
  82.  
  83.     const enum Cell currentCell = *(board[row][col]);
  84.     if (currentCell == Circle)
  85.     {
  86.         *result |= 0x1 << CircleShifts[row * BoardSize + col];
  87.     }
  88.     else if (currentCell == Cross)
  89.     {
  90.         *result |= 0x1 << CrossShifts[row * BoardSize + col];
  91.     } // No further processing needed for empty space.
  92. }
  93.  
  94. // Calculates the value that uniquely characterizes this board.
  95. EncodedValue encodeBoard(const Board* board)
  96. {
  97.     EncodedValue result = 0x0;
  98.  
  99.     for (unsigned int i = 0u; i < BoardSize; ++i)
  100.     {
  101.         for (unsigned int j = 0u; j < BoardSize; ++j)
  102.         {
  103.             encodeCell(board, i, j, &result);
  104.         }
  105.     }
  106.  
  107.     return result;
  108. }
  109.  
  110. // Counts the amount of matches between the winning combinations of winValues and boardValue
  111. unsigned int countWins(const EncodedValue* winValues, const EncodedValue boardValue)
  112. {
  113.     unsigned int result = 0u;
  114.     for (unsigned int i = 0u; i < WinArraySize; ++i)
  115.     {
  116.         result += ((boardValue & winValues[i]) == winValues[i]);
  117.     }
  118.  
  119.     return result;
  120. }
  121.  
  122. // Calculates the amount of winning combinations and the available space, and classifies the board accordingly.
  123. enum BoardClassification classifyBoard(const Board* board)
  124. {
  125.     static const EncodedValue CrossWinValues [WinArraySize] =
  126.     {
  127.      (0x1 << 1u) | (0x1 << 2u) | (0x1 << 3u),          // Row wins
  128.      (0x1 << 4u) | (0x1 << 5u) | (0x1 << 6u),
  129.      (0x1 << 7u) | (0x1 << 8u) | (0x1 << 9u),
  130.      (0x1 << 1u) | (0x1 << 4u) | (0x1 << 7u),          // Col wins
  131.      (0x1 << 2u) | (0x1 << 5u) | (0x1 << 8u),
  132.      (0x1 << 3u) | (0x1 << 6u) | (0x1 << 9u),
  133.      (0x1 << 1u) | (0x1 << 5u) | (0x1 << 9u),          // Diagonal wins
  134.      (0x1 << 3u) | (0x1 << 5u) | (0x1 << 7u)
  135.     };
  136.     static const EncodedValue CircleWinValues [WinArraySize] =
  137.     {
  138.      (0x1 << 11u) | (0x1 << 12u) | (0x1 << 13u),         // Row wins
  139.      (0x1 << 14u) | (0x1 << 15u) | (0x1 << 16u),
  140.      (0x1 << 17u) | (0x1 << 18u) | (0x1 << 19u),
  141.      (0x1 << 11u) | (0x1 << 14u) | (0x1 << 17u),         // Col wins
  142.      (0x1 << 12u) | (0x1 << 15u) | (0x1 << 18u),
  143.      (0x1 << 13u) | (0x1 << 16u) | (0x1 << 19u),
  144.      (0x1 << 11u) | (0x1 << 15u) | (0x1 << 19u),         // Diagonal wins
  145.      (0x1 << 13u) | (0x1 << 15u) | (0x1 << 17u)
  146.     };
  147.     const EncodedValue boardValue = encodeBoard(board);
  148.  
  149.     const unsigned int circleWins = countWins(CircleWinValues, boardValue);
  150.     const unsigned int crossWins = countWins(CrossWinValues, boardValue);
  151.     const bool freeSpace = spaceAvailable(board);
  152.  
  153.     return chooseClassification(circleWins, crossWins, freeSpace);
  154. }
Add Comment
Please, Sign In to add comment