A little Arduino game to test how fast you are

Build a small board with two buttons and challenge other buddies to see who is faster (and learn some Arduino)

This time I would like to present you a small game which goal is to see whose player has the fastest reaction time. It consist of a LED which lights up randomly allowing players to push a button in order to see who was quicker.

What do I need

  • 3 LEDs of your choice (preferebly different colors) + 3 × 330 Ω resistors (orange, orange, brown)
  • Buzzer + 330 Ω resistor (orange, orange, brown)
  • 2 push buttons + 2 × 1 kΩ resistors (brown, black, red)

Schematic

Imagem do esquema de ligação do jogo

Assembly

  1. Put the LEDs as shown on the schematic. For each one, connect a 330 Ω resistor by joining the LED ground to the breadboard ground.

    1. Place the push buttons. Connect one of the push button leds with the +5V power source (white wire on the schematic). On the oposite leg, connect a 1 kΩ resistor. Repeat this for the other button.
  2. Connect the buzzer and put a 330 Ω resistor, by joining the buzzer ground with the breadboard ground.

  3. Connect the first LED (player A) to the Arduino port 2.

  4. Connect the second LED (controller LED) to the Arduino port 3.

  5. Connect the last LED (player B) to the Arduino port 4.

  6. Connect the buzzer to the Arduino port 6.

  7. Connect the buttons for player A and B to Arduino ports 8 and 9, respectively

  8. Connect the breaboard ground to the Arduino GND (ground/0V).

  9. Do the same for the 5V power source.

Done the assembly, upload the code:

// Configuration
byte const PLRA_LED = 2;  // player A LED
byte const PLRA_BTN = 8;  // player A button
byte const PLRB_LED = 4;  // player B LED
byte const PLRB_BTN = 9;  // player B button
byte const BLINKER = 3;  // controller LED
byte const BELL = 6;  // buzzer
int const MIN_TIME = 3000;  // minimum time
int const MAX_TIME = 7000;  // maximum time
int const BELL_CHEAT = 600;  // sound for players cheating

// controlling variables for the game
long last_start = 0;
long score_a = 0;
long score_b = 0;
int multiple = 1;
byte touch = 0;
byte block_A = 0;
byte block_B = 0;

// setup Arduino ports
void setup()
{
  pinMode(PLRA_LED, OUTPUT);
  pinMode(PLRB_LED, OUTPUT);
  pinMode(PLRA_BTN, INPUT);
  pinMode(PLRB_BTN, INPUT);
  pinMode(BLINKER, OUTPUT);
  pinMode(BELL, OUTPUT);
  intro();
  last_start = nextBlink();
}

// game loop
void loop()
{
  long ms = millis();

  // game was started, accept player button presses
  if( ms >= last_start && touch == 0 )
  {
    digitalWrite(BLINKER, HIGH);

    byte read_A = digitalRead(PLRA_BTN);
    byte read_B = digitalRead(PLRB_BTN);

    // player A read
    if( read_A == 1 && block_A == 0 )
    {
      score_a += (1 * multiple);
      digitalWrite(PLRA_LED, HIGH);
      touch = 1;
    }

    // player B read
    if( read_B == 1 && block_B == 0)
    {
      score_b += (1 * multiple);
      digitalWrite(PLRB_LED, HIGH);
      touch = 1;
    }
  }
  else if( ms <= last_start )
  {
    // anti-cheating system
    byte read_A = digitalRead(PLRA_BTN);
    byte read_B = digitalRead(PLRB_BTN);

    if( read_A == 1 )
    {
      digitalWrite(PLRA_LED, HIGH);
      tone(BELL, BELL_CHEAT);
      delay(700);
      noTone(BELL);
      digitalWrite(PLRA_LED, LOW);
      block_A = 1;
    }
    else
    {
      block_A = 0;
    }

    if( read_B == 1 )
    {
      digitalWrite(PLRB_LED, HIGH);
      tone(BELL, BELL_CHEAT);
      delay(700);
      noTone(BELL);
      digitalWrite(PLRB_LED, LOW);
      block_B = 1;
    }
    else
    {
      block_B = 0;
    }
  }

  // generate a new game
  if( ms >= last_start && touch == 1 )
  {
    sound();
    delay(1000);
    digitalWrite(PLRA_LED, LOW);
    digitalWrite(PLRB_LED, LOW);
    digitalWrite(BLINKER, LOW);
    last_start = nextBlink();
    touch = 0;
  }
}

// control next blinking execution
long nextBlink()
{
  return millis() + random(MIN_TIME, MAX_TIME);
}

// buzzer sound routine
void sound()
{
  tone(BELL, 1600);
  delay(100);
  noTone(BELL);
  tone(BELL, 2000);
  delay(100);
  noTone(BELL);
  tone(BELL, 2400);
  delay(500);
  noTone(BELL);
}

// buzzer sound routine reversed
void r_sound()
{
  tone(BELL, 2400);
  delay(100);
  noTone(BELL);
  tone(BELL, 2000);
  delay(100);
  noTone(BELL);
  tone(BELL, 1600);
  delay(500);
  noTone(BELL);
}

// Light and sound animation
// the LEDS blink from left to right and back to left (see seq array)
// a sound is generated at the start and then a reverse sound
void intro()
{
  sound();

  int seq[] = { PLRA_LED, BLINKER, PLRB_LED, BLINKER, PLRA_LED };
  int sz = 5;

  for( byte i = 0; i < sz; i++ )
  {
    digitalWrite(seq[i], HIGH);
    delay(200);
    digitalWrite(seq[i], LOW);
  }

  r_sound();
}

Remarks

This game implements a small anti-cheat system. It consists of checking if a player is pushing the button before controlling LED is light up. When that happens the buzzer generates an error tone, and player's LED who cheated lights up. Variables block_A and block_B are responsible for controlling if a player is cheating or not. This will block the player while he/she has the button pressed.

Another change is the fact we're using the long datatype instead of int. An int can hold 2 bytes of data (values ranging from -32768 to 32767), which is enough to reach 33 seconds of game. From that point onwards, it would happen an overflow and the value would now assume a negative value. The LED would never light up again because the value returned my millis() function would always be greater that 32767. That's why we're using long datatype to hold the game duration. With this datatype we can store up to 2147483647 milliseconds (something like 2 billion), which is almost 23 days of gaming. I believe you will be upset of this game by that time 🙂

Download

Code, Fritizing schematic and some images