Building Simon Says with JavaScript

January 2, 2014

This is a tutorial that will show you how to make the classic Simon Says game on the web using JavaScript. The project lives on GitHub, so please check out the source code, star the repo, or do a pull request!


Simon Says game


The HTML used for the Simon “board” is just an unsorted list with some fancy CSS.

<div class="simon">
        <li class="red" data-tile="1"></li>
        <li class="blue" data-tile="2"></li>
        <li class="yellow" data-tile="3"></li>
        <li class="green" data-tile="4"></li>

One thing you may notice is that there are two “identifiers” for each list item — a color class and a data-tile attribute. The classes are used for styles, and data- attributes for JavaScript selectors.


Simon Says is a really simple game, so the code is short (~100 lines). The more difficult part is controlling the “Light Up” animation, so I’ll cover that first.

Lighting Up

To simulate the lighting, we can just change the background opacity on the list items. However, controlling the order and timing of the light up/down pattern is more complicated. To solve this, we have an array called sequence, filled with numbers that represent colors. When we need to animate, we send the array to the animate function, like this:

function newRound() {
    var sequence = [1,2,1]; //red, green, red

function animate(sequence) {
    var i = 0;
    var interval = setInterval(function() {

        if (i >= sequence.length) {
   }, 600);

We want to make sure the items light up and then down, one at a time. We can use JavaScript’s setInterval method to regulate the timing. Then whenever the interval function fires, we can increment an index to track our progress over the sequence array, firing a second function, lightUp(), with the current color in the sequence. When we reach the end of the sequence array, we can just clear the interval.

Finally, we define the lightUp() function, which first adds a class of “lit”, brightening the background by lowering its opacity. After a 300ms timeout, we remove the “lit” class, thus restoring the tile to its normal color. The CSS includes a transition on the opacity property, which makes the animation appear smooth.

function lightup(tile) {
    var $tile = $('[data-tile=' + tile + ']').addClass('lit');
    window.setTimeout(function() {
    }, 300);



Disclaimer: the method used for playing sounds in this demo is sub-optimal. Currently, sounds are embedded on the fly as the playSound() function is triggered, and since the following HTML audio element is set to autoplay, the sound fires right away:

function playSound(tile) {
    var audio = $('<audio autoplay></audio>');
    audio.append('<source src="sounds/' + tile + '.ogg" type="audio/ogg" />');
    audio.append('<source src="sounds/' + tile + '.mp3" type="audio/mp3" />');

The problem with this approach is that we are retrieving each sound from the server every time a sound is played. Since there are only four tones, we should instead be using JavaScript to fire the play() method on the appropriate audio element in HTML. However, I did not use this approach, because without a sound library, it is difficult to interrupt one sound file in order to play the same sound again. For example, if a user clicks the green tile twice in a row, the sound may not play the second time. However if we re-embed the audio tag, this is not an issue. It’s a hack, but it works.

Game Sequence

Finally, the game sequence is controlled something like this:

  1. Wait for player to click start
  2. Start a round, which follows these steps
    1. Add a random number (1-4) to the sequence
    2. Animate the sequence to the user
    3. Enable user interaction with the board, and register any clicks on the Simon tiles
    4. While the player has not entered an incorrect response, and the number of clicks is less than the length of the sequence, wait for player input
  3. Continue adding rounds until the player loses

To view the full source code, please visit my GitHub repo, and don’t forget to star it!

Github Logo