Building Simon

Stuart Fooks
6 min readJan 16, 2019

--

For our first project at General Assembly, our cohort was tasked with building a simple game. We were given a choice of four games: Simon, Tower of Hanoi, Trivia, or Flash Cards. Simon sounded like the most interesting option to me, so I went with that one. If you’re not familiar with Simon, here’s a quick video of the “real life” Simon gameplay:

The game lights up a sequence of colored lights, and the user tries to press the lights in the same order. If they do, the sequence then grows by one, and the game repeats. If the user presses the order incorrectly, the game starts over.

If you haven’t already done so, you can view and play my version of Simon here:

In this post, I’ll set out to explain my thought process for building Simon, and a few of the problems I faced along the way.

Once I had the initial file structure setup, I used Pug and Sass along with Parcel to create a simple layout that (roughly) resembled the game. At this point it was a box with four colored squares. Good enough for now — our instructors have emphasized this general process for our projects at GA and beyond: make it work, make it right, make it fast. So I moved onto to the meat of this project, the JavaScript.

To begin, I wrote out the high-level steps that the game needed to follow.

The high-level steps for my game can be seen in the top-righthand corner of the above image. The most difficult step for me was by far step 1, ‘Highlight different color blocks in order’. Step 2 involved a pretty simple event listener on each light (block), and pushing the target of the user’s clicks (and the colors they correspond to) into an array. Step 3 is a simple comparison of two arrays. Step 4 just involves generating a random color from an array of four colors, and pushing that onto the end of my “sequence” of random colors. Step 5 just required a way to call the functions that I had already written. With all that in mind, I’ll spend the majority of my time dissecting step 1 — just as I did in writing my code.

Immediately below the high-level steps of my game, you can see that I wrote the number 1 again, basically to say, “woah… let’s break this down a little bit further.”

Step 1 of high-level step 1 is ‘Have an array of 4 colors’. Okay easy enough — I created my array of four colors:

let colors = [
'green',
'red',
'yellow',
'blue'
]

Next up, ‘Loop that array and create a new array [of the same four colors in a random order]’. Again, now that I had the original high-level step 1 broken down into smaller parts, this part was pretty manageable:

let sequence = []const randomizer = () => {
for(let i = 0; i < colors.length; i++) {
let random = Math.random()
let length = colors.length
let index = Math.floor(length * random)
sequence.push(colors[index])
}
}

I now had a way of randomly populating the array I called “sequence”, which was just the order in which I would highlight the colored game blocks. The function is a bit verbose and could definitely be consolidated, but for a difficult first step in a new developer’s first project, it got the job done.

The next step — step 3 of high-level step 1 — was ‘set border of each square to yellow [by] adding a new class in the order of [sequence]’.

** Note that at this point in my process, I was “highlighting” each game block by giving it a thick yellow border. Later on I changed the “highlight” class to give the whole block an opacity of 1, but this is more of a stylistic switch than anything functional.**

This step required me to break down my process even further. We’ll follow the arrow in my notebook to the left for the break break down of the break down.

In the above image, I first wrote the three bullet points. I then realized that in order for the lights to light up one after another, I needed to wrap those tasks in a function, and to somehow run that function on a delay. Great. However, once I set out to write this portion of my code, I realized that this is pretty bad pseudocode. “Get” and “highlight” aren’t exactly standard JavaScript methods. Enter the rewrite of this step.

That’s better — now I knew that I needed a loop, and the tasks inside of the loop were actually what needed to run on a delay, not the whole function. The loop needed to iterate through each color in the sequence array, and save that as the current color. Next, the loop needed to find the game block with a background color equal to the current color. Finally, the loop needed to toggle a CSS class that I called ‘highlighted’, which set the border of the game block to a thick yellow line.

The logic of this seemed easy enough, but I had never made anything run on a delay before. Up until this point, all my code had executed either on the page load or on the function call. Enter setTimeout. SetTimeout allowed me to call functions after a specified delay.

However, this led to problem number one: setTimeout accepts a reference to a function as an argument, not a function call. Of course, this means the function that you reference cannot accept arguments. This presented a problem, as most of the functions I had already written had required parameters. The fix for this turned out to be incredibly simple, but that doesn’t mean it didn’t take some Googling to figure out. The fix: wrap the functions I needed to call in anonymous callback functions with the setTimeout arguments.

The next problem that I ran into during my first encounter with setTimeout took a bit longer for me to figure out. Problem number two: if you call setTimout within a for loop, the function you pass into setTimeout will indeed run on a delay, but the loop will not pause and wait for the function to run before iterating through the rest of the loop. In other words, it iterated through the entire array, waited for my specified delay, and then highlighted all the requisite game blocks at once. Again, the solution turns out to be a fairly simple one: write your loop as a function instead of using a strict for loop.

With that I had completed what I consider to the most challenging part of the project. From there, I added some additional features (such as Standard mode vs Reverse mode) that required some additional if statements and functions, but I didn’t encounter anything as challenging to implement.

I hope you enjoyed a brief insight into my thought process and challenges in building Simon. I would also be happy to answer any questions or clarify anything that is a bit unclear. You can view the GitHub repository and the complete code here:

--

--