Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define BoardSize 3u // Look at what you made me do, Daniel.
- #define WinArraySize 8u
- typedef unsigned int EncodedValue;
- enum Cell
- {
- Empty,
- Circle,
- Cross
- };
- typedef enum Cell Board[BoardSize][BoardSize];
- enum BoardClassification
- {
- NoWinnersYet,
- Tie,
- CircleWin,
- CrossWin,
- InvalidBoard
- };
- // Tells if there is still room to place new values.
- bool spaceAvailable(const Board* board)
- {
- bool result = false;
- unsigned int row = 0u;
- unsigned int col = 0u;
- while (!result && row < BoardSize)
- {
- while (!result && col < BoardSize)
- {
- result = (*(board[row][col]) == Empty);
- ++col;
- }
- ++row;
- }
- return result;
- }
- // Classifies the board into one of the five BoardClassification categories.
- enum BoardClassification chooseClassification(const unsigned int circleWins, const unsigned int crossWins, const bool freeSpace)
- {
- enum BoardClassification result;
- if (circleWins == 0u && crossWins == 0u)
- {
- if (freeSpace)
- {
- result = NoWinnersYet;
- }
- else // If nobody won and there are no more possible moves, it's a tie.
- {
- result = Tie;
- }
- }
- else if (circleWins == 1u && crossWins == 0u)
- {
- result = CircleWin;
- }
- else if (circleWins == 0u && crossWins == 1u)
- {
- result = CrossWin;
- }
- else // (circleWins + crossWins > 1u)
- {
- result = InvalidBoard;
- }
- return result;
- }
- // Based on the contents of board[row][col], it ORs result by the corresponding value
- // if board[row][col] is a Circle or a Cross; does nothing otherwise.
- void encodeCell(const Board* board, const unsigned int row, const unsigned int col, EncodedValue* result)
- {
- static const EncodedValue CrossShifts [BoardSize * BoardSize] = {1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u};
- static const EncodedValue CircleShifts [BoardSize * BoardSize] = {11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u};
- const enum Cell currentCell = *(board[row][col]);
- if (currentCell == Circle)
- {
- *result |= 0x1 << CircleShifts[row * BoardSize + col];
- }
- else if (currentCell == Cross)
- {
- *result |= 0x1 << CrossShifts[row * BoardSize + col];
- } // No further processing needed for empty space.
- }
- // Calculates the value that uniquely characterizes this board.
- EncodedValue encodeBoard(const Board* board)
- {
- EncodedValue result = 0x0;
- for (unsigned int i = 0u; i < BoardSize; ++i)
- {
- for (unsigned int j = 0u; j < BoardSize; ++j)
- {
- encodeCell(board, i, j, &result);
- }
- }
- return result;
- }
- // Counts the amount of matches between the winning combinations of winValues and boardValue
- unsigned int countWins(const EncodedValue* winValues, const EncodedValue boardValue)
- {
- unsigned int result = 0u;
- for (unsigned int i = 0u; i < WinArraySize; ++i)
- {
- result += ((boardValue & winValues[i]) == winValues[i]);
- }
- return result;
- }
- // Calculates the amount of winning combinations and the available space, and classifies the board accordingly.
- enum BoardClassification classifyBoard(const Board* board)
- {
- static const EncodedValue CrossWinValues [WinArraySize] =
- {
- (0x1 << 1u) | (0x1 << 2u) | (0x1 << 3u), // Row wins
- (0x1 << 4u) | (0x1 << 5u) | (0x1 << 6u),
- (0x1 << 7u) | (0x1 << 8u) | (0x1 << 9u),
- (0x1 << 1u) | (0x1 << 4u) | (0x1 << 7u), // Col wins
- (0x1 << 2u) | (0x1 << 5u) | (0x1 << 8u),
- (0x1 << 3u) | (0x1 << 6u) | (0x1 << 9u),
- (0x1 << 1u) | (0x1 << 5u) | (0x1 << 9u), // Diagonal wins
- (0x1 << 3u) | (0x1 << 5u) | (0x1 << 7u)
- };
- static const EncodedValue CircleWinValues [WinArraySize] =
- {
- (0x1 << 11u) | (0x1 << 12u) | (0x1 << 13u), // Row wins
- (0x1 << 14u) | (0x1 << 15u) | (0x1 << 16u),
- (0x1 << 17u) | (0x1 << 18u) | (0x1 << 19u),
- (0x1 << 11u) | (0x1 << 14u) | (0x1 << 17u), // Col wins
- (0x1 << 12u) | (0x1 << 15u) | (0x1 << 18u),
- (0x1 << 13u) | (0x1 << 16u) | (0x1 << 19u),
- (0x1 << 11u) | (0x1 << 15u) | (0x1 << 19u), // Diagonal wins
- (0x1 << 13u) | (0x1 << 15u) | (0x1 << 17u)
- };
- const EncodedValue boardValue = encodeBoard(board);
- const unsigned int circleWins = countWins(CircleWinValues, boardValue);
- const unsigned int crossWins = countWins(CrossWinValues, boardValue);
- const bool freeSpace = spaceAvailable(board);
- return chooseClassification(circleWins, crossWins, freeSpace);
- }
Add Comment
Please, Sign In to add comment