Myself, Coding, Ranting, and Madness

The Consciousness Stream Continues…

Noggle

8 Oct 2012 20:30 Tags: JavaScript, Games, Programming, Web Design

What happens when I get utterly destroyed playing boggle? I write a training program where you have to, as a single player, find words as a path of letters! You can play the result, called Noggle, and have some fun looking for words. The code is not compatible with any current version of Internet Explorer1.

This idea is simple: first, you generate the layout of a Boggle game, present the user some way to input words. As they play, you have to check that the words are in the dictionary, and possible to play on the board given. Finally, words that are successful should be scored, and a total score shown after three minutes. The implementation is, for once, not much harder.

The code for this little boggle trainer — which has been tested in recent versions of Chrome and Firefox — took a very short time to write: most of the work was done one Friday evening, in a three-hour blaze of coding. Some supplementary work — including borrowing a friend's boggle set to check I had the right distribution of letters — happened over the weekend.

The board is generated using a series of shuffle operation. boggle.js contains an array of the 16 boggle dice, each of which has an array containing the letter2 on each side.

The array of each die is shuffled, and the resulting first element is considered to be the side facing the user. The shuffled list of dice determines the order they are laid out on the grid. Actually writing a letter into a div in a sensible way is a surprisingly difficult matter, as people decided to throw the standard out the window.

The standard text property is innerText; Mozilla uses textContent and, in both cases, the property will always be defined — even if it is only an empty string. This means we can take advantage of of the in operator, which tells us whether a property exists in an object.

setText(node, text) { if ('innerText' in node) node.innerText = text; else if ('textContent' in node) node.textContent = text; else alert('Oh noes! it all went wrong!'); }

This simple function3 will continue to work as expected even if other factors change. Many of the other functions for this purpose look for some general ‘tell’ of Firefox — a habit perhaps left over from the time when a browser detection script was considered ac acceptable idea4.

Then we have two input methods. You can either type the word into the input and hit return to submit, or drag a path across the grid in order to spell out a word. As I implemented the dragging method as the last feature before writing this article, it actual just works as an emulator for typing. As you perform the movement, each time you move over a node in the grid, it adds the text of that mode to the input box.

Once this text is added, an addition class is applied to the node, highlighting it to be part of the path. The addition of this class also stops the node's text being added again. When the mouse is released, the input is submitted as if the user had pressed enter

Validation takes place in a number of simple stages. Firstly, we check that the word is three of more letters long, otherwise we just discard it. Next, we check whether the work can be found on the grid (the procedure for this will be explained later), and then in the dictionary. The dictionary operation is simplified by dictionary.js, a copy of a scrabble dictionary formatted as a JavaScript object with a property for every valid word. This allows the check to be made as:

if (word in dictionary)

If the word is in the dictionary, and not in the list of words that have already been played, the score for that word is calculated, and added to the total score. The form is reset, and the user can enter a new word.

The only at all tricky part of this code is the checking whether the word can appear on the board. Even this is not too much of a problem; if you treat 'Qu' as a single character, it's easy to design an exhaustive search pattern. Firstly, we find all instances of the first letter of the word. For each of these, you look for the second letter in all adjacent squares for the second letter. Everywhere the second letter was found, you look at adjacent squares for the third, making sure you don't pick a square that you have already visited

My implementation is rather naïve: the board is scanned linearly for the first letter, and then each node is expanded left-to-right and top-to-bottom in a depth-first search. It is, however, fast enough for a board of this size.

So, that's the game. It was originally intended as a little intellectual exercise in the office one Friday evening to help with my Boggle skills; by Monday evening, there's a working single-player version, with notes on how to make it multi-player in my note pad. In my notepad is, however, where they'll be staying. Noggle itself will probably hang around unobtrusively on the website, and the code should be hitting GitHub before the end of the week.

  1. 1 Although, purely for stylesheet reasons...
  2. 2 Qu is technically two letters, a fact I will mainly be ignoring throughout
  3. 3 Which has terrible error handling — you should not just alert messages to the user willy-nilly
  4. 4 It never was.