Creating an Online Boggle Solver :: Building the User InterfaceBy Scott Mitchell
I spend most of my day writing about ASP.NET or building ASP.NET applications for clients. As every ASP.NET developer knows, the bulk of ASP.NET development centers around data access - building pages to collect user input and crafting reports to summarize that information. To help break this monotony, I occasionally set aside an afternoon to work on a more interesting project, which helps rechage my batteries. I've shared such fun programming projects in past articles here on 4Guys (see Creating a Quick and Dirty Online Blackjack Game).
My immediate and extended family enjoys playing games, and one of the favorites is Boggle. Boggle is a word game trademarked by Parker Brothers and Hasbro that involves several players trying to find as many words as they can in a 4x4 grid of letters. At the end of the game, players compare the words they found. During this comparison I've always wondered what words we may have missed. Was there some elusive 10-letter word that no one unearthed? Did we only discover 25 solutions when there were 200 or more?
To answer these questions, I decided to create a Boggle solver and did so using ASP.NET version 3.5. The Boggle solver recursively explores the board and locates (and displays) all available solutions. With this nifty little web page, at the conclusion of each Boggle game we can see what words we missed.
This article is the first in a two-part series that details the application, its design, and some of the challenges faced when creating it. In this first installment we will look at the user interface; the second installment examines the logic used to actually solve the puzzle. The complete source code for the Boggle solving application is available at the end of the article. You can also see a live demo in action at www.FuzzyLogicInc.net/Boggle. Read on to learn more about this fun little project.
The Rules of Boggle
Before we examine the code, I should first take a moment to explain the rules of Boggle. Boggle is a word game consisting of 16 dice with letters on each face. The dice are jumbled and randomly fall into 16 slots in a 4x4 grid. At that point, a three minute timer is set and all players write down as many words as they can before the timer expires. The letters of a word are formed by starting at any letter then moving, horizontally, diagonally, or vertically to neighboring dice; each tile may be used at most once per word formed. At the end of the three minutes, players enumerate their solutions and any common words are crossed off. Each player sums up his remaining words, awarding himself 1 point for 3 or 4 letter words, 2 points for 5 letter words, 3 points for 6 letter words, 5 points for 7 letter words, and 11 points for words 8 letters or longer.
Prompting the User for the Boggle Board Layout
A user visiting the page must be able to enter the letters from her Boggle board in order to see the complete solutions list. To accomplish this, I used an HTML
<table>to generate a 4x4 grid. I then placed a TextBox Web control in each cell and set the TextBox's with to 30px (via CSS). I named the 16 TextBoxes
cXY, where X is their row position (0..3) and Y is their column position (0..3). For example, the TextBox in the upper left was named
c00, the one in the upper right corner
c03, and the one in the bottom right corner
The following declarative markup illusrates this naming convention.
In addition to the 16 TextBox controls, the page contains three Button Web controls that the user may click to solve the currently entered board, generate a random board, or clear the board. There's also a DropDownList control from which the user can choose the minimum number of letters each solution must contain. The rules of Boggle require all words must be at least 3 letters long; my family usually plays with a 4 letter word minimum. The DropDownList has the hard coded values 3, 4, 5, and 6.
onfocus- this event occurs whenever focus is moved to the TextBox (such as tabbing into it). For this event, I called the
select()method, which selects the text in the textbox (if any). The net effect is that if a user tabs into a textbox that has an existing letter, they do not have to delete the old letter by clicking Delete. Since it's selected, by entering the new letter the old one will be deleted.
onkeyup- this event fires after the user presses a key when focus is in the textbox. After entering a letter, I wanted the focus to immediately shift to the next TextBox so that the user could enter the board's layout by typing in the 16 letters (rather than having to type one letter, then hit Tab, then another letter, then hit Tab, and so on). The one gotcha here was that I had to be careful to only advance to the next textbox if the user typed in a letter. If they hit the Delete key, for instance, I would wanted to leave them in the textbox.
Attributescollection. In the
Page_Loadevent handler I enumerated the rows and columns and, for each TextBox, added the client-side event handlers. For the
onkeyupevent I needed to determine the
ClientIDof each TextBox control as well as the
ClientIDof the TextBox to send the user to after they had entered a letter. After the user entered a value for the last textbox, focus is moved to the
The client-side script functionality is added in the lines that start with
cMe.Attributes["eventName"]. For example, the
onkeyup event is assigned to the string
moveTo('moveToID', event);. The
Script.js file. It determines whether a letter key was pressed and, if so, it sets focus to the
element whose ID matches the moveToID.
Validating the Board
After the user has spelled out the layout of the board, but before our program starts its hunt for solutions, we need to ensure that the board specified by the user is valid. Each TextBox in the Boggle board must contain precisely one letter. This verification - along with the actual solving of the puzzle - is handled by a class I named
BoggleBoard. This class's constructor accepts as input the minimum length of a valid word along with the 16 letters that make up the board. The
BoggleBoardclass also has an
IsValid()method that returns a Boolean indicating if the board is valid. If it is not, the
ErrorMessageproperty contains a list of strings with a description for each problem cell.
After the user enters the board's layout and clicks the "Solve Puzzle" button, the following code executes:
If the board is invalid, the
ErrorMessage property is displayed through a call to
DisplayAlert, which is a custom method
Using a Custom Base Page Class for Your ASP.NET Pages' Code-Behind Classes; for
Your ASP.NET Web Pages.)
If the board is valid, the user is redirected back to the same page (
EnterBoard.aspx), but the querystring includes the board's ID and
the minimum length of each word. Rather than use the standard postback model, I decided to have my actions be querystring based so that a user
could bookmark or email the URL of a particularly interesting Boggle board. (This interest came upon a Boggle board I encountered where there were over
250 solutions of 4+ letter words!) The
BoardID property returns a string of the board's letters, from
the top left down to the bottom right. If the querystring includes a
BoardID value, the
Page_Load event handler populates the
16 TextBoxes with the corresponding values and then solves the puzzle.
Solve() method called from the
Page_Load event handler is a method defined in the code-behind class and is shown below. It creates a
BoggleBoard instance, poopulates it with the values in the 16 TextBoxes, and calls the
Solve() method, which does all the heavy lifting in discovering
the solutions. The
Solve() method returns a
BoggleWordList object, which contains a list of
solutions and their scores. If there is at least one solution, the number of solutions and the total score is displayed in the
Label and the set of solutions are displayed in the
WordList ListView control. If no solutions were found, the message "There were no solutions found" is displayed
WordList ListView renders a three-column HTML
<table>, placing the contents of each solution in a cell.
As you can see, the ListView's
ItemTemplate calls a helper method to generate its markup. The helper method is located in the
code-behind class and
DisplayTableCell; it is passed a
BoggleWord object and returns the HTML to render.
(This technique has been available since the first version of ASP.NET; for a primer on this technique, see
Customizing the Appearance of a DataGrid Column Value.)
DisplayTableCell method returns table cell markup (
<td>) with the word and score present. The word is displayed as
a hyperlink pointing to the dictionary.com entry and the table cell is assigned to one of the following CSS classes based on the word's score:
Score11. The different CSS classes impose different formatting rules.
Score2, for example, formats the table cell using a light yellow background color;
Score11 formats the cell with a pink background
color and bolds the cell's text.
For more information on the ListView control, consult Using ASP.NET 3.5's ListView and DataPager Controls.
At this point we have examined the Boggle solver's user interface. To recap, the user interface consists of a 4x4 grid of 16 TextBox Web controls, three Button Web controls, a DropDownList, a Label, and a ListView control. After entering a board and clicking the "Solve Puzzle" button, the page creates a
BoggleBoardclass instance and calls its
Solve()method (assuming the user's inputs were valid). The
Solve()method returns a
BoggleWordListobject that contains the set of solutions; these are then displayed in a ListView control.
In the next and final installment we will examine how the
BoggleBoard class finds the solutions. In the interim, feel free to try
out the Boggle solver live demo. The complete source code is available at the end of the article.