#include <LiquidCrystal.h> // include the LiquidCrystal library
const int numLights = 9; // (User) number of lights in the circle
int lightPins[numLights] = {}; // (Logic) pins for each light
int ledFirstPin = 13; // (User) first LED pin
const int ledAssignI = -1; // (User) LED pin interval (example LEDs in every other pin would be = 2)
const int buttonPin = 4; // (User) pin for button input
const int greenLED = 4; // (User) what number in numLights is the green LED
int currentLight = 0; // (Logic) current position of the lit light
bool buttonReleased = true; // (Logic) track button release
int numPoints = 0; // (Logic) number of times the player has won
int numLives = 3; // (User) number of lives player starts with
int dsiplayContrast = 1; // (User) contrast for LCD
int ledUpdateSpeed = 3; // (User) starting speed of how offten the LED gets updated (x 100 millaseconds)
int ledUpdate = 0; // (Logic) used for changing the timeing of the leds
int gameStatus = 1; // (Logic) status of the game (1 = running, 0 = Game Over)
int gameResetTimer = 0; // (Logic) used to reset the game after Game Over
// create an instance of the LiquidCrystal library to control the display
LiquidCrystal lcd(52, 50, 48, 46, 44, 42);
void setup() {
// loop to set light pins
for (int i = 0; i < numLights; i++) {
lightPins[i] = ledFirstPin;
ledFirstPin += ledAssignI;
}
// set each light pin as an output
for (int i = 0; i < numLights; i++) {
pinMode(lightPins[i], OUTPUT);
}
// output for LCD display contrast
pinMode(40, OUTPUT);
digitalWrite(40, dsiplayContrast);
// set button pin as an input
pinMode(buttonPin, INPUT);
// initialize the display
lcd.begin(16, 2);
// initialize the Serial Monitor
Serial.begin(9600);
Serial.println("Starting game");
}
void loop() {
// turn off all lights
blackOut();
// turn on current light
digitalWrite(lightPins[currentLight], HIGH);
checkButton(); // Checks to see if the button gets pressed
// update current light position
if (ledUpdate >= ledUpdateSpeed && gameStatus == 1) { // allows me to slow down how fast the LEDs update without changing how fast the logic is
currentLight = (currentLight + 1) % numLights;
ledUpdate = 0;
}
// updates display with current game state
currentGameState();
// check if game is over
if (numLives == 0) {
gameReset();
}
changeLedSpeed();
ledUpdate++;
delay(100);
}
void blackOut() { // turn off all lights
for (int i = 0; i < numLights; i++) {
digitalWrite(lightPins[i], LOW);
}
}
void checkButton(){ // checks the state of the button and changes the game state accordingly
// check if button is pressed
int buttonState = digitalRead(buttonPin);
if (buttonState == HIGH && buttonReleased) { // This is to prevent holding the button (even though that would make you lose anyways)
// button was pressed & then released, set Released to false
buttonReleased = false;
if (currentLight == greenLED) {
int rigged = random(1, 5); // 2 in 4 chance the game is rigged
if (rigged == 1) {
// even though player hit the button at the right time, this game is rigged.
blackOut();
currentLight = greenLED - 1; // set current led back one from the green LED
digitalWrite(lightPins[currentLight], HIGH);
hitYellow();
}
else if (rigged == 2 || rigged == 4) {
// button was pressed at the right time, player gets a point
numPoints++;
Serial.println("You Got a Point!");
currentGameState();
}
else if (rigged == 3) {
// even though player hit the button at the right time, this game is rigged.
blackOut();
currentLight = greenLED + 1; // set current led forward one from the green LED
digitalWrite(lightPins[currentLight], HIGH);
hitYellow();
}
delay(1000);
}
else if (currentLight == greenLED - 1 || currentLight == greenLED + 1) {
// player hit the button in the yello
hitYellow();
delay(1000);
}
else {
// button was pressed at the wrong time, player loses a life
numLives--;
Serial.println("Wrong Time");
delay(1000);
}
}
else if (buttonState == LOW) {
// button was released, set Released to true
buttonReleased = true;
}
}
void hitYellow() {
lcd.clear();
lcd.print("Yellow");
lcd.setCursor(0, 1); // move cursor to second row
lcd.print("No Gain No Loss");
}
void gameReset() { // when game over, wait a bit, then restart
Serial.println("Game over!");
gameStatus = 0;
gameResetTimer += 1;
if (gameResetTimer == 100) {
gameStatus = 1;
gameResetTimer = 0;
numLives = 3;
numPoints = 0;
ledUpdateSpeed = 3
}
}
// updates the display with current game state
void currentGameState() {
if (gameStatus == 1) { // Game running
lcd.clear();
lcd.print("Points: ");
lcd.print(numPoints);
lcd.setCursor(0, 1); // move cursor to second row
lcd.print("Lives: ");
lcd.print(numLives);
}
else if (gameStatus == 0) { // Game Over
lcd.clear();
lcd.print("GAME OVER!");
lcd.setCursor(0, 1); // move cursor to second row
lcd.print("Points: ");
lcd.print(numPoints);
}
}
// changes the speed of the LEDs based on the game score
void changeLedSpeed() {
if (numPoints == 3) {
ledUpdateSpeed = 2;
}
else if (numPoints == 6) {
ledUpdateSpeed = 1;
}
else if (numPoints == 12) {
ledUpdateSpeed = 0;
}
}