Editorial Solution

  • From the task, we understand that we have to: 
    • Develop a number guessing game.
    • Save the score such that the scores are saved across the controller restart
    • Display the leaderboard with the current score if it qualifies for the leaderboard.
  • For developing the number guessing game, we can do the following:
    • Select a random number for a particular session, and maintain a guess count.
    • Prompt the user to enter his guess via the serial monitor.
    • Increase the guess count for each user’s guess.
    • If the user’s guess matches the random number selected, save the current guess count in EEPROM and display the leaderboard.
  • For displaying the leaderboard:
    • Fetch the value from the first 10 locations of the EEPROM.
    • Sort the value using the bubble sort and display the leaderboard.
    • If the current score is in the leaderboard, put the “You” tag before the score.

Code

#include <EEPROM.h>


// EEPROM Structure
const int HISTORY_ADDR = 0;      // Starting address for score history
const int MAX_HISTORY = 10;      // Track last 10 scores
const int MAX_NUMBER = 100;      // Max number to guess
int randomNumber;                // Randomly generated number
int guesses;                     // Number of guesses in the current session


void setup() {
 Serial.begin(9600);
 randomSeed(analogRead(A0));    // Seed for random number generation
 randomNumber = random(1, MAX_NUMBER + 1);
 guesses = 0;


 Serial.println("Welcome to the Number Guessing Game!");
 Serial.println("Guess the number between 1 and 100.");
 Serial.println();
}


void loop() {
 if (Serial.available()) {
   int guess = Serial.parseInt();


   if(guess == 0)
   {
    /*
     * Handling the NL and CR here
     */
     return;
   }
   else if (guess < 1 || guess > MAX_NUMBER) {
     Serial.println("Invalid input. Please guess a number between 1 and 100.");
     return;
   }


   guesses++;
   if (guess < randomNumber) {
     Serial.println("Too Low!");
   } else if (guess > randomNumber) {
     Serial.println("Too High!");
   } else {
     Serial.print("Correct! You guessed it in ");
     Serial.print(guesses);
     Serial.println(" attempts!");


     saveScore(guesses);
     displayLeaderboard(guesses);
     displayHistory();


     Serial.println("Game Over! Resetting...");
     delay(2000);
     resetGame();
   }
 }
}


void saveScore(int score) {
 // Update history log by shifting older scores
 for (int i = (MAX_HISTORY - 1); i > 0; i--) {
   EEPROM.write(HISTORY_ADDR + i, EEPROM.read(HISTORY_ADDR + (i - 1)));
 }
 // Save the latest score
 EEPROM.write(HISTORY_ADDR, score);


 Serial.println("Saving your score...");
}


void displayLeaderboard(int currentScore) {
 Serial.println("\nLeaderboard:");


 // Fetch and sort the scores
 int scores[MAX_HISTORY];
 int validScores = 0;
 for (int i = 0; i < MAX_HISTORY; i++) {
   int score = EEPROM.read(HISTORY_ADDR + i);
   if (score > 0 && score != 255) { // Ignore invalid or uninitialized scores
     scores[validScores++] = score;
   }
 }


 // Sort scores for ranking
 for (int i = 0; i < validScores - 1; i++) {
   for (int j = i + 1; j < validScores; j++) {
     if (scores[j] < scores[i]) { // Bubble Sort Algorithm
       int temp = scores[i];
       scores[i] = scores[j];
       scores[j] = temp;
     }
   }
 }


 // Display sorted leaderboard with "You" tag for the current score
 bool currentScoreTagged = false;
 for (int i = 0; i < validScores; i++) {
   Serial.print(i + 1);
   Serial.print(". ");
   Serial.print(scores[i]);
   Serial.print(" Guesses");
   if (!currentScoreTagged && scores[i] == currentScore) {
     Serial.print(" (You)");
     currentScoreTagged = true;
   }
   Serial.println();
 }


 if (validScores == 0) {
   Serial.println("No scores available.");
 } else if (!currentScoreTagged) {
   Serial.println("\nYour score is not in the top 10.");
 }
}


void displayHistory() {
 Serial.println("\nLast 10 Scores:");
 for (int i = 0; i < MAX_HISTORY; i++) {
   int score = EEPROM.read(HISTORY_ADDR + i);
   if (score > 0 && score != 255) {
     Serial.print(score);
     Serial.print(" Guesses");
   } else {
     Serial.print("-");
   }
   if (i < MAX_HISTORY - 1) Serial.print(", ");
 }
 Serial.println();
}


void resetGame() {
 randomNumber = random(1, MAX_NUMBER + 1);
 guesses = 0;
 Serial.println("New game started! Guess the number between 1 and 100.");
}


Code Explanation

Display Leaderboard - displayLeaderboard(int currentScore)

Retrieve Scores:

  • Reads scores from EEPROM (HISTORY_ADDR) and stores valid scores (> 0) into the scores array.

Sort Scores:

  • Sorts the scores in ascending order to rank players based on the fewest guesses.
  • Implements a simple Bubble Sort algorithm for sorting the scores.

Highlight Current Session:

  • Displays the sorted scores with ranks.
  • Mark the current session's score with (You) if it qualifies for the leaderboard.

Edge Case Handling:

  • If the current session's score is not in the top 10, it notifies the player.
void displayLeaderboard(int currentScore) {
    Serial.println("\nLeaderboard:");

    int scores[MAX_HISTORY];
    int validScores = 0;
    for (int i = 0; i < MAX_HISTORY; i++) {
        int score = EEPROM.read(HISTORY_ADDR + i);
        if (score > 0) {
            scores[validScores++] = score;
        }
    }

    // Sort scores in ascending order
    for (int i = 0; i < validScores - 1; i++) {
        for (int j = i + 1; j < validScores; j++) {
            if (scores[j] < scores[i]) {
                int temp = scores[i];
                scores[i] = scores[j];
                scores[j] = temp;
            }
        }
    }

    // Display leaderboard
    bool currentScoreTagged = false;
    for (int i = 0; i < validScores; i++) {
        Serial.print(i + 1);
        Serial.print(". ");
        Serial.print(scores[i]);
        Serial.print(" Guesses");
        if (!currentScoreTagged && scores[i] == currentScore) {
            Serial.print(" (You)");
            currentScoreTagged = true;
        }
        Serial.println();
    }

    if (!currentScoreTagged) {
        Serial.println("\nYour score is not in the top 10.");
    }
}

 

Display History - void displayHistory()

Retrieve History:

  • Reads the last 10 scores stored sequentially in EEPROM (HISTORY_ADDR).

Display Scores

  • Iterates through the scores and displays each one in the order they were stored.
  • Adds formatting (e.g., commas) for better readability.

Handling Empty Entries

  • Ignores empty or invalid scores (default EEPROM values).
  • Ensures the history log remains clean and relevant.
void displayHistory() {
    Serial.println("\nLast 10 Scores:");
    for (int i = 0; i < MAX_HISTORY; i++) {
        int score = EEPROM.read(HISTORY_ADDR + i);
        if (score > 0) {
            Serial.print(score);
            Serial.print(" Guesses");
            if (i < MAX_HISTORY - 1) Serial.print(", ");
        }
    }
    Serial.println();
}

 

OUTPUT

 

 

 

Submit Your Solution