Go Down

Topic: Simon says (Read 4472 times) previous topic - next topic

digimike

Jan 22, 2010, 07:34 am Last Edit: Jan 22, 2010, 06:39 pm by digimike Reason: 1
This is the Simon Says game originally by Robert Spann. I realized that Simon says should be easy to do on the arduino. So i Googled around for any previous attempts and found Robert's thread posted nearly a year ago.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235696263

I also saw several videos on Youtube, but couldn't find the code for them. Some had sound with them but Robert's didn't. So i took the code, before he added sound to his, and trimmed it down a bit. I  then added my own version of sound coding to it using the Tone.h library. One thing i liked about the code was the cheat functionality too it. It reports to the PC what lights where light making it easy to just follow the numbers on the serial monitor. This is great for troubleshooting the code so i left it in. The hardware setup of the push buttons is different form his. I changed the code to allow the buttons to be set up without a pull down resistor.

Here is my updated version of Robert Spann's Simon Says game.
Thank for the code Robert (a.k.a jackal858).

Code: [Select]
/*Simon Says game. Now with sound effects.

Originaly made by Robert Spann
Code trimmed and sound effects added by digimike

Buttons are to be set on there designated pins without pull
down resistors and tied to ground. Internal pull down resistors
will be in use. Logis is reversed.

*/
#include <Tone.h>  // tone library for note playback
Tone speakerpin; // speaker ID
int note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};  // notes to be played for start and successful turn
int duration[] = {100, 100, 100, 300, 100, 300};  // pause between notes
boolean button[] = {2, 3, 4, 5}; //The four button input pins
boolean ledpin[] = {8, 9, 10, 11};  // LED pins
int turn = 0;  // turn counter
int buttonstate = 0;  // button state checker
int randomArray[100]; //Intentionally long to store up to 100 inputs (doubtful anyone will get this far)
int inputArray[100];  


void setup()
{
 Serial.begin(9600);
 speakerpin.begin(13); // speaker is on pin 13

 for(int x=0; x<4; x++)  // LED pins are outputs
 {
   pinMode(ledpin[x], OUTPUT);
 }
 
 for(int x=0; x<4; x++)
 {
   pinMode(button[x], INPUT);  // button pins are inputs
   digitalWrite(button[x], HIGH);  // enable internal pullup; buttons start in high position; logic reversed
 }

 randomSeed(analogRead(0)); //Added to generate "more randomness" with the randomArray for the output function

 for (int y=0; y<=99; y++)
 { //For statement to loop through the output and input functions
   loop();
   input();
 }

}

void loop()
{   //function for generating the array to be matched by the player
 digitalWrite(ledpin[0], HIGH);
 digitalWrite(ledpin[1], HIGH);
 digitalWrite(ledpin[2], HIGH);
 digitalWrite(ledpin[3], HIGH);
 
 for (int thisNote = 0; thisNote < 6; thisNote ++) {
  // play the next note:
  speakerpin.play(note[thisNote]);
  // hold the note:
  delay(duration[thisNote]);
  // stop for the next note:
  speakerpin.stop();
 }
   
 digitalWrite(ledpin[0], LOW);
 digitalWrite(ledpin[1], LOW);
 digitalWrite(ledpin[2], LOW);
 digitalWrite(ledpin[3], LOW);
 delay(1000);
 
 for (int y=turn; y <= turn; y++)
 { //Limited by the turn variable
   Serial.println(""); //Some serial output to follow along
   Serial.print("Turn: ");
   Serial.print(y);
   Serial.println("");
   randomArray[y] = random(1, 5); //Assigning a random number (1-4) to the randomArray[y], y being the turn count
   for (int x=0; x <= turn; x++)
   {
     Serial.print(randomArray[x]);
     
     for(int y=0; y<4; y++)
     {
     
       if (randomArray[x] == 1 && ledpin[y] == 8)
       {  //if statements to display the stored values in the array
         digitalWrite(ledpin[y], HIGH);
         speakerpin.play(NOTE_G3, 100);
         delay(400);
         digitalWrite(ledpin[y], LOW);
         delay(100);
       }

       if (randomArray[x] == 2 && ledpin[y] == 9)
       {
         digitalWrite(ledpin[y], HIGH);
         speakerpin.play(NOTE_A3, 100);
         delay(400);
         digitalWrite(ledpin[y], LOW);
         delay(100);
       }

       if (randomArray[x] == 3 && ledpin[y] == 10)
       {
         digitalWrite(ledpin[y], HIGH);
         speakerpin.play(NOTE_B3, 100);
         delay(400);
         digitalWrite(ledpin[y], LOW);
         delay(100);
       }

       if (randomArray[x] == 4 && ledpin[y] == 11)
       {
         digitalWrite(ledpin[y], HIGH);
         speakerpin.play(NOTE_C4, 100);
         delay(400);
         digitalWrite(ledpin[y], LOW);
         delay(100);
       }
     }
   }
 }
}



