Objective
The task is to build a number-guessing game using a microcontroller, where the system randomly selects a number between 1 and 100, and the user guesses it through a serial terminal (e.g., PuTTY or Arduino IDE).
Requirements
Why Use EEPROM?
This task can be implemented with the following microcontrollers:
We are using the ESP32 DevKitC v4 development board and programming it using the Arduino IDE.
We are going to use EEPROM to implement this task, but ESP32 does not have a real EEPROM chip inside. Instead, part of its Flash memory is used to simulate EEPROM behaviour.
Connect the ESP32 development board to your computer using a USB cable.
#include <EEPROM.h>
// EEPROM Emulation Configuration
#define EEPROM_SIZE 128 // Using 128 bytes of flash (can be adjusted)
// Game Constants
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(115200);
// Initialize EEPROM emulation with specified size
EEPROM.begin(EEPROM_SIZE);
// Seed random number generator
randomSeed(analogRead(34));
randomNumber = random(1, MAX_NUMBER + 1);
guesses = 0;
Serial.println("\nWelcome 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 newline/carriage return
while (Serial.available()) Serial.read(); // Clear buffer
return;
} else if (guess < 1 || guess > MAX_NUMBER) {
Serial.println("Invalid input. Please guess a number between 1 and 100.");
while (Serial.available()) Serial.read(); // Clear buffer
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();
}
while (Serial.available()) Serial.read(); // Clear buffer
}
}
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);
// Commit changes to flash (important!)
EEPROM.commit();
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("\nNew game started! Guess the number between 1 and 100.");
}setup();loop();Serial.parseInt(), checks if it’s within 1–100, and increments the guess count. saveScore(int score);EEPROM.commit().displayLeaderboard(int currentScore);displayHistory();resetGame();EEPROM.begin(size);EEPROM.write(address, value);commit() to save).EEPROM.read(address);EEPROM.commit();randomSeed(analogRead(34)); / random(1, MAX_NUMBER + 1);random() (or its lower-level version rand()) is a pseudo-random number generator (PRNG).We are using the Arduino UNO development board and programming it using the Arduino IDE.
Connect the Arduino UNO development board to your computer using a USB cable.
We are going to use EEPROM.h library to implement this task. In Arduino UNO, there is a separate EEPROM chip available of 1KB.
#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.");
}setup();analogRead(A0), creates a random target number (1–100), resets the guess counter, and prints the welcome message.loop();Serial.parseInt(), ignores blank input, and validates if it’s between 1–100.saveScore(int score);displayLeaderboard(int currentScore);displayHistory();resetGame();EEPROM.read() / EEPROM.write();randomSeed(analogRead(A0)); / random(1, MAX_NUMBER + 1);