Mr. Martin's programming school

Merlin

« JavaScript
Merlin was a kind of computer game from the early 70'ies. Well, hardly a computer. It was not even a gaming console since it did not accept cartriges, and could only play a few built-in games. It didn't even have a screen, just some pushbuttons and red LED's. And the games was actually quite boring.

However, it is suitable as an example for us to learn some of what can be done with JavaScript.
It had the size and look of a phone receiver of the time, and it was red, as you can see here to the right.

The game we will work with used the nine combined push-buttons and LED's you can see in the middle of the... whatever.

We will use two images that will work as push-buttons and LED's, one is lit and the other is dark. This is what they look like:

 

We will display these images in a 3 * 3 grid.

The game itself is very simple, and thus should prove easy to implement in JavaScript. The objective is to achive the following pattern by clicking the buttons:


Pressing one button will make it toggle, but it will also make some other buttons toggle. The patterns are easy. If you press a corner button, it will also toggle the two oposite sides center buttons. So, if lower right corner button is pressed, upper center and left center buttons also toggle, like this:



Pressing a button on the middle of a side also toggles the two opposite corner buttons. If you press e.g. the top center button, the bottom corner buttons are also toggled, like this:



These rules apply to all corner and mid-side buttons. The center button, however toggles all buttons. No need to make a picture to show that.

When the correct pattern is achieved, a messagebox should appear to display the number of button presses you needed to solve the game:



The script

We will write an html file and embed the script in it. We save it as a common .html file so that you will just have to double-click it in order to start the browser and run the game.

Let us start with a short html page containing a section for the script and a 3 * 3 table in the body. Note that we must put in an onLoad event handler in the body tag in order to initialy shuffle and display the board, else we would only have empty labels:

<html>
    <head>         <script type="text/javascript">
        </script>
    </head>     <body onload="JavaScript:shuffle()">
        <table>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </table>
    <body>
</html>

Fill each table cell with a label. We will use the lables as buttons and to show images in. Number the lables with an id from "0" to "8". Also add an event handler call to a function switch_pattern() which we will soon write:

<label id="0" onClick="JavaScript:switch_pattern(0)"/>

That would be all HTML-code we willneed. Next is a bunch of JAvaScript to go into the script section. That is between the <script language="JavaScript1.3"> and the </script> tag, of course.

In order to keep track of the game progress we need one list of integers that stores the state of each of the nine buttons, and one list holding the solution pattern, and a counter to count how many button clicks the user needed to solve the game. Put them in the beginning of the script section:

        var pattern = [0,0,0,0,0,0,0,0,0];
        var solved = [1,0,1,0,1,0,1,0,1];
        var count = 0;

We will need a couple of functions. The pattern needs to be shuffled, i.e. some values set to 1 for a lit button, and some to 0. We use the Math library function random() to get a random value between 0 (inclusive) and 1 (exclusive), and round() to get 0 or a 1 since round() will return 1 when the value is 0.5 or above, else 0:

        function shuffle()
        {
            for(var i = 0; i < 9; i++)
            {
                pattern[i] = Math.round(Math.random());
            }
            update_board();
            count = 0;
        }

We will also need a function that updates the board, i.e. sets the images according to the pattern array. Here we use getElementById to get the DOM objec for each label in turn, and set the images according to the values in pattern[]:

            function update_board()
            {
                document.getElementById("0").innerHTML = "<img src='" + pattern[0] + ".png'>";
                document.getElementById("1").innerHTML = "<img src='" + pattern[1] + ".png'>";
                document.getElementById("2").innerHTML = "<img src='" + pattern[2] + ".png'>";
                document.getElementById("3").innerHTML = "<img src='" + pattern[3] + ".png'>";
                document.getElementById("4").innerHTML = "<img src='" + pattern[4] + ".png'>";
                document.getElementById("5").innerHTML = "<img src='" + pattern[5] + ".png'>";
                document.getElementById("6").innerHTML = "<img src='" + pattern[6] + ".png'>";
                document.getElementById("7").innerHTML = "<img src='" + pattern[7] + ".png'>";
                document.getElementById("8").innerHTML = "<img src='" + pattern[8] + ".png'>";
            }

The main logics will go into a function that handles the button clicks i.e. the one you put into the labels in the table, the one that should handle the onClick() events:

            function switch_pattern(btn)
            {
                switch(btn)
                {
                    case 0:
                        toggle(0);
                        toggle(5);
                        toggle(7);
                    break;
                    case 1:
                        toggle(1);
                        toggle(6);
                        toggle(8);
                    break;
                    case 2:
                        toggle(2);
                        toggle(3);
                        toggle(7);
                    break;
                    case 3:
                        toggle(3);
                        toggle(2);
                        toggle(8);
                    break;
                    case 4:
                        toggle(0);
                        toggle(1);
                        toggle(2);
                        toggle(3);
                        toggle(4);
                        toggle(5);
                        toggle(6);
                        toggle(7);
                        toggle(8);
                    break;
                    case 5:
                        toggle(5);
                        toggle(0);
                        toggle(6);
                    break;
                    case 6:
                        toggle(6);
                        toggle(1);
                        toggle(5);
                    break;
                    case 7:
                        toggle(7);
                        toggle(0);
                        toggle(2);
                    break;
                    case 8:
                        toggle(8);
                        toggle(1);
                        toggle(3);
                    break;
                }
                
                update_board();
                count++;
                var all_done = true;
                var i = 0;
                while(all_done && i < 9)
                {
                    if(pattern[i] != solved[i])
                    {
                        all_done = false;
                    }
                    i++;
                }
                
                if(all_done)
                {
                    alert("Congratulations! You made it in " + count + " tries!");
                    shuffle();
                }
            }

The function above first uses the index value in the argument btn in a switch to select what buttons needs to be toggled. Then it updates the board and at last compares the pattern to the solution array, and if they are the same, shows the message. The function calls toggle() and update_board(), the latter we have, but toggle() still needs to be written:

            function toggle(btn)
            {
                pattern[btn] = Math.abs(pattern[btn] - 1);
            }

The value toggling could have been done using a simple if-else syntax, or a switch syntax, but I elected to use the Math library, just to show you it is there and that it works.

That should be all. You can save the file where you like and double-click it. You can also try it here: