Simon Says Memory Game!

by 929312 in Circuits > Arduino

246 Views, 1 Favorites, 0 Comments

Simon Says Memory Game!

IMG_5141.JPG

Simon Says is a memory game. Start the game by pressing one of the three buttons. When a button lights up, press the button, repeating the sequence. The sequence will get longer and longer. The game is won after 10 rounds. Generates random sequence, plays music, and displays button lights.



Supplies

61ULFspZSdL._AC_SX679_.jpg
71d1wRcqghL._SX425_.jpg
611N7Dw52dL._SX425_.jpg
Piezo.jpg
51+7w6NGyAL._SX425_.jpg

1 Red LED ($0.01)

1 Green LED ($0.01)

1 Yellow LED ($0.01)

1 Blue LED ($0.01)

4 resistors ($0.14)

4 buttons ($0.28)

1 piezo ($0.79)

1 Breadboard ($2.00)

1 Arduino ($28.50)

Wires (Length and amount depends on the size of breadboard and workspace) (Estimated cost $0.30)


Purchase Set of 500 LEDS on Amazon ($6.19)

Purchase Set of 200 (330 Ohm) Resistors on Amazon ($6.99)

Purchase Set of 100 Button on Amazon ($6.99)

Purchase Set of 10 Piezo Buzzers on Amazon ($7.86)

Purchase Set of 840 Jumper Wires on Amazon ($11.59)

Purchase Set of 6 Breadboards on Amazon ($11.99)

Purchase an Arduino on Amazon ($28.50)

Setup Your Bread Board

Screenshot 2023-01-25 9.19.53 AM.png

The first step is to starting any project is to set up your power and ground. As you can see in the image above Ground being sent to the ground lane. In this particular project all the power will be received from the pins so there is no need to set up the power lane.

Before starting any project it is good practice to test your materials to make sure they are indeed working accordingly. Particularly LEDs in this project were tested before any building took place. This included connecting the anode to power and the Cathode to a resistor that connected to ground. This simple test should turn the LED on, confirming it is functional and appropriate for use.

Buttons

Screenshot 2023-01-25 9.22.10 AM.png

Secondly, place your four buttons on the breadboard in succession like shown above. Have atleast two column space in between each button. Connect the button terminal 1a to ground for each button.

LEDs

Screenshot 2023-01-25 9.24.16 AM.png

Next, place your LEDs next to their corresponding button. Note that it would be most convenient that the corresponding and LED are in close proximity with each other in order to make the game easier to play. Connect the Cathode of the LEDs to ground using a Resistor (330 Ohm resistor is the best recommendation).

Pins & Piezo

Screenshot 2023-01-25 9.48.41 AM.png

Now connect your LEDs and buttons to the pins in the Arduino.

For the Blue LED we connect the Anode to pin 9 and for its correlating button's terminal 2a to pin 8. Continue this for the rest of the buttons. The blue, green, red, and yellow LED's would be connected to pins 9,7,5,3. The blue, green, red, and yellow buttons would be connected to pins 8,6,4,2. Notice how the LED's are connected to the odd pins and the buttons to the even pins. This will be important later in the code.

Place your piezo on your breadboard and connect the negative end to ground and positive end to pin 10 on the Arduino.

(Note that the corresponding pins and components can be rearranged. However these are the pins referred to in the code)

Beginning the Code

Screenshot 2023-01-25 10.07.57 AM.png
Screenshot 2023-01-25 10.07.10 AM.png

Now opening the Arduino software we begin our code in c++.

Starting off by setting the pins where the buttons, LEDs, and Piezo connect we write:

int button[] = {2,4,6,8};

int led[] = {3,5,7,9};       

int buzzerPin = 10;  


To declare the tones to play with each button (c, e, g, b) we write:

int tones[] = {262, 330, 392, 494};  


To declare the number of rounds the player has to play before they win the game (the array can only hold up  to 16 rounds) we write:

int roundsToWin = 10;    

int buttonSequence[16];   


But we also need to make sure the game keeps track of what round the player is on and if no button is being pressed in order to restart the game. For this we will have to create a variable that represents when no button is being pressed so we write:

int pressedButton = 4;    

int roundCounter = 1;     


To add some difficulty to the game we added a time limit to hit a button and write:

long startTime = 0;      

long timeLimit = 2000;   

boolean gameStarted = false; 


Now we can start writing our void setup. Here we will define all the button as outputs and set all of the button pins to input_pullup. Input_pullup allows the buttons default state to be HIGH. Here we will also define the buzzer as an output device. So we write:


void setup(){

 pinMode(button[0], INPUT_PULLUP);

 pinMode(button[1], INPUT_PULLUP);

 pinMode(button[2], INPUT_PULLUP);

 pinMode(button[3], INPUT_PULLUP);

  

pinMode(led[0], OUTPUT);

 pinMode(led[1], OUTPUT);

 pinMode(led[2], OUTPUT);

 pinMode(led[3], OUTPUT);

 pinMode(buzzerPin, OUTPUT);  

}



Writing Void Loop

IMG_5191.jpg

In Void loop we want to make sure that the game can restart by itself regardless of whether the player wins or loses. We do this by resetting the round counter if the gameStarted = false. We will also flash the LEDs in a start sequence to indicate to the player that the game is starting again after all this we write gameStarted = true so that the game dosn't reset itself again. So we write:


