We created a Whac-A-Mole game with solenoid moles and a two-digit score counter.

At random intervals, a random solenoid piston will extend. If the extended piston is hit within the time limit, it will fall and depress the button placed under it. The score then gets incremented.

Here’s the circuit diagram to show how the solenoid extension and feedback works:
(Modified from circuit images found in course webpage)

And here’s a glimpse of the actual circuit:

The scoring mechanism uses a Geneva drive to turn the ten’s digit wheel in discrete steps, one step per full rotation of the one’s digit:

Finally, this is a code that drives the whole game:

//====================================================================================
//Digital Port Definitions
#define HIT_TRIGGER 9
#define MOTOR_DIR 10
#define MOTOR_STEP 11
enum mole_t {MOLE_0, MOLE_1, MOLE_2, MOLE_3, MOLE_4, MOLE_5, MOLE_6, MOLE_7, MOLE_8};

//====================================================================================
//State Definitions
enum state_t {GAME_IDLE, NEW_MOLE, WAIT_HIT, WAS_HIT, NOT_HIT, GAME_OVER} game_state;
int mole;
int score;
int timer;

//====================================================================================
void setup() {
  //set up the moles
  pinMode(MOLE_0, OUTPUT); digitalWrite(MOLE_0, LOW);
  pinMode(MOLE_1, OUTPUT); digitalWrite(MOLE_1, LOW);
  pinMode(MOLE_2, OUTPUT); digitalWrite(MOLE_2, LOW);
  pinMode(MOLE_3, OUTPUT); digitalWrite(MOLE_3, LOW);
  pinMode(MOLE_4, OUTPUT); digitalWrite(MOLE_4, LOW);
  pinMode(MOLE_5, OUTPUT); digitalWrite(MOLE_5, LOW);
  pinMode(MOLE_6, OUTPUT); digitalWrite(MOLE_6, LOW);
  pinMode(MOLE_7, OUTPUT); digitalWrite(MOLE_7, LOW);
  pinMode(MOLE_8, OUTPUT); digitalWrite(MOLE_8, LOW);
  
  //set up hit feedback
  pinMode(HIT_TRIGGER, INPUT);

  //set up score-keeping motor
  pinMode(MOTOR_DIR, OUTPUT); 
  pinMode(MOTOR_STEP, OUTPUT);

  //initialize gamestate
  game_state = GAME_IDLE;
  score = 0;
}

void loop() {
  timer++;
  switch(game_state) {
    case GAME_IDLE:
      game_state = NEW_MOLE;
      break;
      
    case NEW_MOLE:
      new_mole();
      timer = 0;
      game_state = WAIT_HIT;
      break;
      
    case WAIT_HIT:
      if (!digitalRead(HIT_TRIGGER)) {
        digitalWrite(mole, LOW); 
        game_state = WAS_HIT;
      }
      else if (timer >= random(1000,3000)) {
        digitalWrite(mole, LOW);
        timer = 0; 
        game_state = NOT_HIT;
      }
      break;
      
    case WAS_HIT:
      score++;
      game_state = NEW_MOLE;
      digitalWrite(MOTOR_DIR, HIGH);
      for(int i = 0; i < 80; i++) {
        digitalWrite(MOTOR_STEP, HIGH); delay(1);
        digitalWrite(MOTOR_STEP, LOW);  delay(1);
      }
      break;

    case NOT_HIT:
      game_state = NEW_MOLE;
      break;
      
    case GAME_OVER:
      break;
      
  }
  delay(1);
}

void new_mole(){
  delay(random(1000));
  mole = random(9);
  digitalWrite(mole, HIGH); 
  delay(10);
}