Adding a RESTful Service to My Boggle Solver

Published 11 September 10 02:47 AM | Scott Mitchell

This blog post has been deprecated. Please see Updating My Online Boggle Solver Using jQuery Templates and WCF for an updated discussion on the solver service, the data it returns, and how to call it from a web page.

My immediate and extended family enjoys playing games, and one of our 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 created a Boggle solver web application (back in 2008) that prompts a user for the letters in the Boggle board and then recursively explores the board to locate (and display) all available solutions. This Boggle solver is available online - fuzzylogicinc.net/Boggle. My family uses it every time we get together and play Boggle. For more information on how it works and to get your hands on the code, check out my article, Creating an Online Boggle Solver.

Recently, I’ve been working on some projects that have involved creating RESTful web services using WCF. Being Friday, I decided to have a little fun and add a RESTful interface to the Boggle solver. This was actually quite easy to do and took all of 5 minutes.

Creating the Boggle Solver Service

I started by adding a new item to my website of type WCF Service, naming it Solver.svc. This created three files:

  • Solver.scr
  • ISolver.cs
  • Solver.cs

In the contract (ISolver.cs) I added a single method, Solve, that accepts two inputs: a string representing the board and a string indicating the minimum number of letters for a word to be considered a solution. (Boggle rules allow for words of three letters or more, but house rules only count words that are four letters or longer.) I then used the WebGet attribute to indicate that the board and length input parameters would be specified via the querystring fields BoardID and Length, and that the resulting output should be formatted as JSON.

[ServiceContract]
public interface ISolver
{
    [OperationContract]
    [WebGet(UriTemplate = "?BoardID={board}&Length={length}", ResponseFormat=WebMessageFormat.Json)]
    BoggleWordDTO[] Solve(string board, string length);
}

Note that the Solve method returns an array of BoggleWordDTO objects. This is a new class I created to represent the data to transmit from the service. This class has two properties:

  • Word – a string value that represents a word found in the Boggle board, and
  • Score – the score for that solution. According to the official rules, three and four letter words are worth 1 point, five letter words are worth 2, six letter words worth 3, seven letter words worth 5, and eight letter words and longer worth 11.

The Solve method implementation (Solver.cs) is pretty straightforward. It starts with a bit of error checking to ensure that the passed in board and letter information is kosher. Next, it creates a BoggleBoard object, specifying the minimum number of letters for a solution and the board contents. Then the BoggleBoard object’s Solve method is invoked, which performs the recursion and computes the set of solutions (as an object of type BoggleWordList). The solutions are then converted into an array of BoggleWordDTO objects, which is then returned to the client.

public BoggleWordDTO[] Solve(string board, string length)
{
    ...

    // Create the BoggleBoard
    BoggleBoard bb = new BoggleBoard(
                        letters,
                        board[0].ToString(), ..., board[15].ToString()
                    );

    // Solve the Boggle board
    var solutions = bb.Solve();

    // Populate and return an array of BoggleWordDTO objects
    return solutions
                .Select(s => new BoggleWordDTO()
                {
                    Word = s.Word,
                        Score = s.Score
                })
                .ToArray();
}

Because the service is configured to return the data using JSON, the results are serialized into a JSON array.

In addition to creating the Solver-related files and writing the code I noted, I also had to add <system.serviceModel> configuration to Web.config to permit HTTP access to the service and to enable ASP.NET compatibility. The reason I had to enable ASP.NET compatibility is because the dictionary used by the solver is a text file stored on disk, and the solver gets the path to that text file using Server.MapPath (namely, HttpContext.Current.Server.MapPath(“…”)). Without ASP.NET compatibility, HttpContext.Current is null when the service attempts to solve and then the call to Server.MapPath blows up. Also, I had to specify the Factory attribute in the <%@ ServiceHost %> directive of the Solver.svc file.

