0

I'm making a game where there are three LEDs and three buttons: 1 LED for 1 button. One has to press the button that has its LED lit. If it is correct, another (random) LED will light up and the game continues. However, if one presses one that isn't lit, one has points taken from one's score.

Example image: http://i.imgur.com/xSUrVRV.png

I'm having trouble figuring out how to find out when the wrong one is pressed. With the code below it will print "Ouch" whenever the led switches numbers.

Code that switches LED:

led = random(1, 4);
switch(led) {
  case 1:
    ledLeftState = HIGH;
    break;
  case 2:
    ledMiddleState = HIGH;
    break;
  case 3:
    ledRightState = HIGH;
    break;
}

Code that checks if the wrong button is pressed:

 if(digitalRead(BUTTON_LEFT) == LOW && led != 1 || digitalRead(BUTTON_MIDDLE) == LOW && led != 2 || digitalRead(BUTTON_RIGHT) == LOW  && led != 3) {
    static unsigned long lastTime = 0;
    if(millis() - lastTime > 400) {
      Serial.println("Ouch, minus ten miliseconds!");
      hurt += 10;
      lastTime = millis();
    }
  } 

Hopefully you can figure this scenario out in your heads, otherwise simply tell me that you'd like code instead of downvoting.

Thanks for your time!

1
2

The line

if(millis() - lastTime > 400)

is supposed to test that the button press does not come right after the LED switches. This means the line

lastTime = millis();

should be right when you change the displayed LED.

1

First: Your buttons are not wired up properly according to the diagram. They seem to be only connected to 5V.

On Arduino buttons can be wired both active-high and active-low. Active-high means then when the button is pressed you get a HIGH signal, and LOW otherwise. Obviously active-low is the opposite. The code below assumes active-high.

You might want to go do some reading on "button de-bouncing". I've included some rudimentary code to help, but it's not perfect. A 0.1 micro-farad capacitor across the button terminals will help with this too.

So ... onto the code.

It's really the game-loop that needs some work. I'll assume your random LED-lighting code is in a function called newRandomLED(), and variables ledLeftState, hurt, etc. are globals.

The new_pattern_time variable should probably also be set in newRandomLED() since they always are called together. But I'm trying to help, not re-write ;)

const int debounce_time  =  30; // milliseconds
const int max_push_time  = 400; // milliseconds - How long is a turn

// Draw the first LED pattern
newRandomLED();

// the time the latest LED pattern was re-drawn
unsigned long new_pattern_time = millis();  

// Reset the score
hurt = 0;

while (true) // TODO: insert some game-length decision 
{
    // Has the time to press a button expired?
    if (millis() - new_pattern_time > max_push_time)
    {
        // TODO: sound the buzzer for *fail*

        // Time is up, penalise the user
        hurt += 10;

        // Time for a new pattern
        newRandomLED();
        new_pattern_time = millis();
    }

    // Perform the initial-read of the buttons
    int butt_left  = digitalRead(BUTTON_LEFT);
    int butt_mid   = digitalRead(BUTTON_MIDDLE);
    int butt_right = digitalRead(BUTTON_RIGHT);

    // de-bounce the button presses
    delay(debounce_time); 
    if (butt_left == HIGH)
        butt_left = digitalRead(BUTTON_LEFT);
    if (butt_mid  == HIGH)
        butt_mid = digitalRead(BUTTON_MIDDLE);
    if (butt_right == HIGH)
        butt_right = digitalRead(BUTTON_RIGHT);

    // So now we have the state of the three buttons, de-bounced too.
    // Was there any input from the user?
    if (butt_left == HIGH || butt_mid == HIGH || butt_right == HIGH)
    {
        // So one (or more) buttons have been pressed
        // Check that for each LED that is on, that the button is pressed too
        boolean success = true;
        if (ledLeftState != butt_left)
            success = false;
        if (ledMiddleState != butt_middle)
            success = false;
        if (ledRightState != butt_right)
            success = false;

        // Was the user correct?
        if (success == true)
        {
            // TODO: sound the buzzer for *WIN*
            hurt -= 10;

            // And we need to show the next pattern
            newRandomLED();
            new_pattern_time = millis();
        }
    }
}

So essentially you're looping around checking to see if the player pressed anything. Most of the time, there will be no input from the user, and this loop will spin thousands of times without any input.

On each loop the code checks to see if the time is up, or some buttons were pushed. In both cases, it's time for a new pattern. A side effect of this code is that it allows for simultaneous button pushes, so at higher difficulty levels you could illuminate more than 1 LED.

Note: this code is a quick response to the question. It may not be 100% correct, nor have flawless C-textbook syntax.

0

Off the top of my head and without a compiler would something like this work?

int BasePin = 3;
int BaseButton = 7;

int led = random (1, 4); // Are you sure its 4??
digitalWrite(BasePin+led, HIGH);

if (digitalRead(BaseButton+led))
{
  // Success
}
else if (millis() - lastTime > 400))
{
  // Out of time
}
else if (  digitalRead(BaseButton+1)
        || digitalRead(BaseButton+2)
        || digitalRead(BaseButton+3)
{
  // Wrong button 
  // (The right one will have been handled by the earlier clause)
}

OK the last clause is a bit of a hack, but it should give you a starting point to tidy up.

You are probably going to get issues unless you debounce the switches.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.