header
More Functions

Our game currently works. So let's clean up our code a bit and learn some more about functions.

Look at this section of our code:

   if (digitalRead(inPin[0]) == HIGH) {
     digitalWrite(ledPin[0], HIGH);
     delay(250);
     digitalWrite(ledPin[0], LOW);
     delay(250);
     if (pattern[i] == 1) {
       break;
     }
   }
   if (digitalRead(inPin[1]) == HIGH) {
     digitalWrite(ledPin[1], HIGH);
     delay(250);
     digitalWrite(ledPin[1], LOW);
     delay(250);
     if (pattern[i] == 0) {
       break;
     }
   }

We are running the same code twice, but just changing the variable. Whenever you see this, try to move it to a function. In this case, let's move this code to a function called check_input. We'll also have to send the function the different variables to use in the function. So let's try something like this.

// Use arrays to hold our pin numbers and the pattern.
// This will let us use a loop to go through the values.
int speaker = 9;
int ledPin[] = { 67 };
int inPin[] = { 24 };
int pattern[5];  // This array will hold the pattern we generate.

// Need some notes
int C = 523;
int F = 698;

void setup() {
  pinMode(speakerOUTPUT);
  pinMode(ledPin[0], OUTPUT);
  pinMode(ledPin[1], OUTPUT);
  pinMode(inPin[0], INPUT);
  pinMode(inPin[1], INPUT);
  randomSeed(analogRead(0));  // Ensures that pattern is different at every reset
}

void loop() {
  play_start_tones();
  generate_pattern();
  
  // Go through each note in the pattern and see if the player matches it
  for (int i = 0i < 5i++) {
    // Until the player pushes a button, do nothing
   while ((digitalRead(inPin[0])) == LOW && (digitalRead(inPin[1]) == LOW)) { }
   check_input(0i);
   check_input(1i);

   }
}

void check_input(int pinint pat) {
  if(digitalRead(inPin[pin]) == HIGH) {
    digitalWrite(ledPin[pin], HIGH);
    delay(250);
    digitalWrite(ledPin[pin], LOW);
    delay(250);
    if (pattern[pat] == pin) {
      // correct answer, do nothing
    } else {
     break
    }
  }
}

void play_start_tones() {
  for (int i = 0i < 3i++) {
    tone(speakerC);
    delay(350);
    noTone(speaker);
    delay(350);
  }
  tone(speakerF);
  delay(350);
  noTone(speaker);
}

void generate_pattern() {
  // Generate random pattern
  for (int i = 0i < 5i++) {
    int number = random(0,2);
    pattern[i] = number;
    digitalWrite(ledPin[number], HIGH);
    delay(500);
    digitalWrite(ledPin[number], LOW);
    delay(500);
  }
}

Oops. That didn't work. When trying to upload, we get this error:

game.cpp: In function 'void check_input(int, int)':
game:42: error: break statement not within loop or switch

The good news is that the error message is telling us what's wrong. The break command that we moved to our function is no longer in the loop that we're trying to break out of. So, we need to change our function a bit, to get this to work. We're going to do that by making our function send a return value. Try changing the code to this.

// Use arrays to hold our pin numbers and the pattern.
// This will let us use a loop to go through the values.
int speaker = 9;
int ledPin[] = { 67 };
int inPin[] = { 24 };
int pattern[5];  // This array will hold the pattern we generate.

// Need some notes
int C = 523;
int F = 698;

void setup() {
  pinMode(speakerOUTPUT);
  pinMode(ledPin[0], OUTPUT);
  pinMode(ledPin[1], OUTPUT);
  pinMode(inPin[0], INPUT);
  pinMode(inPin[1], INPUT);
  randomSeed(analogRead(0));  // Ensures that pattern is different at every reset
}

void loop() {
  play_start_tones();
  generate_pattern();
  
  // Go through each note in the pattern and see if the player matches it
  for (int i = 0i < 5i++) {
    // Until the player pushes a button, do nothing
   while ((digitalRead(inPin[0])) == LOW && (digitalRead(inPin[1]) == LOW)) { }
   if (check_input(0i) == 1) {
     break
   }
   if (check_input(1i) == 1) {
     break;
   }
  }
}

int check_input(int pinint pat) {
  if(digitalRead(inPin[pin]) == HIGH) {
    digitalWrite(ledPin[pin], HIGH);
    delay(250);
    digitalWrite(ledPin[pin], LOW);
    delay(250);
    if (pattern[pat] == pin) {
      return (0); // For correct answer return 0
    } else {
      return (1); // For incorrect answer return 1
    }
  }
}

void play_start_tones() {
  for (int i = 0i < 3i++) {
    tone(speakerC);
    delay(350);
    noTone(speaker);
    delay(350);
  }
  tone(speakerF);
  delay(350);
  noTone(speaker);
}

void generate_pattern() {
  // Generate random pattern
  for (int i = 0i < 5i++) {
    int number = random(0,2);
    pattern[i] = number;
    digitalWrite(ledPin[number], HIGH);
    delay(500);
    digitalWrite(ledPin[number], LOW);
    delay(500);
  }
}

Note that we also had to change the void in front of check_input to int. This is because there is a value that is being returned from this function and the int gives us a place to store it. Now you know why we have void in front of all our other functions. They don't return any value so we don't need to save a place to store a value.

Our game works, but what if we now wanted to play one tone when the user gets all the answers correct and another when they make a mistake. That's next.

Adding winning and losing tones

Game Home