/**
Simon Game for Arduino with Score display
Copyright (C) 2022, Uri Shaked
Released under the MIT License.
*/
#include "pitches.h"
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
/* Constants - define pin numbers for LEDs,
buttons and speaker, and also the game tones: */
const uint8_t ledPins[] = {9, 10, 11, 12, A0, A1};
const uint8_t buttonPins[] = {2, 3, 4, 5, 6, 7};
#define SPEAKER_PIN 8
#define MAX_GAME_LENGTH 100
const int gameTones[] = { NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G5, NOTE_C5, NOTE_E5};
// G3 = 196 // C4 = 262 // E4 = 330 // G5 = 784 //
/* Global variables - store the game state */
uint8_t gameSequence[MAX_GAME_LENGTH] = {0};
uint8_t gameIndex = 0;
/**
Set up the Arduino board and initialize Serial communication
*/
void setup() {
Serial.begin(9600);
for (byte i = 0; i < 6; i++) {
pinMode(ledPins[i], OUTPUT);
pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(SPEAKER_PIN, OUTPUT);
// The following line primes the random number generator.
// It assumes pin A3 is floating (disconnected):
randomSeed(analogRead(A3));
lcd.init();
lcd.backlight();
lcd.clear();
}
/**
Lights the given LED and plays a suitable tone
*/
void lightLedAndPlayTone(byte ledIndex) {
digitalWrite(ledPins[ledIndex], HIGH);
tone(SPEAKER_PIN, gameTones[ledIndex]);
delay(300);
digitalWrite(ledPins[ledIndex], LOW);
noTone(SPEAKER_PIN);
}
/**
Plays the current sequence of notes that the user has to repeat
*/
void playSequence() {
for (int i = 0; i < gameIndex; i++) {
byte currentLed = gameSequence[i];
lightLedAndPlayTone(currentLed);
delay(50);
}
}
/**
Waits until the user pressed one of the buttons,
and returns the index of that button
*/
byte readButtons() {
while (true) {
for (byte i = 0; i < 6; i++) {
byte buttonPin = buttonPins[i];
if (digitalRead(buttonPin) == LOW) {
return i;
}
}
delay(1);
}
}
/**
Play the game over sequence, and report the game score
*/
void gameOver() {
lcd.clear();
Serial.print("Game over! your score: ");
lcd.setCursor(1,0);
lcd.print("Game over!");
lcd.setCursor(1,1);
lcd.print("Your score: ");
Serial.println(gameIndex - 1);
lcd.setCursor(13,1);
lcd.print(gameIndex - 1);
gameIndex = 0;
delay(200);
// Play a Wah-Wah-Wah-Wah sound
tone(SPEAKER_PIN, NOTE_DS5);
delay(300);
tone(SPEAKER_PIN, NOTE_D5);
delay(300);
tone(SPEAKER_PIN, NOTE_CS5);
delay(300);
for (byte i = 0; i < 10; i++) {
for (int pitch = -10; pitch <= 10; pitch++) {
tone(SPEAKER_PIN, NOTE_C5 + pitch);
delay(5);
}
}
noTone(SPEAKER_PIN);
delay(500);
}
/**
Get the user's input and compare it with the expected sequence.
*/
bool checkUserSequence() {
for (int i = 0; i < gameIndex; i++) {
byte expectedButton = gameSequence[i];
byte actualButton = readButtons();
lightLedAndPlayTone(actualButton);
if (expectedButton != actualButton) {
return false;
}
}
return true;
}
/**
Plays a hooray sound whenever the user finishes a level
*/
void playLevelUpSound() {
tone(SPEAKER_PIN, NOTE_E4);
delay(150);
tone(SPEAKER_PIN, NOTE_G4);
delay(150);
tone(SPEAKER_PIN, NOTE_E5);
delay(150);
tone(SPEAKER_PIN, NOTE_C5);
delay(150);
tone(SPEAKER_PIN, NOTE_D5);
delay(150);
tone(SPEAKER_PIN, NOTE_G5);
delay(150);
noTone(SPEAKER_PIN);
}
/**
The main game loop
*/
void loop() {
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Welcome to");
lcd.setCursor(1,1);
lcd.print("Mini Game SMK 7");
// Add a random color to the end of the sequence
gameSequence[gameIndex] = random(0, 6);
gameIndex++;
if (gameIndex >= MAX_GAME_LENGTH) {
gameIndex = MAX_GAME_LENGTH - 1;
}
playSequence();
if (!checkUserSequence()) {
gameOver();
}
delay(300);
if (gameIndex > 0) {
playLevelUpSound();
delay(300);
}
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
buzzer:1
buzzer:2
led-red:A
led-red:C
led-green:A
led-green:C
led-blue:A
led-blue:C
led-yellow:A
led-yellow:C
btn-red:1.l
btn-red:2.l
btn-red:1.r
btn-red:2.r
btn-green:1.l
btn-green:2.l
btn-green:1.r
btn-green:2.r
btn-blue:1.l
btn-blue:2.l
btn-blue:1.r
btn-blue:2.r
btn-yellow:1.l
btn-yellow:2.l
btn-yellow:1.r
btn-yellow:2.r
led1:A
led1:C
led2:A
led2:C
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL