Duke Computer Science Shield

Assignment 1: Jotto

Due September 17th

Computer Science 201

The Big Picture

See The Medium Pictures and The Little Pictures for the specifics of what you're going to do and how to proceed. The Big Picture is to give you a bird's-eye view of what's going to happen. I recommend you read this page through, start to finish, before you snarf any code!

Jotto is a word-guessing logic game. One player (you, in our case) has a secret, five-letter word. (The game makes sense with words of more than five letters, but everybody always uses five.) The other player (the computer, in our case) is trying to guess what that word is. Play proceeds by having the computer guess a word. The human then indicates how many letters that word has in common with the secret word. The definition of "has in common" is a bit tricky; see the little pictures. The guesser uses this information to inform their next guess, and the game continues.

The Jotto assignment has three specific objectives:

  1. Building a deeper understanding of how objects interact.
  2. Introducing you to the Model/View design we'll be using in many of our assignments.
  3. Having you think about instance variables and helper methods. What information does my Jotto player need to store? What methods might I write to make that easier?

There are several different versions of Jotto available to play online; we recommend this one. It doesn't use exactly the same rules we're going to implement (it doesn't allow repeated letters), but it should give you an idea of how play will progress. There's also an example session below.

The Medium Pictures

How Jotto Works

In the Jotto assignment you will implement, the computer does the guessing, and you have the secret word. The computer will make a guess, you will tell it how many letters it has in common, and then the computer will guess again. You are going to implement a fairly simple guessing strategy: "Guess a random word." However, not completely random. Instead, you will have the computer guess a random word from the set of words that could still be the secret word. For example, if the computer guesses "fruit" and the player responds that there are two letters in common with the secret word, the computer can remove "ghost", "ruins", "tires", and lots of other words from the list of possibly words since these words have, respectively, one, three, and three letters in common with "fruit" and thus cannot be the secret word. The computer would leave "flips", "track", and others in the list since these have two letters in common with fruit and could possibly be the user's secret word. This strategy, while not perfect, is remarkably good at finding secret words in just a few guesses!

Letters in Common
The Jotto definition of "letters in common" is tricky. From above, we noted that "fruit" has two letters in common with "flips" ('f' and 'i') and two in common with "track" ('r' and 't'). It has one in common with "ghost" ('t'), three in common with "ruins" ('r', 'u', and 'i'), and three in common with "tires" ('t', 'i', and 'r'). So far, so good. However, consider what happens when you have a word with repeated letters: "radii", for example. The overlap between "radii" and "gifts" is one: the letter i. However, the overlap between "radii" and "ionic" is two: the letter i twice. In short, count matters: it's more complicated than "both words contain the character 'i'". Similarly, "gaffe" and "gaffs" have an overlap of four ('g', 'a', 'f', 'f' again) and "geese" and "genes" have an overlap of four ('g', 'e', 'e' again, and 's'). Finally, "radii" and "belli" have an overlap of one; just a single 'i'.

I find it helpful to think about it this way: each specific letter in the guess has the opportunity to match a letter in the secret word. If a match exists, remove that specific letter from the guess, and its match from the secret word; now both have length 4. Repeat this process until no more matches exist, and count the number of removals you did. (This may also suggest a convenient way to implement this, hint hint.) Note also that order matters: if the word is "easel" and the player guesses "lease", they have not won the game (although they did get an overlap of five).

Part of this assignment is to implement a method to compute the letters in common of two Strings; see the little pictures for more detail.

A Sample Run
Here's a sample run of a completed Jotto assignment, with screenshots. Note that the provided skeleton code will produce some of this, but not all. Try running it seeing what happens.

Not shown: File -> Open -> kwords5.txt If you forget this step, all kinds of things will break.
I start a new game.
My secret word is radii. Here, the computer has guessed "doted" (one letter in common), "comas", (one letter in common), and so on. Note that the computer is guessing randomly; the next time I play, even if I choose the same random word, it will guess different things.
The computer has guessed my word. Note that I entered 6, not 5, even though my word has only five letters in common with itself. Because the code you will write expects the player to type an integer, we need to pick a special integer to mean "You guessed right!". Five won't work because order matters. Note the use of a modal dialog box!

This assignment will be graded entirely on how well your Jotto program works; does it play Jotto? Does it correctly implement the guessing strategy? Does it correctly only guess words that might be your secret word?

The Little Pictures

At this point, you should have a pretty good bird's-eye view of Assignment 1. The Little Pictures explain the steps you're going to take to complete it and how it will be graded.

You'll be submitting two things: your implementation of Jotto, and a README file. Your README should be in .txt format.

Step 0:
Pause to collect your thoughts. Lament that there is no Led Zeppelin song appropriate to Jotto. Record this lamentation in your README.

Step 1: Code
Snarf the code! You'll find three pieces of code provided:

  1. Jotto.java just starts everything up. This is the code you run as a program to make everything go. You won't need to modify this.
  2. JottoViewer.java implements a graphical user interface (or "GUI", pronounced "gooey") for Jotto; you've already seen it, in the screenshots above. You don't need to modify this file, either.
  3. JottoModel.java is where you'll be doing all of your work. You should read through the many comments within.

Step 2: Model-View
Step 2 isn't actually something you turn in; it's just you reading this paragraph. The code for Jotto follows a pattern that you will see several times in this course: a "Model-View" design. Here, "Model" means "data and logic" and "View" means "graphical interface". The idea is to separate the internal Jotto logic (picking a word to guess, computing the common count, etc.) from the logic of actually putting it all on the screen. That way, you don't need to worry about how the GUI is created (it's messy!); instead, you just give it high-level instructions like "Show a dialog box that indicates that the game is over." The View takes care of presenting that to the user. On the other hand, the Model stores the computer's current Jotto game state, and implements the logic to actually decide what the next guess is. You should read the comments in JottoModel.java in detail; they describe what the various methods do, which ones you need to modify, and which ones you can leave alone.

Step 3: JottoModel.java
Like Step 2, this isn't something you turn in, it's just something you read. Read JottoModel.java from top to bottom; there are extensive comments about how it works, what you'll need to do, and how you might go about doing it. Of particular note are the various places marked TODO: those are places you're going to write code. (Note that large parts of the file needn't be modified at all.)

Step 4: Implement Jotto
Per the goals, there are two hard parts to this assignment: code interaction, and computing the common count. We suggest writing a helper method to compute the common count; we've provided an incomplete version (with extensive hints) as commonCount in JottoModel.

On the code interaction front, you'll need to handle the several ways the game can end: the guesser can win, the guesser can lose (if it takes more than 15 guesses) and the guesser can give up (which will happen if there are absolutely no words that are consistent with the answers given by the human player; this probably means the human has messed up a common count somewhere). There are two different ways to present information to the player: using the Model's showModalMessage method, which brings up a dialog box that you have to close before you can do anything else, and the Model's messageViews method, which fills in the text box at the bottom of the GUI. Which one makes the most sense in each case is up to you. In the last screenshot, above, the "Great! I got your word" text is from showModalMessage, and the "I will guess your word" is from messageViews.

One thing you don't have to do is deal with restarting the game. Once it ends (by the guesser winning, the guesser hitting 15 guesses, or the guesser concluding that the human has been lying), you can assume that the program will be quit and restarted before it's run again.

A common mistake: people often forget to remove the guessed word from the set of possible words. If the secret word is "space", and I guess "paces", the overlap count is 5. If I'm not careful, "paces" will remain in my list of possible words, and I'll foolishly guess "paces" again. Be sure to handle this case!

Grading
The entire assignment is graded on a ten-point scale. Correctly implementing the word-guessing strategy is worth three points. Correct interaction with the View is worth three points: in particular, your code should know when it has won (and announce that). It should also be able to handle the case of a dishonest human player: what happens if the human provides inconsistent counts? You should be able to detect this, and present a meaningful message. (The same thing could happen if the player chooses a word that's not in kwords5.txt, the list of legal words.) Your README is worth two points, and two points are awarded for code style. (See below for details on the README and style).

Submission
Submit your code and README using Ambient or websubmit. Please make sure you submit your entire assignment each time you submit; this makes life much easier for the graders. You can submit as many times as you'd like; we'll take the last one.

Extra Credit
For extra credit, re-examine the computer's guessing strategy. Can you do better than picking a random valid word? There's a menu option for "Smarter AI" in the Jotto program; selecting this calls the playSmarter method in the Jotto Model. To implement a smarter Jotto, use that method to set an instance variable, and then have the rest of the code check that instance variable and do something smarter if it's set. To make sure that we grade your extra credit, be sure to point out that you've implemented it in your README!

The README
Like every assignment (but not APTs), you should include a README text file in your submission. It should include:

  • Your name.
  • When you started and finished the assignment, and your best estimate of how long it took.
  • The credits: who helped you. Recalling the collaboration policy from the syllabus, be sure to give credit where credit is due. Also, take credit where it's due: if you helped someone else, say so! If you didn't talk to anybody about this assignment, say that.
  • Anything we've specifically said should be included in the README.
  • Any feedback you have about the assignment itself; we're always trying to make these assignments better. If you'd rather that feedback be anonymous, there's a link for that on the course page.
You can add a text file to your code using File -> New -> Untitled Text File in Eclipse.

Code Style
Fact: code is hard to read.
How you lay out your code, and your program, make a big difference in how easy it is to understand. There are (at least!) four people who need to understand your code: you (while writing it), anybody you ask for help, your grader, and you (six months from now, when you look at it to figure out how you did something). While the following rules are not set in stone, they provide a good place to start:

  • Think about how your code is going to be organized before you've written it. Good design matters!
  • Give your classes, variables, and methods descriptive names. Naming your variables foo and bar doesn't say much; xPosition and yPosition are much better.
  • Use Java's conventions on naming. ClassesAreNamedLikeThis: words are run together, and each word is capitalized. Similarly, methodsAreNamedLikeThis: words run together, and all but the first word are capitalized. Variables are named like methods.
  • Indent your code properly. Roughly speaking, this means "everything inside a curly brace gets indented one extra level." See the code we provide for how this should look. To make this easy, Eclipse can do it for you: select your code with the mouse, and then do Source -> Correct Indentation.
  • Don't let your lines get too long. Although Java doesn't care how long your lines are, long lines are much harder to read. The closest thing there is to a universal standard is 80 characters. Eclipse makes this easy, too: in Preferences -> Text Editors, turn on "Print Margin" and set it to 80. That will add a vertical line at the 80-character mark.

Remember: easy-to-understand code makes your grader happy. Happy graders are friendly graders!