Simon says

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).

/*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
}
digitalWrite(button[x], HIGH);  // buttons start in high possition

A better comment would be "// enable pull-ups"

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...

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

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

@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.

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.

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. Arduino Says, Game Like Simon Says : Crazy Idea Factory