#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// Initialize the I2C LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Keypad setup
const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
int targetNumber;
int guessCount = 0;
int maxAttempts;
String guessInput = "";
int buzzerPin = 11;
bool isRange99 = false; // Start with guessing range 0-9
bool buzzerEnabled = true; // Buzzer state
void setup() {
lcd.init();
lcd.backlight();
pinMode(buzzerPin, OUTPUT);
randomSeed(analogRead(0)); // Initialize random seed
startNewGame();
}
void loop() {
char key = customKeypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Limit input based on range
if ((isRange99 && guessInput.length() < 2) || (!isRange99 && guessInput.length() < 1)) {
guessInput += key;
updateDisplay();
} else {
displayLimitMessage();
}
} else if (key == '#') {
if (guessInput.length() > 0) {
int guessedNumber = guessInput.toInt();
int maxValue = isRange99 ? 99 : 9;
if (guessedNumber >= 0 && guessedNumber <= maxValue) {
checkGuess(guessedNumber);
guessInput = "";
} else {
displayInvalidInput();
guessInput = "";
}
}
} else if (key == '*') {
startNewGame();
} else if (key == 'A') {
showHelp();
} else if (key == 'B') {
if (guessInput.length() > 0) {
guessInput.remove(guessInput.length() - 1); // Remove last character
updateDisplay();
}
} else if (key == 'C') {
toggleRange();
} else if (key == 'D') {
toggleBuzzer();
}
}
}
void startNewGame() {
targetNumber = random(0, isRange99 ? 100 : 10); // Generate random number between 0-9 or 0-99
guessCount = 0;
maxAttempts = isRange99 ? 7 : 3; // Set max attempts to 7 for 0-99 and 3 for 0-9
guessInput = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Your Guess");
lcd.setCursor(0, 1);
lcd.print(isRange99 ? "(0-99)" : "(0-9)");
}
void updateDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Your Guess: ");
lcd.print(guessInput);
lcd.setCursor(0, 1);
lcd.print(isRange99 ? "(0-99)" : "(0-9)");
}
void checkGuess(int guessedNumber) {
guessCount++;
lcd.clear();
if (guessedNumber == targetNumber) {
lcd.setCursor(0, 0);
lcd.print("Correct! The ");
lcd.setCursor(0, 1);
lcd.print("Number is ");
lcd.print(guessedNumber);
playTone(1000, 500); // Play success tone
delay(2000);
displayFunnyMessage(true);
startNewGame();
} else if (guessedNumber < targetNumber) {
displayTryAgain("Low", "more attempts");
} else {
displayTryAgain("High", "more attempts");
}
if (guessCount >= maxAttempts) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Out of attempts!");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("The number was");
lcd.setCursor(0, 1);
lcd.print(targetNumber);
delay(3000);
startNewGame();
}
}
void displayInvalidInput() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid input!");
lcd.setCursor(0, 1);
lcd.print(isRange99 ? "Enter 0-99" : "Enter 0-9");
playTone(500, 200); // Play error tone
delay(2000);
updateDisplay();
}
void displayTryAgain(String line1, String line2) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
int remainingAttempts = maxAttempts - guessCount;
if (remainingAttempts > 1) {
lcd.print(remainingAttempts);
lcd.print(" ");
lcd.print(line2);
} else if (remainingAttempts == 1) {
lcd.print("1 more attempt");
}
playTone(500, 200); // Play incorrect guess tone
delay(1500);
updateDisplay();
}
void displayFunnyMessage(bool success) {
lcd.clear();
if (success) {
switch (random(0, 3)) {
case 0:
lcd.setCursor(0, 0);
lcd.print("You're a");
lcd.setCursor(0, 1);
lcd.print("Mind Reader!");
break;
case 1:
lcd.setCursor(0, 0);
lcd.print("Are you");
lcd.setCursor(0, 1);
lcd.print("psychic?!");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print("Congrats!");
lcd.setCursor(0, 1);
lcd.print("You nailed it!");
break;
}
}
delay(2000);
}
void showHelp() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("*: New Game");
lcd.setCursor(0, 1);
lcd.print("#: Confirm Guess");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("B: Backspace");
lcd.setCursor(0, 1);
lcd.print("C: Toggle Range");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("D: Buzzer On/Off");
lcd.setCursor(0, 1);
lcd.print(buzzerEnabled ? "Buzzer: ON" : "Buzzer: OFF");
delay(2000);
updateDisplay();
}
void displayLimitMessage() {
lcd.clear();
lcd.setCursor(0, 0);
if (isRange99) {
lcd.print("Limit: 2 Digits");
} else {
lcd.print("Limit: 1 Digit");
}
delay(2000);
updateDisplay(); // Return to guessing display
}
void toggleRange() {
isRange99 = !isRange99; // Toggle range
startNewGame(); // Restart game with new range
}
void toggleBuzzer() {
buzzerEnabled = !buzzerEnabled; // Toggle buzzer state
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(buzzerEnabled ? "Buzzer: ON" : "Buzzer: OFF");
delay(1000);
updateDisplay(); // Return to guessing display
}
void playTone(int frequency, int duration) {
if (buzzerEnabled) {
tone(buzzerPin, frequency, duration);
delay(duration);
noTone(buzzerPin);
}
}