void input() { //Function for allowing user input and checking input against the generated array

 for (int x=0; x <= turn;)
 { //Statement controlled by turn count

   for(int y=0; y<4; y++)
   {
     
     buttonstate = digitalRead(button[y]);
   
     if (buttonstate == LOW && button[y] == 2)
     { //Checking for button push
       digitalWrite(ledpin[0], HIGH);
       speakerpin.play(NOTE_G3, 100);
       delay(200);
       digitalWrite(ledpin[0], LOW);
       inputArray[x] = 1;
       delay(50);
       Serial.print(" ");
       Serial.print(1);
       if (inputArray[x] != randomArray[x]) { //Checks value input by user and checks it against
         fail();                              //the value in the same spot on the generated array
       }                                      //The fail function is called if it does not match
       x++;
     }
      if (buttonstate == LOW && button[y] == 3)
     {
       digitalWrite(ledpin[1], HIGH);
       speakerpin.play(NOTE_A3, 100);
       delay(200);
       digitalWrite(ledpin[1], LOW);
       inputArray[x] = 2;
       delay(50);
       Serial.print(" ");
       Serial.print(2);
       if (inputArray[x] != randomArray[x]) {
         fail();
       }
       x++;
     }

     if (buttonstate == LOW && button[y] == 4)
     {
       digitalWrite(ledpin[2], HIGH);
       speakerpin.play(NOTE_B3, 100);
       delay(200);
       digitalWrite(ledpin[2], LOW);
       inputArray[x] = 3;
       delay(50);
       Serial.print(" ");
       Serial.print(3);
       if (inputArray[x] != randomArray[x]) {
         fail();
       }
       x++;
     }

     if (buttonstate == LOW && button[y] == 5)
     {
       digitalWrite(ledpin[3], HIGH);
       speakerpin.play(NOTE_C4, 100);
       delay(200);
       digitalWrite(ledpin[3], LOW);
       inputArray[x] = 4;
       delay(50);
       Serial.print(" ");
       Serial.print(4);
       if (inputArray[x] != randomArray[x])
       {
         fail();
       }
       x++;
     }
   }
 }
 delay(500);
 turn++; //Increments the turn count, also the last action before starting the output function over again
}

void fail() { //Function used if the player fails to match the sequence

 for (int y=0; y<=2; y++)
 { //Flashes lights for failure
   
   digitalWrite(ledpin[0], HIGH);
   digitalWrite(ledpin[1], HIGH);
   digitalWrite(ledpin[2], HIGH);
   digitalWrite(ledpin[3], HIGH);
   speakerpin.play(NOTE_G3, 300);
   delay(200);
   digitalWrite(ledpin[0], LOW);
   digitalWrite(ledpin[1], LOW);
   digitalWrite(ledpin[2], LOW);
   digitalWrite(ledpin[3], LOW);
   speakerpin.play(NOTE_C3, 300);
   delay(200);
 }
 delay(500);
 turn = -1; //Resets turn value so the game starts over without need for a reset button
}


Groove

Code: [Select]
digitalWrite(button[x], HIGH);  // buttons start in high possition

A better comment would be "// enable pull-ups"
Per Arduino ad Astra

Coding Badly

#2
Jan 22, 2010, 09:20 am Last Edit: Jan 22, 2010, 09:21 am by bcook Reason: 1

There's a 50:50 chance I disagree.   ;D  

It depends on the audience and the intent.  If the audience is his future self and the intent is to remind him that the logic is reversed, then it's a good comment.  (well, the comment would work for me)  If the audience is the world-at-large and the intent is to describe the purpose of the function call, then your comment is certainly better.  The best comment would be...

Code: [Select]
digitalWrite(button[x], HIGH);  // enable internal pullup; buttons start in high position; logic reversed

But who has time for all that typing!   ::)


@digimike: Thanks for posting about your project.  I love reading what other people do with Arduinos!

@Groove: Thanks for posting about comments.  It's good (at least for me) to discuss these things so we can get better at our craft.

digimike

Made a couple of amendments to the code. The OP has been updated with these changes since they are minor ones. First i was bothered that the original code had the void loop() at the end of the code with nothing in it just so it would compile. So i changed the void output() to void loop() to get rid of the extra line of code. I then added a tune to the start of the game. Upon competition of each turn this tune is played again.

Crazy Ideas

#4
Oct 25, 2010, 01:30 am Last Edit: Oct 25, 2010, 01:44 am by Crazy_Ideas Reason: 1
Hi I used digimike's code to make a Simon/Arduino Says game for a Halloween party next weekend.  I am going to try to attach the youtube video below. http://crazyideafactory.com/?p=1013
[media]
[media]http://www.youtube.com/watch?v=0V1xP_3rY3M[/media]
http://www.youtube.com/watch?v=0V1xP_3rY3M

Go Up