#define led_off 0 //Used to control LEDs #define choice_none 0 //Used to check buttons #define choice_red (1 << 0) #define choice_green (1 << 1) #define choice_blue (1 << 2) #define choice_yellow (1 << 3) //LED pin definitions #define led_red 17 #define led_green 26 #define led_blue 25 #define led_yellow 16 // Button pin definitions #define button_red 23 #define button_green 19 #define button_blue 22 #define button_yellow 18 // Buzzer pin definition #define buzzer 5 // Define game parameters int rounds = 5; //Number of rounds to succesfully remember before player turns off alarm, preset as 5 byte gameBoard[32]; //Array that ontains the combination of buttons as player advances byte gameRound = 0; //Counts the number of succesful rounds the player has made it through void setup() { //Setup hardware inputs/outputs //Enable pull up resistors on buttons pinMode(button_red, INPUT_PULLUP); pinMode(button_green, INPUT_PULLUP); pinMode(button_blue, INPUT_PULLUP); pinMode(button_yellow, INPUT_PULLUP); pinMode(led_red, OUTPUT); pinMode(led_green, OUTPUT); pinMode(led_blue, OUTPUT); pinMode(led_yellow, OUTPUT); pinMode(buzzer, OUTPUT); play_winner(); // After setup is complete, signal that it is done } void loop() { attractMode(); // Blink lights while waiting for player to press a button // Indicate the start of game play setLEDs(choice_red | choice_green | choice_blue | choice_yellow); // Turn all LEDs on delay(1000); setLEDs(led_off); // Turn off LEDs delay(250); // Play memory game and handle result if (simon() == true) play_winner(); // Player won, play winner tones else play_loser(255); // Player lost, play loser tones } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //The following functions are related to game play only boolean simon() // Returns 0 if player loses, or 1 if player wins { randomSeed(millis()); // Seed the random generator with random amount of millis() gameRound = 0; // Reset the game to the beginning while (gameRound < rounds) { add_to_moves(); // Add a button to the current moves, then play them back playMoves(); // Play back the current game board //Require the player to repeat the sequence for (byte currentMove = 0 ; currentMove < gameRound ; currentMove++) { byte choice = wait_for_button(); // See what button the user presses if (choice != gameBoard[currentMove]) return false; // If the choice is incorect, player loses } delay(1000); // Player was correct, delay before playing moves } return true; // Player made it through all the rounds to win! } void playMoves() //plays back current gameBoard { for (byte currentMove = 0 ; currentMove < gameRound ; currentMove++) { playLED(gameBoard[currentMove], 150); delay(150); // Wait some amount of time between button playback } } void add_to_moves() //adds new random button to gameBoard array by sampling timer { byte newButton = random(0, 4); //gives number between 0-3 inclusive if (newButton == 0) newButton = choice_red; //random number converted into specific color choices else if (newButton == 1) newButton = choice_green; else if (newButton == 2) newButton = choice_blue; else if (newButton == 3) newButton = choice_yellow; gameBoard[gameRound++] = newButton; // Add new button byte to the gameBoard array } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //The following functions control the hardware void setLEDs(byte leds) //lights specific LED according to choice byte { if ((leds & choice_red) != 0) digitalWrite(led_red, HIGH); else digitalWrite(led_red, LOW); if ((leds & choice_green) != 0) digitalWrite(led_green, HIGH); else digitalWrite(led_green, LOW); if ((leds & choice_blue) != 0) digitalWrite(led_blue, HIGH); else digitalWrite(led_blue, LOW); if ((leds & choice_yellow) != 0) digitalWrite(led_yellow, HIGH); else digitalWrite(led_yellow, LOW); } byte wait_for_button() //waits for button to be pressed and returns LED color as byte { while (1) // Loop until button is pressed { byte button = checkButton(); if (button != choice_none) { playLED(button, 150); // Play the button the player just pressed while (checkButton() != choice_none) ; // wait for player to release button delay(10); // This helps with debouncing and accidental double taps return button; } } } byte checkButton() // Returns a '1' bit in the position corresponding to choice_red, choice_green, etc. { if (digitalRead(button_red) == 0) return (choice_red); else if (digitalRead(button_green) == 0) return (choice_green); else if (digitalRead(button_blue) == 0) return (choice_blue); else if (digitalRead(button_yellow) == 0) return (choice_yellow); return (choice_none); // If no button is pressed, return none } void playLED(byte which, int LED_delay) //Light up an LED { setLEDs(which); //Turn on a given LED delay(LED_delay); setLEDs(led_off); // Turn off all LEDs } void play_winner() //play winner sound and lights { setLEDs(choice_green | choice_blue); winner_sound(); setLEDs(choice_red | choice_yellow); winner_sound(); setLEDs(choice_green | choice_blue); winner_sound(); setLEDs(choice_red | choice_yellow); winner_sound(); } void winner_sound() //function for winner sound { // Toggle the buzzer at various speeds for (byte x = 250 ; x > 70 ; x--) { for (byte y = 0 ; y < 3 ; y++) { digitalWrite(buzzer, LOW); delayMicroseconds(x); digitalWrite(buzzer, HIGH); delayMicroseconds(x); } } } void play_loser(int lose_length) //flash loser lights { setLEDs(choice_red | choice_green); delay (lose_length); setLEDs(choice_blue | choice_yellow); delay (lose_length); setLEDs(choice_red | choice_green); delay (lose_length); setLEDs(choice_blue | choice_yellow); delay (lose_length); } void attractMode() //show "attract mode" display while waiting for player to first press button to start game { while (1) { setLEDs(choice_red); delay(100); if (checkButton() != choice_none) return; setLEDs(choice_blue); delay(100); if (checkButton() != choice_none) return; setLEDs(choice_green); delay(100); if (checkButton() != choice_none) return; setLEDs(choice_yellow); delay(100); if (checkButton() != choice_none) return; } }