Reaction Time Game, How To Make It So If You Press Early It Resets

I have a simple reaction time game on a protoboard where it does a countdown on a display that goes down somewhat randomly, then when it reaches 0 you have to press the button and an LED will light up relating to how well you did. That all works fine but Im wondering how to make it so you cant just hold down the button/spam it to get the best reaction time possible. I also want it to check during the delays as thats basically all of the countdown. This is my code.

int good=2;
int ok=3;
int bad=4;
int button=6;
int b=12;
int c=11;
int d=9;
int a=8;
unsigned long changeTime;

void setup()
{
  Serial.begin(9600);
  pinMode(good,OUTPUT);
  pinMode(ok,OUTPUT);
  pinMode(bad,OUTPUT);
  pinMode(button,INPUT);
  pinMode(a,OUTPUT);
  pinMode(b,OUTPUT);
  pinMode(c,OUTPUT);
  pinMode(d,OUTPUT);
  digitalWrite(a,HIGH);
  digitalWrite(d,HIGH);
  Serial.begin(9600);
}

void loop()
{
  delay(1000);
  digitalWrite(good,LOW);
  digitalWrite(ok,LOW);
  digitalWrite(bad,LOW);
  
  delay(random(250, 1000));
  
  digitalWrite(a,LOW);
  
  delay(random(250, 1000));
  
  digitalWrite(a,HIGH);
  digitalWrite(d,LOW);
  digitalWrite(b,HIGH);
  digitalWrite(c,HIGH);

  delay(random(250, 1000));

  digitalWrite(a,LOW);

  delay(random(250, 1000));

  digitalWrite(a,HIGH);
  digitalWrite(b,LOW);

  delay(random(250, 1000));

  digitalWrite(a,LOW);

  delay(random(250, 1000));

  digitalWrite(a,HIGH);
  digitalWrite(b,HIGH);
  digitalWrite(c,LOW);

  delay(random(250, 1000));

  digitalWrite(a,LOW);

  delay(random(250, 1000));

  digitalWrite(b,LOW);
  digitalWrite(a,HIGH);

  delay(random(250, 1000));

  digitalWrite(a,LOW);
  digitalWrite(b,LOW);
  digitalWrite(c,LOW);
  digitalWrite(d,LOW); 

  changeTime=millis();
  while(true){
    int state=digitalRead(button);
   
    Serial.println(state);
    while(state==HIGH){
      
      if((millis()-changeTime)<=100){
        digitalWrite(good,HIGH);
        digitalWrite(a,HIGH);
        digitalWrite(d,HIGH);
        state=LOW;
        return;
      }
      else if((millis()-changeTime)<=300 && (millis()-changeTime)>100){
        digitalWrite(ok,HIGH);
        digitalWrite(a,HIGH);
        digitalWrite(d,HIGH);
        state=LOW;
        return;
      }
      else if((millis()-changeTime)>400){
        digitalWrite(bad,HIGH);
        digitalWrite(a,HIGH);
        digitalWrite(d,HIGH);
        state=LOW;
        return;
      }

    }
  }
}

You are already using millis; so why not use it for ALL your timing, instead of "delay()"?

3 Likes

So you want to abort early if the button has been pressed before the light turns on?

Add a test of the button in here:

  delay(random(250, 1000));
  
  if(digitalRead(button) == LOW ) return;  // <<<<<<<<<<<<<<

  digitalWrite(a,LOW);
  digitalWrite(b,LOW);
  digitalWrite(c,LOW);
  digitalWrite(d,LOW); 

  changeTime=millis();
  while(true){
    int state=digitalRead(button);

If you really want to do things during your delay()s, it would be better to redesign it without using delays(). Or you could write
your own button-checking delay loops.

2 Likes

You have two Serial.begin() which let the sketch compile and run, but will stop Serial Monitor output. Remove one of them to get the button state in the Serial Monitor.

Also, after you set changeTime to millis()... you compared an even larger millis() to changeTime, so the "slow" LED would alway illuminate...

      if ((millis() - changeTime) <= 100) {
.
.
      else if ((millis() - changeTime) <= 300 && (millis() - changeTime) > 100) {
.
.
      else if ((millis() - changeTime) > 400) {

The code in void loop() could be un-delayed with a state machine in a timer in a function.

The timer runs when the wait time variable is > 0. It returns from the function until the wait is over then it sets wait = 0. When a delay is needed, wait is set and the state machine won't run till wait == 0.

The state machine breaks up the steps in that void loop. The state variable lets the code exit and come back to run the same or another case in the code to finish or advance. When loop() runs, the function runs a step at a time till the whole process is finished.

The conversion is pretty cut&dry. You can know a button is touched within a few milliseconds with buttons.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.