Design
printer friendly version

The game was designed by following the procedure outlined in the flowchart in Fig 1. The flowchart is fairly obvious, as it simply follows the game play of a typical game of Simon. We begin by prompting the user for the desired game mode and difficulty level. Then, we initialize the game to the user’s settings and begin playing the sequence. After the sequence is played, the game looks for the user’s response. If the response is correct, the new sequence is played and the process repeats. If the user answered incorrectly, then the game ends and waits for a new game to begin.

Fig 1

To implement the flowchart we created a Finite State Machine (FSM) to run the program (see Fig 2). The FSM gives a more detailed explanation of how the game process works. It follows the same pattern and procedure as the flowchart, but shows how the program plays back the sequence, as well as checks the user’s inputs.

Fig 2

Numerous functions are called during the implementation of the FSM, but here are a few things worth mentioning:

The sequence of colors is held in noteArray. Each color has a corresponding musical note, which is held in noteTable. The value held in noteTable is half of the period for 1 cycle of each musical note in 1/8 ms. ticks, since the port with the speaker needs to be toggled in order to make sound. The first four values of noteTable are the notes corresponding to the red, blue, yellow, and green sounds.

randNote() creates a random color and adds that color to the end of the current sequence, which is held in noteArray. In order to generate the random number needed for randNote(), we incremented a running variable every 1 ms. by placing it in the Timer 0 overflow I.S.R. When randNote() is run, it pulls the value of that number off of the variable at that moment, and then masks it with 0x18 (chosen arbitrarily) to get two bits. These two bits give a random number between 0 and 3, which corresponds to red, blue, yellow, or green respectively. Since this number is incremented so quickly in between “pulls,” it is essentially random.

playback() plays the next color in the sequence by setting the OCR1A to the appropriate noteTable value, turns on Timer 1, and lights up the matching colored LED. The playbackFlag is then set high, indicating that the program is in “playback mode.” The Playback state of the FSM cannot do anything until the playbackFlag is set low again, or until the program is out of playback mode. In order to be able to speed up the rate at which the notes of the sequence are played back in the Free For All mode, we used a timing method that allows a specific amount of time for each note/LED to be on and off. This timer reduces during play, making Simon play the sequence faster and faster as time goes on.

userPush() sets OCR1A to the noteTable value of the color that the user just pushed. It also turns on Timer 1 and lights up the matching colored LED using a timing scheme similar to the one used for playback(). A userplaybackFlag is set high, the LED and sound are turned on, a user timer (which is always the same amount of time) is run down, and then the LED and sound is then turned off. This allows the LED and sound to be on for a constant amount of time for any button push the user makes.

The sound for the start and select buttons is turned on in the toggleMode and toggleLevel functions, as well as in the ModeStart and LevelStart states of the FSM. This means that a sound is made every time the start or select button is pushed (while not in the middle of a game). Instead of using another timing scheme like the one for playback() and userPush(), the sound is turned off in the beginning of the task containing the FSM (assuming that the program is not in a playback or userPlayback mode). This much simpler scheme still allows the sound to be played for a decent amount of time.

The remaining functions deal with the LCD, doing one of three things: initialize the LCD to display which mode/level the user desires, update the rounds won, or display winning/losing message to user.

For further details of any function used, please see the code in Appendix 1.

The FSM is defaulted to the ModeStart state. The FSM cycles between ModeStart and ModeSelect. The user can press the select button to choose the desired mode or the start button to jump to the LevelStart state. The FSM also cycles between LevelStart and LevelSelect. The user can press the select button to choose a difficulty level or press the start button to start the game.

Once the game is started, the first color of the sequence is created with randNote(). The FSM then goes into the Playback state. Playback will cycle through noteArray, playing and lighting the appropriate sound and LED. The FSM then goes into ButtonPress, which waits for the user to press a button. Once a color button is pressed, userPush() is called, which plays/lights the matching sound/LED of the button pressed. From here, the FSM must wait for the userplayback mode to finish before it can go into Check, which is actually set in the “main” function of the program instead of in the FSM itself. The Check state compares the color pressed by the user to the correct color in the sequence, which is held in noteArray. If the color entered is wrong, the FSM jumps to Endgame, where the program waits for the user to hit the start button to start a new game. If it is correct, the game continues to GameCont, which checks if the user has more colors to enter. If the user needs to enter another color, the FSM cycles back to ButtonPress, where this checking process is repeated for each color the user enters.

After the user has successfully repeated the given sequence, the number of correct rounds is incremented and the FSM goes into RoundCheck, where it checks if the number of correct rounds is less than the predetermined length of the game. If it is not, such as round 7 when the game length is set to 7 in the regular Simon Easy level, then the user has just completed the last round and has won the game, which sends the FSM to Endgame. If the number of correct rounds is less than the game length, then randNote() is called to create a new random color for noteArray, and the FSM goes back into Playback. This game process is repeated until the user wins the game or enters the wrong color.