simon.pde

/*

This is a the classic "copy the sequence of coloured lights". Originally called Simon.

There are coloured lights, each with its own button. The computer picks a random colour, which the player then has to copy (by pressing that colour's button). The computer then picks another colour, and adds it to the original. Now the player has to copy both colours. This continues, with the sequence getting longer and longer until the player gets it wrong, at which point the game is over.

  • /

int COLOURS = 4;

int ledPins 4 = {6,7,8,9}; int buttonPins 4 = {2,3,4,5}; int speakerPin = 10; int speedPin = 0;

int NONE = -1; int colour = NONE; // The currently lit LED. 0 to 3, or NONE when no colour is lit.

int tones4 = {700,800,900,1000}; // Each colour has a different tone

/* "state" determines what is to happen next, and the following are the vaues that "state" can have. The numbers don't mean anything (as long as they are all different).

  • / int STATE_NONE = -1; int STATE_RESTART = 1; // Press any key to start a new game. int STATE_LISTEN = 2; // The program plays the sequence that the player will soon repeat. int STATE_REPEAT = 3; // The player is trying to repeat the sequence.

int state = STATE_RESTART;

const int MAX_SEQUENCE = 100; int sequence MAX_SEQUENCE ; // The list of random colours (0..3) in the sequence so far. int sequenceSize = 0; // The number of items in the sequence so far int repeatIndex = 0; // The number of colours the player has repeated.

int delayDuration = 500;

int awaitState = HIGH;

void setup() { Serial.begin( 9600 );

for ( int i = 0; i < COLOURS; i ) { pinMode( ledPins i , OUTPUT ); pinMode( buttonPins i , INPUT ); digitalWrite( ledPins i , LOW ); // All lights off at the beginning } pinMode( speakerPin, OUTPUT ); } void loop() { if ( state == STATE_RESTART ) { awaitRestart(); } else if ( state == STATE_LISTEN ) { computersTurn(); } else if ( state == STATE_REPEAT ) { playersTurn(); } } void awaitRestart() { colour ; if ( (colour >= COLOURS) || (colour < 0) ) { colour = 0; awaitState = (awaitState == HIGH) ? LOW : HIGH; }

Serial.print( awaitState ); Serial.println( colour ); digitalWrite( ledPins colour , awaitState );

delayDuration = analogRead( speedPin );

delay( delayDuration );

for ( int i = 0; i < COLOURS; i ) { if ( ! digitalRead( buttonPins i ) ) { randomSeed( millis() ); changeState( STATE_LISTEN ); break; } } } void changeState( int newState ) { colour = NONE; repeatIndex = 0; state = newState; for ( int i = 0; i < COLOURS; i ) { digitalWrite( ledPins i , LOW ); }

}

void computersTurn() {

if ( sequenceSize >= MAX_SEQUENCE ) { // The player has remembered the maximum size sequence - they win! } else { // Add a ramdon colour to the sequence, and then play it back.

int newColour = random( 4 ); sequence sequenceSize = newColour; sequenceSize ; playSequence( delayDuration ); changeState( STATE_REPEAT ); } } void playSequence( int duration ) { delay( duration * 2 ); for ( int i = 0; i < sequenceSize; i ) { int colour = sequence i ; digitalWrite( ledPins colour , HIGH ); // Turn the LED ON playTone( tones colour , duration ); // Play the note digitalWrite( ledPins colour , LOW ); // Turn the LED OFF delay( duration / 4 ); }

}

void playersTurn() {

if ( colour == NONE ) {

for ( int i = 0; i < COLOURS; i ) { boolean value = digitalRead( buttonPins i ); // Serial.print( "button down? : " ); Serial.print( i ); Serial.print( " = " ); Serial.println( value ); if ( ! value ) { colour = i; digitalWrite( ledPins colour , HIGH ); // Turn the LED ON break; } } } else { boolean value = digitalRead( buttonPins colour ); if ( ! value ) { // Button is still pressed playTone( tones colour , 10 ); } else { // Button has been released digitalWrite( ledPins colour , LOW ); // Turn the LED OFF checkColour(); } } } /* Checks that the correct colour has been chosen. If it isn't then the game is over, and the buzzer will sound. Press any key to start a new game. */ boolean checkColour() { Serial.print( repeatIndex ); Serial.print( " = " ); Serial.print( sequence repeatIndex ); Serial.print( " vs " );Serial.println( colour ); int requiredColour = sequence repeatIndex ; if ( requiredColour == colour ) { // Yes they have chosen the correct color repeatIndex ; colour = NONE;

if ( repeatIndex == sequenceSize ) { // They have repeated the whole index, so now its the computers turn changeState( STATE_LISTEN ); }

} else { // No that's wrong! playTone( 1200, 600 ); // Error sound playTone( 1400, 700 ); // Error sound playTone( 1800, 1000 ); // Error sound changeState( STATE_RESTART ); } }

/* Plays a note. The pitch is different for each colour. See the array "tones".z

  • / void playTone( int tone, int duration ) { for ( long i = 0; i < duration * 1000L; i += tone * 2 ) { digitalWrite( speakerPin, HIGH ); delayMicroseconds( tone ); digitalWrite( speakerPin, LOW ); delayMicroseconds( tone ); } }