I am creating a three-person reaction time game but I would like to be able to read all three buttons' proximity to the start time - currently only the winner is displayed on the serial read.
Here is my code:
int ledPin = 12;
int buttonPin1 = 7;
int buttonPin2 = 6;
int buttonPin3 = 5;
void setup() {
Serial.begin(9600);
Serial.println("Setup start");
pinMode(ledPin, OUTPUT);
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
randomSeed(analogRead(A0));
Serial.println("Setup complete");
}
void loop() {
Serial.println("Game start");
digitalWrite(ledPin, HIGH);
delay(2000);
delay(random(1000, 3000));
digitalWrite(ledPin, LOW);
Serial.println("LED off, waiting for button press");
unsigned long start_time = millis();
int winner = 0;
while (winner == 0) {
winner = check_buttons();
}
unsigned long end_time = millis();
unsigned long total_time = end_time - start_time;
Serial.print("Player ");
Serial.print(winner);
Serial.println(" wins!");
Serial.print("It took ");
Serial.print(total_time);
Serial.println(" ms to press the button.");
delay(5000);
}
int check_buttons() {
int player1 = digitalRead(buttonPin1);
int player2 = digitalRead(buttonPin2);
int player3 = digitalRead(buttonPin3);
if (player1 == LOW) {
return 1;
} else if (player2 == LOW) {
return 2;
} else if (player3 == LOW) {
return 3;
} else {
return 0;
}
}
1 Answer 1
You will need an end_time
variable for each of the players, either as a distinct variable for each player, or use an array. Define as a global:
unsigned long end_time_player1;
unsigned long end_time_player2;
unsigned long end_time_player3;
or
unsigned long end_time_player[3];
Then in check_buttons()
you will need to record the respective end_time
, like so
if (player1 == LOW) {
end_time_player[0] = millis();
//end_time_player1 = millis();
return 1;
} else if (player2 == LOW) {
end_time_player[1] = millis();
//end_time_player2 = millis();
return 2;
}else if (player3 == LOW) {
end_time_player[2] = millis();
//end_time_player3 = millis();
return 3;
} else {
return 0;
}
Obviously, if using an array, then the index of the array is one less than the player number.
An array is probably more elegant and expandable, so for four players:
const int kNumPlayers=4
unsigned long end_time_player[kNumPlayers];
If using arrays (for both the times and the buttons (as well as the players)), you could also turn the series of if
statements into a for
loop using kNumPlayers
:
int buttonPin[kNumPlayers] = {7, 6, 5};
...
int check_buttons() {
int player[kNumPlayers];
for (n=0; n < kNumPLayers; n++) {
player[0] = digitalRead(buttonPin[n]);
if (player[0] == LOW) {
end_time_player[n] = millis();
return n+1;
} else {
return 0;
}
}
}
or, more simply, just dispense with the player
local variable altogether
int buttonPin[kNumPlayers] = {7, 6, 5};
...
int check_buttons() {
for (n=0; n < kNumPlayers; n++) {
if (digitalRead(buttonPin[n]) == LOW) {
end_time_player[n] = millis();
return n+1;
} else {
return 0;
}
}
}
Then you will need to change the code in loop()
to display the time for each user. I'll let you work that bit out yourself.
-
Yes, but what if the third player doesn't press the button? Or the second?2024年06月23日 07:02:41 +00:00Commented Jun 23, 2024 at 7:02
-
Then the display in
loop()
won''t show a value for that player, or display "n/a". Thewhile
loop would no longer have to wait for just one winner, but rather wait for a time out (of say, one second, maybe two). If a player hasn't hit a button within that time frame, then it can be safely assumed that they have died of boredom..! :-) Yes, I must admit that there are some necessary logic changes required inloop()
that I had overlooked... although, in fairness, I did leave that for the OP to figure out, as the question seemed to focus on the reading and not the displaying.Greenonline– Greenonline2024年06月23日 10:37:52 +00:00Commented Jun 23, 2024 at 10:37
while (second == 0) ...
?