In this project, we continue the development of our Simon Says pattern-matching game by adding button input.

In our last project, we created a random sequence of LED flashes. We included that code in a loop that will continue to add another flash to the end of the sequence and replay the sequence. This is exactly how our game will work, except that after playing a sequence, the player will have to repeat the sequence using the buttons on the breadboard. If they do it correctly, we add a new LED flash to the sequence; if they do it incorrectly, the game is over.

In this project, we'll add the buttons as input, and add the code that will verify the button sequence that the player enters.

The hardware setup for this project should be the same setup that was completed for the project. Here's a reminder:

## Add Initialization Code.

The first thing we're going to need to do is initialize the buttons. We'll import the function we need and create the button list just like we did in :

from rstem.button import Button buttons = [Button(14), Button(15), Button(23), Button(17)]

## Check Button Sequence Entered by Player.

Next, we need to add code after we play the sequence to check for whether the user has entered the correct sequence back. There are several parts to this, and they will all be captured in a `for` loop that runs through the sequence the player is repeating. Each time through the `for` loop, we'll need to accomplish the following things:

1. First, we test to see if the button pressed was the next button in the sequence.

2. If an incorrect button was pressed, we set a variable called `failed` to `True`. This will be our indication to the `while` loop that the game is over and that we should drop through the loop on our next pass. This will also require us to change our test in the `while` loop that we already created (we'll do that in Step #3). And we'll need to stop checking for additional button presses and drop through the loop.

3. Lastly, if the player has entered a correct button in the sequence, we need to flash that LED.

Here is what the beginning of the `for` loop would look like:

# Wait for user to repeat for i in play_order: button_pressed = Button.wait_many(buttons, timeout=3)
wait_many() Function

As discussed in the project, the `wait_many()` function takes a list of buttons as a parameter, will wait for any of them to be pressed and will then return the index into the button list of the button that was pressed.

Next, we check to see if player pressed the WRONG button:

if button_pressed != i: failed = True break

If the button entered by the player was incorrect, we set a variable called `failed` to `True`, and then we `break` — the `break` command will immediately exit the `for` loop.

If the button entered by the player was correct, we need to light the LED before moving on to check the next button entered. Here is what that code should look like:

# Light and play while button is pressed. lights[button_pressed].on() buttons[button_pressed].wait(press=False) time.sleep(0.2) lights[button_pressed].off()

In the code above, we turn the LED on, wait until the button is released, and turn it back off. But there's an extra line in there as well — we sleep for a very short period. This extends the time the LED is on to give a better appearance when a player presses and releases a button very quickly.

## Update the `while` Loop.

Finally, we have to update our `while` loop, as we want it to drop through if we determine that the user made a mistake and the game is over. Remember, we set a variable called `failed` to `True` when the user made a mistake, so we can simply test to see whether `failed` is `True` in our `while` loop.

To update the `while` loop, we need to first initialize our failed variable when we start the program, then we can update our `while` loop as follows:

failed = False ... while not failed: ...

## Put It All Together.

Here is what the code for this project should look like at this point (with new changes highlighted with arrows) — when you run it, you will see a single LED flash, and you can press the button associated with that LED; then the pattern will repeat, adding a new LED light and you can enter the 2-light sequence; the sequence will continue to add a new LED flash for as long as you correctly enter the sequence:

# ################################## # Import Modules and Initialize Game # ################################## *from rstem.button import Button from rstem.gpio import Output from random import randrange import time *buttons = [Button(14), Button(15), Button(23), Button(17)] lights = [Output(4), Output(18), Output(24), Output(27)] for light in lights: light.off() play_order = [] *failed = False # ################################## # Main while: loop for game # ################################## *while not failed: # Add another random LED to sequence play_order.append(randrange(4)) # Play LED sequence for i in play_order: lights[i].on() time.sleep(0.4) lights[i].off() time.sleep(0.2) * # ############################# * # for: loop to get player input * # ############################# * * for i in play_order: * * # Get the user's button press * button_pressed = Button.wait_many(buttons, timeout=3) * * # If user enters incorrect button, end game * if button_pressed != i: * failed = True * break * * # If user enters correct button, flash LED and play tone * lights[button_pressed].on() * buttons[button_pressed].wait(press=False) * time.sleep(0.2) * lights[button_pressed].off() * * if not failed: * time.sleep(1.0)

1. The user is given 3 seconds of time to press each button in the sequence. Can you change this to 2 seconds?

2. Can you make the game even harder by making the time the user has to press a button decrease by 5% each time a new LED is added to the `play_order`?

3. If the user hits the wrong button, give them another chance: flash the LED (the wrong one) with 3 quick flashes. Then give them another 3 seconds to try again to hit the correct button.