Landing : Athabascau University
  • Blogs
  • Circuit 4C: DIY Who Am I? Game

Circuit 4C: DIY Who Am I? Game

I had no trouble building the circuit. I modified the example program so that there are multiple categories, and the category for the round is chosen at random. Here is the code:

#include <LiquidCrystal.h> //the liquid crystal library contains commands for printing to the display
LiquidCrystal lcd(7, 12, 11, 10, 9, 8); // tell the RedBoard what pins are connected to the display
int buttonPin = 2; //pin that the button is connected to
int buzzerPin = 6; //pin for driving the buzzer
int buttonPressTime = 0; //variable to show how much time the player has left to guess the word (and press the button)
long timeLimit = 4000; //time limit for the player to guess each word
long startTime = 0; //used to measure time that has passed for each word
int roundNumber = 0; //keeps track of the roundNumber so that it can be displayed at the end of the game
int arraySize = 0; //Size of the chosen category array
String category = ""; //Name of the chosen category
const int maxArraySize = 31; //Size of the largest category array that could be chosen
const int rounds = 3; //Number of rounds to win
//These are the category arrays
const char* animals[] = {"moose", "beaver", "bear", "goose", "dog", "cat", "squirrel", "bird", "elephant", "horse",
"bull", "giraffe", "seal", "bat", "skunk", "turtle", "whale", "rhino", "lion", "monkey",
"frog", "alligator", "kangaroo", "hippo", "rabbit"};

const char* plants[] = {"tree", "sunflower", "dandelion", "carrot", "potato", "grass", "onion", "cactus", "corn", "rose",
"tobacco"};

const char* bugs[] = {"spider", "ant", "ladybug", "wasp", "bumble bee", "termite", "centipede", "millipede", "moth",
"caterpillar", "butterfly", "dung beetle", "rhinoceros beetle", "fruit fly", "cricket",
"grasshopper", "worm", "maggot", "cockroach", "dragonfly", "firefly", "housefly",
"horse-fly", "mosquito", "louse", "tapeworm", "wood tick", "deer tick", "tarantula",
"scorpion", "snail"};
int sequence[maxArraySize]; //Sequence array
void setup() {
pinMode(buttonPin, INPUT_PULLUP); //set the button pin as an input
lcd.begin(16, 2); //tell the LCD library the size of the screen
selectRandomCategory(); //Choose a category randomly
generateRandomOrder(); //generate an array of random numbers that will determine which order the words are shown in
showStartSequence(); //print the start sequence text
}
void loop() {
boolean lost = false; //Becomes true when the player loses
//for each word in the sequence while lost is false
for (int i = 0; i < rounds && lost == false; i++) {
lcd.clear(); //clear off the array
roundNumber = i + 1; //the array starts at 0, but the roundNumber will start counting from 1
lcd.print(roundNumber); //print the roundNumber (this is the current round number)
lcd.print(": "); //spacer between the number and the word
//These if statements print a word from the chosen category
if(category == "Animals"){
lcd.print(animals[sequence[i]]); //print a random word from the animals array
} else if(category == "Bugs"){
lcd.print(bugs[sequence[i]]); //print a random word from the bugs array
} else if(category == "Plants"){
lcd.print(plants[sequence[i]]); //print a random word from the plants array
} else {
lcd.print("ERROR"); //This means I probably made a typo above
}
startTime = millis(); //record the time that this round started
while (digitalRead(buttonPin) == HIGH && lost == false) { //do this until the button is pressed...
int roundedTime = round((timeLimit - (millis() - startTime)) / 1000); //calculate the time left in the round
lcd.setCursor(14, 1); //set the cursor in the lower right corner of the screen
lcd.print(" ");
lcd.setCursor(14, 1); //set the cursor in the lower right corner of the screen
lcd.print(roundedTime); //print the time left in the time limit
delay(15);
if (digitalRead(buttonPin) == LOW) {
tone(buzzerPin, 272, 10); //emit a short beep when the button is pressed
}
if (millis() - startTime > timeLimit) { //if the time limit is up before the button is pressed
lost = true;
}
} //exit this loop when the button is pressed
delay(500); //delay for a moment before going onto the next round (Debounce)
}

//if you finish all the rounds
if(lost == false){
winner(); //show the you win message
} else {
gameOver(); //loser
}
setup();
}

