Example #1
0
/**
 * Recursive MiniMax algorithm that computes the best move at the current call's
 * move depth, based on the player.
 * @param  board  A pointer to a representation of the board to compute scores
 *                on. Note that this may be different than the actual current
 *                board.
 * @param  player Whether to evaluate the board as the player or the opponent.
 * @return        The MAX score if player, or MIN score if Opponent.
 */
minimax_score_t minimax(minimax_board_t* board, bool player) {
  // Increment depth at the beginning of this function call
  depth++;

  // Create 2 arrays (indexed the same) to save moves and their score
  // at this level of recursion.
  minimax_move_t moves[MINIMAX_TOTALSQUARES];
  minimax_score_t scores[MINIMAX_TOTALSQUARES];

  // Recursion base case, there has been a win or a draw.
  if (minimax_isGameOver(minimax_computeBoardScore(board))) {
    depth--;  // decrement depth as we return;

    // Since this call is the end case, simply return the board's score
    return minimax_computeBoardScore(board);
  }

  // Otherwise, the recursion is called.
  // This while-loop will generate all possible boards.
  int16_t index = 0;  // used to track the number of score/move pairs.
  int row, col;
  for (row = 0; row < MINIMAX_BOARD_ROWS; row++) {  // For each row
    for (col = 0; col < MINIMAX_BOARD_ROWS; col++) {  // For each column
      // Find an empty square
      if ((*board).squares[row][col] == MINIMAX_EMPTY_SQUARE) {
        // Assign the square to the player or opponent.
        if (player) {
          (*board).squares[row][col] = MINIMAX_PLAYER_SQUARE;
        }
        else {
          (*board).squares[row][col] = MINIMAX_OPPONENT_SQUARE;
        }
        // Make the recursive call that determines the MIN or MAX score
        // based on the player to save to the table.
        minimax_score_t score = minimax(board, !player);

        scores[index] = score;  // Add score to the score table
        moves[index].row = row; // Add move row to the move table
        moves[index].column = col;  // Add move column to the move table

        index++;  // Increment the index into the moves/scores table

        // Undo the change to the board (return the square to empty)
        // prior to next iteration of for-loops.
        (*board).squares[row][col] = MINIMAX_EMPTY_SQUARE;
      }
    }
  }

#ifdef MINIMAX_DEBUG
  // Print out Score Matrix at Top Level if DEBUG mode is enabled.
  // This is useful in visually checking that the score table is correct
  // after all of the recursive calls have been made.
 if (depth == 0) {
   printf("Scores:\n\r");
   int count;
   for (count = 0; count < index; count++) {
     printf("Move (%d, %d) Score: %d\n", moves[count].row, moves[count].column, scores[count]);
   }
 }
 #endif

  // Once here, we have iterated over empty squares at this level.
  // All of the scores and moves have been computed at this level.
  minimax_score_t score = 0; // the value of the score to return
  int16_t tempIndex = 0; // variable used to store the index of the MIN/MAX
  // Now we return the score based upon whether we are computing min or max.
  int i;
  if (player) {
    // If the player is X, we want to find the MAX score
    int16_t highScore = scores[0];  // Initialize to the first score.
    // Iterate over all of the move/score pairs in the table
    for (i = 0; i < index; i++) {
      if (scores[i] > highScore) {
        // Raise the maximum highScore found so far
        highScore = scores[i];
        tempIndex = i;
      }
    }
    choice = moves[tempIndex];  // Get the choice with the MAX score
    score = scores[tempIndex];  // Return the highest score in the table.
  }
  else {
    // If we are looking at 'O', we want to find the MIN score
    int16_t lowScore = scores[0];  // Initialize to the first score.
    // Iterate over all of the move/score pairs in the table
    for (i = 0; i < index; i++) {
      if (scores[i] < lowScore) {
        // Lower the minimum lowScore found so far
        lowScore = scores[i];
        tempIndex = i;
      }
    }
    choice = moves[tempIndex];  // Get the choice with the MIN score
    score = scores[tempIndex];  // Return the lowest score in the table.
  }

  // Done with the recursive call, decrement depth as we return
  depth--;
  return score;
}
Example #2
0
//checks if game is over
bool ticTacToeControl_checkEndGame(minimax_board_t *board, bool player)
{
    int16_t score = minimax_computeBoardScore(board, player); //get board score
    return minimax_isGameOver(score); //return if game is over
}