Csci 210 Lab 5 & 6: Boggle
(Laura Toma adapted from Eric Chown)
In this assignment, you will implement the back-end logic for a
graphical version of the popular board game Boggle. Specifically, you
will design and implement the algorithmes necessary for a computer
player to play against a human opponent. If you get everything right,
the computer player should almost always "win" the game by a large
margin, but it will be fun to play anyway.
The main focus of this assignment is designing operations that will
efficiently find words that appear in a Boggle board using
recursion. Because your focus will be on the back-end logic, you will
be provided with a graphical display program, BoggleGUI. This
program knows how to generate and render a random Boggle board,
interact with a human player, and display results of the game. It will
use your code to verify input from the human player, and to obtain the
computer player's results.
The program will be due in two parts. In the first part, due next
week, you are to write a method to check whether or not words are on
the board or not. In the second part, due in two weeks, you are to be
able to find all possible words on the board.
Get the Boggle files from here.
A little background on Boggle
The game of Boggle uses a board which is a 4-by-4 grid on which you
randomly shake and distribute 16 dice. The 6-sided dice have letters
rather than dots on the faces, creating a grid of letters in which you
find words. In the original version, the players all start together
and write down all of the words they can find by tracing paths through
neighboring dice faces on the board. Two dice are neighbors if they
are next to each other horizontally, vertically, or diagonally (So
there are up to eight neighbors of a die; dice on the edges of the
grid have fewer neighbors). A die can only be used once in a word,
and a word must be at least 3 letters long. At the end of a three
minute session, all players stop recording words. Words found by more
than one player are then removed from the players' lists and the
players receive points equal to the number of letters beyond the
minimum word length found in their remaining words.
In the computer version of the game, the human player gets to go
first. (Don't worry, the computer player will still trounce you.) The
player proceeds to enter in the text area at the bottom of the window,
one at a time, each word that she finds in the game board. A valid
word must meet four requirements:
All valid words entered by the player are highlighted graphically on
the board display. The computer player determines the validity of the
words, but we assume it can be trusted to do so fairly.
- it must contain at least the minimum number of letters;
- the word must not already have been entered by the player;
- the word can be formed from the letters showing on the board following in order a path through neighboring
dice without using the same die twice; and
- the word must exist in
the official lexicon of words.
Unlike the original version, there is no time limit here. Instead,
the player indicates that she is through entering words by hitting a
lone extra carriage return, as if entering an empty word. At this
point, the computer gets to take its turn. The computer searches
through the board looking for all the valid words it can find. The
computer typically beats the human player mercilessly, but the player
is free to try again by starting a new game. Scoring is as for the
original version of the game, except that words are not removed from
the players' lists (if they were, the human player would never have
any words left!).
The computer version that I have given you has been handicapped in
a few ways (e.g. it doesn't bother with shorter words). Your final
version shouldn't be.
The structure of the implementation
There are two java files: BoggleGUI.java---the front-end
graphical interface, and BogglePlayer.java---used by
BoggleGUI to execute the required back-end logic.
BoggleGUI.java is complete and you do not need to modify it.
You will only be editing BogglePlayer.java.
In order that you might focus on the most interesting part of the
assignment (involving recursion) I have written some of the methods
for you, as follows.
- buildLexicon: this method takes as argument a
Set containing the list of words specifying the official
lexicon to be used for the game (a set is a collection of elements
that does not allow duplicates; much like a Vector; check out the
Java doc on Sets). Each word in the Set will be a String consisting
of lowercase letters a-z only. This function loads the words into an
efficient data structure that can be used internally as needed by
- setBoard: this method takes in an array of Strings
of length N^2 specifying the layout of dice on the N-by-N board. (In
official standard Boggle N is 4; but your BogglePlayer should work
for any square board.) The elements of the array specify the letters
found on dice going from left to right, and top to bottom of the
board. (So the element indexed 0 is a String containing the
letter(s) on the die at the upper left corner; on a 4x4 board, the
element indexed 3 is the top right letter, and index 15 gives you
the letter at the bottom right.) Each String may be upper or lower
case, and may contain one or more letters; for purposes of finding
words on the board, they should be considered lowercase. (In
official Boggle, these Strings will contain one character only,
except for the double letter die face "Qu"; but your BogglePlayer
should work correctly for arbitrary strings.)
- isInLexicon: this function takes in a String and
determines whether the String can be found in the lexicon specified by
the most recent call to buildLexicon(). The function returns true if
the word is in the lexicon and false if it is not in the lexicon. If
buildLexicon() has not yet been called, the behavior of this
method is undefined.
What you need to implement
Although you will probably implement other methods too, your
BogglePlayer class must implement methods with these exact signatures:
public Vector isOnBoard(String wordToCheck)
public Vector getAllValidWords(int minimumWordLength)
You may also find useful to change getCustomBoard. This is a
function that will aid you immensely in debugging if you are wise
enough to use it. This function will be called by the GUI
application when a choice of "custom", non-randomly selected board
layout is requested. This function should return an array of 16
Strings representing the desired dice layout based on the usual
index from 0 to 15. The idea here is that you can work on repeatable
boards. If you have a bug you can attack it relentlessly.
- isOnBoard: this function takes as argument a String
and determines whether the String can be found in the board
specified by the most recent call to setBoard(). The return
type of this function is a Vector object containing Integer
elements. If it is possible to find the word in the current board,
the function returns a Vector of Integers representing the locations
of the dice used to form the word, in order---where a location is a
one-dimensional offset in the range 0..N^2-1, obtained from
(row,col) using the reverse transformation in
setBoard(). If is is NOT possible to form the word, the
function returns null. If setBoard() has not yet been
called, the behavior of this method is undefined.
- getAllValidWords: this function returns, as a sorted
Vector of Strings, all the words that
If either buildLexicon() or setBoard() has not yet
been called, this method should return null.
- are of at least the given minimum length;
- are in the lexicon specified by the most recent call to
- can be found by following a simple path on the board specified by the most recent call to setBoard(); and
- were not found by previous calls to
Hints and Suggestions
In a project of this complexity, it is important that you get an early
start and work consistently toward your goal. To be sure that you are
making progress, it also helps to divide up the work into manageable
pieces, each of which has identifiable milestones. Here is a suggested
plan of attack that breaks the problem down into phases:
- Read BogglePlayer.java and understand the overall
structure of the game and the methods that have already been
- Implement isOnBoard: Remember that a valid word
must correspond to a simple path according to the neighborhood
relation on the dice. You should search the board recursively, trying
to find a legal formation of the user's word. This recursion can be
made what you might call a "fail-fast" recursion: as soon as you
realize you can't form the word along a path, you can immediately
backtrack or move on to the next untried path start point. Reject any
word that cannot be formed from the letters currently on the board.
- Because it is so important I'm going to make the last point over
again, but in a different way. You're used to basic recursion - make a
recursive call, collect the results and pass them on. The recursion in
this lab is more subtle. The key thing is that when you make your
recursive calls you need to consider the results. For example, when
looking for a word, if your recursive call succeeds then you are
done. Pass the happy results along and stop making recursive
calls. However, if it didn't work then you need to keep
searching. Understanding this simple aspect of the assignment will
save you countless hours of frustrating debugging.
- Think about your base cases. You should essentially have two -
one for the case when you hit a dead end, and another for the case
that you have found the whole word.
- Think about your recursive case. Imagine you are checking if the
word "boggle" is on the board. Your recursive call might target a
square to check if it is the "b" and if that is true then it could
call itself looking for the rest of the word. The call to itself
would probably consist of 8 different calls representing the eight
neighbors of the original square. Don't forget that an individual
square cannot be used more than once in a boggle word. Therefore you
must do something to mark that a square has already been used. Your
experience with blobCount code should help.
- A good way to write this is by having the isOnBoard call
another method which is recursive. Your isOnBoard method can help by
only calling the recursive method when it has identified a good
candidate for the word. For example, if you are looking for "computer"
it would only call the recursive method in the locations where there
- Implement getAllValidWords: Now it's time to implement
the world-class computer player. The computer should easily trounce a
human player; it can very quickly learn more words than any human
knows, and it can very quickly and perfectly check them against the
board. The trick is to program the machine to do that. Your program
must also do this recursively. Part of the problem is to have a good
word list to start with (the file "dict1.txt" contains such a list and
is provided in the same folder as the Java files, though you may want
to test on a shorter list to start).
The hard part is implementing data structures and algorithms to make
the computer's search work efficiently. It is easy to get lost in the
recursive decomposition and you should think carefully about how to
proceed. Bear in mind that you can significantly speed up this
algorithm using "pruning" by recognizing when you are going down a
dead end, abandoning it, and backtracking to where there are still
For example, if you have built a path starting with "zx", you could
use an isPrefix function implemented on your lexicon to
determine that there are no words in English beginning with that
prefix. If you miss this optimization, you may find yourself taking
long coffee breaks while the computer is busy checking out
non-existent words like "zxgub" and "zxaep", etc.
Alternatively, if you have traversed your lexicon starting with "ab"
and your game board representation is able to tell you there are no
paths on the board starting with those letters, you know you don't
have to even consider any lexicon words that have "ab" as prefix.
Please note: one implementation of getAllValidWords is to
simply run through the dictionary and repeatedly call
isOnBoard. This is not a valid solution for this lab (you
will get 0 points). Your solution should follow the strategy outlined
The file BoggleGUI.java is a GUI application that you can
use as a nice interface when testing some things about your Boggle
player. Note however that your BogglePlayer class must have the
required functionality without the BoggleGUI code
present. Also keep in mind that BoggleGUI only knows about 4x4 Boggle
boards, and official Boggle dice, while your BogglePlayer needs to be
able to handle any square board, and any Strings on the die faces.
The file BoggleGUI.jar is a partially
correct solution to the assignment. (It has bugs, and as a player, it
it violates the spec by never finding words shorter than 5 or longer
than 8 letters, but it lets you find them -- just to give you a
The BoggleGUI program comes with a main method that will set up the
game. You can also pass this method parameters when you run it to set
a word file and various game parameters such as minimum word
length. Be careful to keep your word file in the same folder as your
project because that is where BlueJ will look for it.
Don't forget that the BoggleGUI is only one possible implementation
of a Boggle-style game. Your code must be general. E.g. a "B" program
would be able to handle standard boggle dice, but an "A" program
should be able to handle any dice. Along those lines, I will use my
own program to test your program, so if you alter the BoggleGUI it
won't be used when I'm testing your program.
Be aware that where your program runs will make a significant
difference in the speed of the program. If you run off the network,
for example, your program might take several minutes to run where it
might only take a second or two if run off the desktop.
If you test your program in the early stages without using a small
lexicon (e.g. 10 words) and a custom board then you are in for
trouble. This is also a good time to use BlueJ's ability to run
methods individually effectively.
It is virtually essential that you master the debugger on this
project. The second part in particular can get very complicated. Once
you have your program up and running I will expect that anytime you
ask me a question you'll already have the debugger up and will just
want me to clarify something or provide a suggestion.
Handing in: As always this is due at the start of the next
lab and you should hand in a hard copy in addition to emailing me the
java file. Email me only BogglePlayer.java, as an
attachment; do not zip or tar. On the hard-copy sign that you
followed the honor code for the class.
Last modified: Wed Oct 17 11:39:41 EDT 2007