//--------------FUNCTIONS------------------------------
//DISPLAYS A COUNTDOWN TO START THE GAME
void showStartSequence() {
lcd.clear(); //clear the screen
lcd.setCursor(0, 0); //move the cursor to the top left corner
lcd.print("Category:"); //print "Category:"
lcd.setCursor(0, 1); //move the cursor to the bottom left corner
lcd.print(category); //print the name of the category
delay(2000); //Wait 2 seconds
lcd.clear(); //clear the screen
lcd.print("Get ready!"); //print "Get ready!"
delay(1000); //wait 1 second
lcd.clear(); //clear the screen
lcd.print("3"); //print "3"
delay(1000); //wait 1 second
lcd.clear(); //clear the screen
lcd.print("2"); //print "3"
delay(1000); //wait 1 second
lcd.clear(); //clear the screen
lcd.print("1"); //print "3"
delay(1000); //wait 1 second
}
//GENERATES A RANDOM ORDER FOR THE WORDS TO BE DISPLAYED
void generateRandomOrder() {
randomSeed(analogRead(0)); //reset the random seed (Arduino needs this to generate truly random numbers
for(int i = 0; i < arraySize; i++){
sequence[i] = -1;
}

for (int i = 0; i < arraySize; i++) { //do this until all required positions are filled

int currentNumber = 0; //variable to hold the current number
boolean match = false; //does the currentNumber match any of the previous numbers?
//generate random numbers until you've generated one that doesn't match any of the other numbers in the array
do {
currentNumber = random(0, arraySize); //generate a random number
match = false; //we haven't checked for matches yet, so start by assuming that it doesn't match
for (int i = 0; i < arraySize; i++) { //for required numbers in the array
if (currentNumber == sequence[i]) { //does the currentNumber match any of the numbers?
match = true; //if so, set the match variable to true
}
}
} while (match == true); //if the match variable is true, generate another random number and try again
sequence[i] = currentNumber; //if the match variable is false (the new number is unique) then add it to the sequence
}
}
//GAME OVER
void gameOver() {
lcd.clear(); //clear the screen
lcd.setCursor(0, 0); //move the cursor the top left corner
lcd.print("Game Over"); //print "Game Over"
lcd.setCursor(0, 1); //move to the bottom row
lcd.print("Score: "); //print a label for the score
lcd.print(roundNumber); //print the score (the round number is the same as the score)
//play the losing fog horn
tone(buzzerPin, 130, 250); //E6
delay(275);
tone(buzzerPin, 73, 250); //G6
delay(275);
tone(buzzerPin, 65, 150); //E7
delay(175);
tone(buzzerPin, 98, 500); //C7
delay(500);
while (digitalRead(buttonPin) == HIGH) {
if (digitalRead(buttonPin) == LOW) {
tone(buzzerPin, 272, 10); //emit a short beep when the button is pressed
}
}
}
//WINNER
void winner() {
lcd.clear(); //clear the screen
lcd.setCursor(7, 0); //move the cursor to the top center of the screen
lcd.print("YOU"); //print "You"
lcd.setCursor(7, 1); //move the cursor to the bottom center of the screen
lcd.print("WIN!"); //print "WIN!"
//play the 1Up noise
tone(buzzerPin, 1318, 150); //E6
delay(175);
tone(buzzerPin, 1567, 150); //G6
delay(175);
tone(buzzerPin, 2637, 150); //E7
delay(175);
tone(buzzerPin, 2093, 150); //C7
delay(175);
tone(buzzerPin, 2349, 150); //D7
delay(175);
tone(buzzerPin, 3135, 500); //G7
delay(500);
while (digitalRead(buttonPin) == HIGH) {
if (digitalRead(buttonPin) == LOW) {
tone(buzzerPin, 272, 10); //emit a short beep when the button is pressed
}
}
}
void selectRandomCategory(){
randomSeed(analogRead(0)); //reset the random seed
int randomNumber = random(0, 3); //Random number from 0 to 2
//These if statements choose the category based on the random number
//The arraySize variable is different for each category because
// each category has a different amount of words
if(randomNumber == 0){
category = "Animals";
arraySize = 25;
} else if(randomNumber == 1){
category = "Plants";
arraySize = 11;
} else if(randomNumber == 2){
category = "Bugs";
arraySize = 31;
}
}

Most of the code is from the example program. Instead of having one “words” array I have added three different arrays, one for each category of words. I have also created the method selectRandomCategory() which selects the category randomly. The showStartSequence() function is exactly the same as in the example program. I have edited the while loops in the winner() and gameOver() functions so that they do nothing until the button is pressed, rather than doing nothing forever. This allows the player to reset the game by pressing the button attached to the breadboard, rather than having to press the “reset” button on the RedBoard. Aside from the while loop, the winner() and gameOver() functions are the same as in the example program. The generateRandomOrder() function is also mostly the same as in the example program, but I added a for loop to set all the values in the “sequence” array to -1.

Here is a video of the program in action:  WhoAmI

I had some trouble figuring out how to reset the game by pressing the button on the breadboard instead of the reset button. I had initially thought that I would only need to edit the while loops in the winner() and gameOver() functions to exit when the button is pressed. However, this did not work properly because the program would continue in the loop() function rather than starting from the beginning. To fix this, I moved the call to gameOver() to inside an if-else statement at the end of the loop() function along with the call to winner(), and I added the boolean variable “lost” to allow the while and for loops to exit when lost == true, as well as a call to setup() at the very last line of the function to set the program back to setup(). However, these changes were still not enough to make it work properly, because the sequence array was still filled with the values from the previous game, and the generateRandomOrder() function generates random numbers in the specified range until it generates one that is not already in the array. This would cause a never-ending loop since the range of numbers could be equal to the size of the array, so any number that could be generated could also be found in the array, so it would just loop forever. I fixed this problem by including a for loop at the beginning of gnerateRandomOrder() to set all the values of the sequence array to -1.