-
Video Uploaded
09/10/2024 at 17:20 • 0 commentsA brief video of the game's operation has been attached to the project.
-
Video Forthcoming!
09/08/2024 at 17:03 • 0 commentsDue to a lack of planning on my part, I am out of coin cell batteries. Once I grab one from the store I will upload a video of the game running!
-
Code
09/08/2024 at 16:54 • 0 commentsFor easy copy-paste, the code for the Simon Says game is below. It is also attached as a file to this project.
/** * Simon Says * * This program represents a simple game of Simon Says with two LEDs and two push buttons. * It is designed to showcase a minimalistic circuit that still does something interesting. * * When the circuit is powered on, both LEDs will blink three times. Then, LEDs will light up * one at a time in a random pattern that the user must duplicate using the push buttons. * Once the sequence has completed, each button controls an LED. The pattern in which the * LEDs blink is randomly generated, and has a length measured in blinks. The patterns begin * with one blink, then increase by one blink each time the player correctly mimics the sequence. * * If the user gets the sequence wrong, both LEDs will blink three times, then start a new * pattern at length 1. The game will continue until the pattern is 50 blinks long. If the * user correctly mimics all 50 patterns, the game is over and the LEDs will blink in a * celebratory pattern until the circuit is power cycled. * * This code can be run on an Arduino, but is designed for the ATtiny85 microcontroller. * * Author: acr */ // pin configuration const int greenLED = 4; const int redLED = 1; const int greenButton = 3; const int redButton = 2; // debounce unsigned long lastGreenDebounceTime = 0; unsigned long lastRedDebounceTime = 0; unsigned long debounceDelay = 50; // game data char pattern[50] = {0}; int curPatternLength = 1; int greenButtonState = 0; int redButtonState = 0; int lastGreenButtonState = 0; int lastRedButtonState = 0; void setup() { // initialize LED pins as digital outputs pinMode(greenLED, OUTPUT); pinMode(redLED, OUTPUT); // initialize button pins as digital inputs pinMode(greenButton, INPUT); pinMode(redButton, INPUT); // seed random number generator randomSeed(analogRead(0)); } /** * Blink both LEDs in the pattern that occurs when * the player has lost the game. */ void blinkLose() { for(int i = 0; i < 3; i++) { digitalWrite(greenLED, HIGH); digitalWrite(redLED, HIGH); delay(500); digitalWrite(greenLED, LOW); digitalWrite(redLED, LOW); delay(500); } } /** * Blink both LEDs in the pattern that occurs when * the player has won the game. */ void blinkWin() { for(int i = 0; i < 2; i++) { digitalWrite(greenLED, HIGH); digitalWrite(redLED, LOW); delay(500); digitalWrite(greenLED, LOW); digitalWrite(redLED, HIGH); delay(500); digitalWrite(greenLED, LOW); digitalWrite(redLED, LOW); } for(int i = 0; i < 2; i++) { digitalWrite(greenLED, HIGH); digitalWrite(redLED, HIGH); delay(500); digitalWrite(greenLED, LOW); digitalWrite(redLED, LOW); delay(500); } } /** * Generate a blink pattern that is length blinks long, * and store that pattern in the pattern array. */ void generatePattern(int length) { for(int i = 0; i < length; i++) { int rand = random(10); if(rand < 5) { pattern[i] = 'r'; }else { pattern[i] = 'g'; } } } /** * Turns off all LEDs. */ void turnLightsOff() { digitalWrite(greenLED, LOW); digitalWrite(redLED, LOW); } /** * Turns on all LEDs. */ void turnLightsOn() { digitalWrite(greenLED, HIGH); digitalWrite(redLED, HIGH); } /** * Turns both lights on and blocks all other activity. * For use in case of an error state to indicate that * the user should check the logs and power cycle. */ void error() { while(1) { turnLightsOn(); } } /** * Display the current pattern stored in the pattern array * using the red and green LEDs. */ void displayPattern() { for(int i = 0; i < curPatternLength; i++) { turnLightsOff(); delay(500); if(pattern[i] == 'g') { digitalWrite(greenLED, HIGH); delay(500); }else if(pattern[i] == 'r') { digitalWrite(redLED, HIGH); delay(500); }else { error(); } } turnLightsOff(); } /** * Check whether the color at position pos in the pattern * matches the given color. Returns 1 if true, 0 if false. */ int checkPatternColor(char color, int pos) { if(pattern[pos] == color) { return 1; } return 0; } /** * Returns 1 if both buttons are unpressed, 0 otherwise. */ int buttonsUnpressed(int redState, int greenState) { if(redState == LOW && greenState == LOW) { return 1; } return 0; } /** * Reads the pattern as input by the player. Returns 1 if * the player entered the pattern correctly, 0 otherwise. */ int readPlayerPattern() { int cntr = 0; // counter for current position in the pattern int correct = 1; // whether the pattern is correct char playerColor = 0; // store the current color selection by the player while(cntr < curPatternLength) { int greenReading = digitalRead(greenButton); int redReading = digitalRead(redButton); int buttonsChanged = 0; if(greenReading != lastGreenButtonState) { lastGreenDebounceTime = millis(); } if(redReading != lastRedButtonState) { lastRedDebounceTime = millis(); } if((millis() - lastGreenDebounceTime) > debounceDelay) { if(greenReading != greenButtonState) { greenButtonState = greenReading; buttonsChanged = 1; } } if((millis() - lastRedDebounceTime) > debounceDelay) { if(redReading != redButtonState) { redButtonState = redReading; buttonsChanged = 1; } } if(buttonsChanged == 1) { // monitor button state to debounce if(greenButtonState == HIGH && redButtonState == HIGH) { // fail - the two lights will never be on at the same time correct = 0; break; }else if(greenButtonState == HIGH && redButtonState == LOW) { // green button pressed playerColor = 'g'; }else if(greenButtonState == LOW && redButtonState == HIGH) { // red button pressed playerColor = 'r'; }else { playerColor = 0; } /* Note: Nothing is done if both buttons are low so that the player * has time to input the pattern at their own pace. */ if(playerColor != 0) { // check if the choice was correct correct = checkPatternColor(playerColor, cntr); if(correct == 1) { // if so, increment the counter and continue cntr++; playerColor = 0; }else { // if not, break out of the loop break; } } } lastGreenButtonState = greenReading; lastRedButtonState = redReading; buttonsChanged = 0; } return correct; } /** * The main loop of the program, runs repeatedly while the * power is on. */ void loop() { // Serial.println("Starting program"); blinkLose(); // blink 3 times on power up // start the game while(curPatternLength <= 50) { // game is 50 levels long generatePattern(curPatternLength); displayPattern(); int playerResult = readPlayerPattern(); if(playerResult == 1) { // player got the latest pattern correct, continue to the next one curPatternLength++; }else { // player failed the latest pattern, notify player of loss and restart pattern counter blinkLose(); curPatternLength = 1; } delay(2000); // break in between patterns so user can keep up } // at this point, the user must have won all levels, so display win pattern blinkWin(); }