[UPDATE: 2010-09-10] Ben Amada posted a helpful comment pointing me to the existence of the HostingEnvironment.MapPath method, which does the same work as Server.MapPath but doesn’t require an HttpContext object. I updated this code accordingly. I also updated the code that cached the dictionary in memory, replacing the use of HttpContext.Current.Cache with HttpRuntime.Cache, which I probably should have been using all along. The code has been updated. Thanks, Ben!

Using the Boggle Solver Service

To use the service, just point your browser (or your code/script) to:  http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=board&Length=length. The board value should be entered as a string of the characters in the Boggle board, starting from the upper left corner and reading to the right and down. For example, if you had the board:

r e i b
t m f w
i r a e
r h s t 

You would use a board value of reibtmfwiraerhst. letter should be a number between 3 and 6, inclusive.

So, to find all solutions to the above board that are four or more letters, you’d visit: http://fuzzylogicinc.net/Boggle/Solver.svc?BoardID=reibtmfwiraerhst&Length=4

Doing so would return the following (abbreviated) JSON:

[{"Score":1,"Word":"amir"},{"Score":2,"Word":"amirs"},{"Score":1,"Word":"awes"},{"Score":1,"Word":"bier"},{"Score":1,"Word":"ears"},{"Score":1,"Word":"east"},...]

The above JSON represents an array of objects, where each object has two properties, Score and Word.

So how can this service be used? Well, with a bit of JavaScript you can call the service from a browser and display the results dynamically. I’ve included a rudimentary example in the download (which you can find at the end of this blog post) that prompts the user to enter the 16 characters for the board and the minimum number of letters. It then uses jQuery’s getJSON function to make a call to the service and get the data back. The JSON array is then enumerated and a series of list items are constructed, showing each solution in a bulleted list.

Here is the web page when you visit it and enter a boggle board and the minimum number of letters (but before you click the “Find All Words!” button.

BoggleBoard2

Clicking the “Find All Words!” button executes the following jQuery script:

$.getJSON(
    "Solver.svc",
    {
        "BoardID": $("#board").val(),
        "Length": $("#length").val()
    },
    function (words) {
        var output = "No solutions exists!";

        if (words.length > 0) {
            output = "<h2>" + words.length + " Solutions!</h2><ul>";

            var score = 0;

            $.each(words, function (index, word) {
                score += word.Score;
                output += "<li>" + word.Word + " (" + word.Score + " points)</li>";
            });

            output += "</ul><p>Total score = " + score + " points!</p>";
        }

        $("#solutions").html(output);
    }
);

Note that the above script calls the Solver.svc service passing in the BoardID and Length querystring parameters. The textbox where the user enters the board has an id of board while the minimum letter drop-down list has an id of length. The function defined in the call is what is executed when the result comes back successfully. Here, the jQuery each function is used to enumerate the array and build up a string of HTML in a variable named output that produces a bulleted list of solutions. The total number of solutions and total number of points is also included in output. Finally, the contents of output are dumped to a <div> on the page with an id of solutions.

Here’s the page after clicking the “Find All Words!” button. Nothing fancy, of course, and not nearly as useful or eye-pleasing as the website’s results page, but it does illustrate one way you can use the Boggle Solver.svc service.

BoggleBoard3

Download the Code!

You can download the complete Boggle solver engine, web application, and WCF RESTful service from http://aspnet.4guysfromrolla.com/code/BoggleSolver.zip.

Happy Programming, and Happy Boggling!

Comments

No Comments

Archives

My Books

  • Teach Yourself ASP.NET 4 in 24 Hours
  • Teach Yourself ASP.NET 3.5 in 24 Hours
  • Teach Yourself ASP.NET 2.0 in 24 Hours
  • ASP.NET Data Web Controls Kick Start
  • ASP.NET: Tips, Tutorials, and Code
  • Designing Active Server Pages
  • Teach Yourself Active Server Pages 3.0 in 21 Days

I am a Microsoft MVP for ASP.NET.

I am an ASPInsider.