void loop(){

if (gameStarted == false){  

 startSequence();      

 roundCounter = 0;      

 delay(1500);        

 gameStarted = true;     

}


//each round, start by flashing out the sequence to be repeated

for(int i=0; i <= roundCounter; i++){  //go through the array up to the current round number

 flashLED(buttonSequence[i]);     //turn on the LED for that array position and play the sound

 delay(200);              //wait

 allLEDoff();             //turn all of the LEDs off

 delay(200);

}


Then we want the game to start going through the sequence one at a time and see if the user presses the correct button while simultaneously recording the start time. However if a button 4 or greater is pressed (4 means that no button is pressed) then play the loose sequence and then create a "break" to end the "while" so that the game can start over. Otherwise if the button pressed matches the LED lit then the loop will continue with the next round in the sequence. If we reach the round limit (10 but can be up to 16) than the winner sound will play. We would write this like the following:


for(int i=0; i <= roundCounter; i++){  

 startTime = millis();         

 while(true){ 

  pressedButton = buttonCheck();   

  if (pressedButton < 4){       

   flashLED(pressedButton);    


   if(pressedButton == buttonSequence[i]){  

     delay(250);         

     allLEDoff();         

     break;            

   } else{             

     loseSequence();        

     break;            

   }

  } else {              

   allLEDoff();           

  }

  if(millis() - startTime > timeLimit){  

   loseSequence();           

   break;               

  }

 }   

}

 roundCounter = roundCounter + 1;   

 if (roundCounter >= roundsToWin){        

  winSequence();           

 }

 delay(500);              

}

Functions

The first void we must define is flashLED(int ledNumber). This function takes an integer argument, ledNumber, which is used to determine which LED should be turned on. The function uses the digitalWrite() function to set the specified LED to a high state, and uses the tone() function to play a sound on the buzzer pin, using a predefined frequency that corresponds to the led number passed as an argument. We would write this as:


void flashLED (int ledNumber){

 digitalWrite(led[ledNumber], HIGH);

 tone(buzzerPin, tones[ledNumber]);

}


Next function is allLEDoff(). This function turns all of the LEDs off using digitalWrite() function and turns the buzzer off using noTone() function. We would write this as:

void allLEDoff (){

 digitalWrite(led[0],LOW);

 digitalWrite(led[1],LOW);

 digitalWrite(led[2],LOW);

 digitalWrite(led[3],LOW);

 noTone(buzzerPin);

}


Now we write function buttonCheck(). This function checks if any of the buttons are being pressed. It uses the digitalRead() function to check the state of each button, and returns an integer value corresponding to the button that is being pressed. If no button is pressed, it returns the value 4. We write this as:


int buttonCheck(){

 if(digitalRead(button[0]) == LOW){

  return 0;

 }else if(digitalRead(button[1]) == LOW){

  return 1;

 }else if(digitalRead(button[2]) == LOW){

  return 2;

 }else if(digitalRead(button[3]) == LOW){

  return 3;

 }else{

  return 4;

 }

}


The next function is startSequence(). This function is used to initialize the game. It uses the randomSeed() function to seed the random number generator, then uses a for loop to generate a random sequence of button presses. Next, it flashes all of the LEDs and plays different tones for a moment when the game starts. We would write this as:


void startSequence(){

 randomSeed(analogRead(A0)); 

 for (int i=0;i<=roundsToWin;i++){

  buttonSequence[i] = round(random(0,4));

 }


 for(int i=0; i<=3; i++){

  tone(buzzerPin, tones[i], 200);


  digitalWrite(led[0],HIGH);

  digitalWrite(led[1],HIGH);

  digitalWrite(led[2],HIGH);

  digitalWrite(led[3],HIGH);


  delay(100);   


  digitalWrite(led[0],LOW);

  digitalWrite(led[1],LOW);

  digitalWrite(led[2],LOW);

  digitalWrite(led[3],LOW);

  delay(100); 


The next function is winSequence(). This function is called when the player wins the game. It turns all of the LEDs on, and plays a celebratory sound on the buzzer using tone() function. It then waits for the player to press a button, then resets the game so that the start sequence will play again. We would write this as:


void winSequence(){


 for(int j=0; j<=3; j++){

  digitalWrite(led[j], HIGH);

 }


 tone(buzzerPin, 1318, 150);  //E6

 delay(175);

 tone(buzzerPin, 1567, 150);  //G6

 delay(175);

 tone(buzzerPin, 2637, 150);  //E7

 delay(175);

 tone(buzzerPin, 2093, 150);  //C7

 delay(175);

 tone(buzzerPin, 2349, 150);  //D7

 delay(175);

 tone(buzzerPin, 3135, 500);  //G7

 delay(500);  


 do {     

  pressedButton = buttonCheck();

 } while(pressedButton > 3);

 delay(100);

 gameStarted = false; 

}


The final function is loseSequence(). This function is called when the player loses the game. It turns all of the LEDs on, and plays a losing sound on the buzzer using tone() function. It then waits for the player to press a button, then resets the game so that the start sequence will play again. We would write this as:


void loseSequence(){

 for(int j=0; j<=3; j++){

  digitalWrite(led[j], HIGH);

 }


 tone(buzzerPin, 130, 250);  //E6

 delay(275);

 tone(buzzerPin, 73, 250);  //G6

 delay(275);

 tone(buzzerPin, 65, 150);  //E7

 delay(175);

 tone(buzzerPin, 98, 500);  //C7

 delay(500);


 do {     

  pressedButton = buttonCheck();

 } while(pressedButton > 3);

 delay(200);

 gameStarted = false;  

}