This term's Advanced Java project will be a networked Boggle game. Although Boggle is a very simple game, the implementation is actually rather involved. Over the next few weeks we will build out the various components of our game, and then we will begin to draw them all together into a single unified application.
Most of the game Boggle centers around lists of words, so we will need a solid utility class for managing word lists. This week's focus is on building a "word list" class that can store the dictionary of valid words, and that can be used to store the words that players find as they play. (You might call this class WordList, for example.)
Here is a specification of what your word-list class must provide:
Implement your word-list class to use a java.util.Set implementation that is fast for lookups and membership-tests. It is not necessary to keep these word-lists in sorted order for the majority of their operations.
Make sure that your implementation properly uses Java generics.
Write an "add word" method to add new words to the word-list. Here are some additional specifications for this functionality:
(Hint: You should put this "preprocess word" functionality into a helper method.)
Provide another constructor that takes a java.io.File object, and reads in all words in the specified file. Each word will appear on its own line in the input file. Take a look at java.io.BufferedReader for an easy way to retrieve the input line-by-line. Each word should be preprocessed as it is added to the list. (Hint: reuse your work!)
This constructor should throw a java.io.IOException if the file cannot be opened, or some other issue occurs during file-load.
Write a method to add another word-list into a word-list. For example, if you have two word-lists a and b, then a.addWordList(b) would modify a so that it contains words that appear in both a and b.
Because the other word-list will have properly processed each word, you don't have to worry about preprocessing words as you did for the "add word" method.
(Hint: you can implement this method very easily by using the appropriate Set method, and by accessing the passed-in WordList's private members. Because this method is implemented on the WordList class, the method can access the private members of any WordList object.)
Implement a method void WordList.subtract(WordList), that computes the set-difference between two WordList objects. For example, if you have two word-lists a and b, then a.subtract(b) would modify a so that it only contains words that do not also appear in b.
This week we will only do some very basic testing of our word lists. Create a simple test class for your word list, that does the following:
Make sure that your word-list and your test class both compile. Then, try your program with this file. (Uncompress it first! On Linux: unzip sowpods.zip) You should get 267,751 words in total.
Anytime you begin to work on a project with more than a few classes, it becomes really helpful to have access to API documentation for your project. Creating this documentation by hand would be prohibitively expensive, but fortunately, Sun provides us a very helpful tool called javadoc, which can generate all manner of Java API documentation from our source code.
Fully document your word-list class using Javadoc-style comments and annotations. This should include:
Once you have documented your class, generate the Javadoc API documentation with this command:
javadoc -d docs *.java(Or, you could just specify WordList.java instead of *.java; it's not a big deal this week.)
The -d docs argument tells javadoc to put the generated files into the ./docs directory; javadoc will actually create this directory for you if it doesn't already exist.
Then, you can point a web-browser to the index.html file in your docs directory to make sure your documentation is correct and complete. (If you are on the CS cluster and you have put your work into the ~/cs11/advjava/lab1 directory, your URL would be "file:///home/username/cs11/advjava/lab1/docs/index.html", with your username substituted into the URL.)
That is all that's required for this week's assignment. When you are finished, submit your source files (but not your .class files, generated javadocs, or the word-list!) on csman.
If you want to make your word-list code more sophisticated, you can try this task for "extra credit" (i.e. your own edification, although I do tend to grade more leniently when people do extra-credit tasks).
You may have noticed that our dictionary file is 687KB when compressed, but it is 2.9MB when uncompressed. Plain text compresses quite well. So, extend your word-list code with the ability to load from a ZIP file and/or a gzipped file.
The first thing you would do is to add a constructor that takes an InputStream. This way you can load your word-list from a java.util.zip.GZIPInputStream or a java.util.zip.ZipInputStream without any changes to the word-list code itself.
Next, you could add a static method to your word-list class that loads a word-list from one of these archive types. For example, you could create functions like this:
// Load a word-list from a gzip-compressed input file. public static WordList loadFromGZipFile(File gzipFile) throws IOException // Load a word-list from a zip-compressed input file. public static WordList loadFromZipFile(File zipFile, String zipEntryName) throws IOException
gzip-compressed files only contain a single file, so this would be the simpler function to implement. In constrast, zip-files may contain multiple entries, so you would need the ability to specify the name of the entry within the zip file as well.
(Alternatively, your zip-load method could require the .zip file to only contain ONE entry, and throw some kind of exception if this is not the case.)
Make sure to document the details of how your load-function(s) work! Use javadoc-style comments, as usual.