Assignment 3
Assignment 3
Assignment #3 — Hangman
Due: 11AM PST on Thursday, July 20th
This assignment may be done in pairs (which is optional, not required)
Based on handouts by Mehran Sahami, Eric Roberts and Marty Stepp
For this assignment, your mission is to write a program that plays the game of Hangman.
As an assignment, Hangman will give you practice with Strings, file processing,
parameters, and return values, while also in itself being a fun console-based game to play.
You should implement all required parts of the assignment in the file Hangman.java.
Note that this assignment may be done in pairs, or may be done individually. You may
only pair up with someone in the same section time and location. If you would like to
work with a partner but don’t have one, you can try to meet one in your section. If you
work as a pair, comment both members’ names on top of every .java file. Only one of
you should submit the assignment; do not turn in two copies.
Note that you should limit yourself to the material covered up until the release of this
assignment (through lecture on Wednesday, July 12th). You should not use any other
material (in particular private instance variables). You may, however, use what we
learn about graphics programs for optional extensions to this assignment. If you have any
questions about what is ok to use, feel free to ask.
Comparing Output: each of your programs must exactly match the specified output. To
check your output, use the Output Comparison tool; see the Assignment 2 handout for more
information. You may also directly view sample output files by opening them in Eclipse
from inside the output/ folder, or via the Assignment 3 page of the course website.
On each turn, the program shows a hint about the secret word. The hint is initially a row
of dashes, one for each letter in the secret word. For example, if the secret word is
"HELLO", the hint is "-----". If the player's guess is a letter that appears in the secret
word, the hint is updated so that all instances of that letter are shown in their correct
positions. For example, if the secret word is "SHELLS" and the player guesses "H", the
hint becomes "-H----". If the player then guesses "L", the hint becomes "-H-LL-".
–2–
As in past assignments, we ask you to break apart the overall task into methods; however,
since we are now using parameters and return values and writing a much larger program,
it is difficult for a new programmer to come up with good decomposition. Therefore, we
are going to tell you what methods you should have (and require these methods) in your
program. You may create additional methods if you like, but you must have the methods
shown below with exactly these names and exactly these parameters (no more, no less) and
return types. Do not change the method definitions in any way, or you will be
substantially penalized. The reason we are requiring these methods is to provide practice
using parameters and return values to communicate between these methods.
Eventually, your playOneGame method must call the methods above to help it solve the
overall task of playing the game. Since this is a challenging program, we suggest that you
develop it in stages. The following pages outline a series of stages that we strongly
recommend you follow in order.
–3–
CS 106A Hangman!
I will think of a random word.
You'll try to guess its letters.
Every time you guess a letter
that isn't in my word, a new body
part of the hanging man appears.
Guess correctly to avoid the gallows!
You should also modify your program’s run method to simply call playOneGame once,
for now. Make the secret word always be a particular word of your choice, such as
"PROGRAMMER".
public void run() {
playOneGame("PROGRAMMER");
}
For now, don’t worry about playing multiple games or displaying statistics. You will need
code to do tasks such as the following:
• Display a “hint” about the secret word on each turn; initially a string of dashes
• Ask the user to type a valid guess
• Figure out if a guess is correct (in secret word) or incorrect (not in secret word)
• Keep track of the number of guesses remaining
• Determine when the game has ended (when the user guesses all letters in the secret
word, or runs out of guesses)
–4–
Note that if you wrote the entirety of the code for playing one game in playOneGame,
the method would be very long and poorly decomposed. To help you break apart this task,
we require that you write and use the following additional methods. The idea is that your
playOneGame method should call these methods as part of its overall task.
Here are some example calls to this method, and their expected results:
• createHint("STARTED", "ETOSX") should return "ST--TE-"
• createHint("PROGRAMMER", "RMPAO") should return "PRO-RAMM-R"
• createHint("COMPUTER", "") should return "--------"
The following is a log of console output of one call of this method when passed the guessed
letters string "TOSX". The call below would ultimately return the character 'K' in
uppercase, even though the user typed 'k'. Remember to match this console output
format exactly. (User input appears bold and blue).
Remember that you are not limited to having only the above methods to help you
implement this functionality, so if you want more decomposition you are welcome to add
more methods. But you must have at least the methods shown above, with exactly those
definitions. Your playOneGame code must also call these methods to help it solve the
overall task of playing a single game.
display8.txt: display7.txt:
+------------+ +------------+ _________
| | | | / \
| | _______ | Why me? |
| | / o o \ / \_________/
| | | . | /
| | | ___ |
| | \_______/
| | |
| |
| |
| |
---+--- ---+---
####### #######
You should also modify your playOneGame method so that on each turn, your program
calls displayHangman to print the current game state, right before displaying the secret
word hint, number of guesses remaining, and other game state. See the expected output
logs in the output/ folder of the starter project, or on the Assignment 3 webpage.
Secondary "canvas" console: The provided starter files come with a split-screen with a
second console to the right of the main console. You can optionally choose to print your
Hangman display to this secondary console instead of the main console while having the
rest of the game output in the primary console, so that it is always visible on the screen
during the game. To do so, use the command canvas.println rather than just
println. You can also clear the canvas just before printing each file's contents.
File format: Each input file uses exactly the following format dict.txt:
(shown at right): the first line contains a single positive integer
n that is the number of words in the file. Each of the following 73
ABSTRACT
n lines contain a single uppercase word. You will read the AMBASSADOR
input file for this program in the following method: ... (70 lines omitted)
ZIRCON
Later in our course you will learn how to store large numbers of strings using features
called arrays and lists. But we haven't learned such things yet, and you are not to use them
on this assignment, even if you have somehow seen them before. The idea is not to read
all of the words and store all of them as data in your program; instead, you must advance a
Scanner to exactly the right place and select the word found there to be returned.
You may assume that the given file exists, can be read, and contains at least one word. (It
does not matter what code you put in your catch block, though we recommend a descriptive
error message with the exception variable.) You may also assume that the words in the
given file are all uppercase, and that the integer count on the first line is correct.
Common bug: The Scanner has unusual behavior if you use nextInt and nextLine
together. We recommend using next instead of nextLine to avoid such behavior,
which works fine because each line contains only a single word.
Once you’ve written the above method, modify your run method to prompt the user for
the dictionary filename. Do this just after printing the introduction. Your run method
should use your new getRandomWord method to pull a random word from this file every
time for each new game of Hangman. This way, each round will have a new random word.
The task of prompting and re-prompting for the file name can be made simple by using the
ConsoleProgram's method promptUserForFile, which accepts prompt string and
directory parameters, and re-prompts until the user has typed the name of a file that exists
in that directory. The function returns the file name that was typed. Note that the files in
this project live in the "res" directory.
–8–
A key concept in this phase is that you should not need to go back to modify your methods
from Tasks 1 or 2 (other than possibly fixing bugs). The new code you're adding here does
not change the task of playing a single game or displaying the ASCII Hangman art. That's
part of why we got those parts working first, so that we can build on them in this phase.
Your code should be robust against invalid input. Specifically, you should re-prompt the
user until they type a Y or N, case-insensitively. readBoolean may come in handy here;
as a reminder, it accepts parameters for the prompt message text, the "yes" text to look for,
and the "no" text to look for (it ignores case), and it returns true or false to indicate
yes or no. This means that you can use it as a test in an if statement or a while loop:
Next, write code to output statistics about the player’s games. Write the following method:
The following is the output from a call to stats(4, 2, 5); match our console output
format exactly.
Overall statistics:
Games played: 4
Games won: 2
Win percent: 50.0%
Best game: 5 guess(es) remaining
Thanks for playing!
The stats are for a single run of the program only; if the user closes the program and runs
it again, the stats are forgotten. If the player did not win any games, their win percentage
is 0.0% and their best game is 0 guess(es) remaining.
Also modify your run method to call your new stats method Play again (Y/N)? n
once the user is done playing Hangman. At right is a partial log Overall statistics:
showing the relevant part of the program. ...
The hard part of this stage comes from figuring out how to pass around the data between
your methods as parameters and return values. As a reminder, on this program you are
forbidden from using private instance variables (aka "global" variables) so all data needed
by your program must be stored in local variables and passed around using parameters and
return so that run will have all of the necessary values to pass to stats. It can be
challenging to find a good decomposition of the problem and pass the data around properly.
If you do the graphics extra feature, you can either make a second project (and
second submission) and edit the starter files as you wish, or you can make new
– 10 –
• Sounds: Make the game play a sound when a new game begins, when a correct or
incorrect guess is made, when the game ends with a win or loss, and so on. The
starter project does not contain any audio clip files, but you can find some on the
web and download them into your project's res/ subdirectory. You can load and
play a sound in that directory named horn.wav by writing:
Note that for this you will need to add import acm.util.* and import
java.applet.* to the top of your .java file.
• Vary number of guesses allowed: The default game lets the player have 8 guesses,
but you could write a version that allows any number of guesses and prompts the
user for how many they want to be given. Of course, you must figure out a way to
make the hanging man's full body appear in that number of guesses.
• Similar Games: There are other games that involve guessing letters. Expand the
program to play something like Wheel of Fortune, in which the word is now a
phrase and in which you have to “buy” a vowel.
Grading
Functionality: Your code should compile without any errors or warnings. In grading we
will test your game's overall flow, that it displays the right information at all times, handles
user input properly, and so on. We use an Output Comparison Tool to see that your output
exactly matches the output shown in this spec and the output/ folder. You should use
the Output Comparison Tool to verify your output before submitting.
Style: Follow style guidelines taught in class and listed in the course Style Guide. For
example, use descriptive names for variables and methods. Format your code using
indentation and whitespace. Avoid redundancy using methods, loops, and factoring. Use
descriptive comments, including the top of each .java file, atop each method, inline on
complex sections of code, and a citation of all sources you used to help write your program.
If you complete any extra features, list them in your comments to make sure the grader
knows what you completed. Limit yourself to using Java syntax taught in lecture and the
– 11 –
textbook parts we have read so far. In particular, you are forbidden from using instance
variables; a substantial deduction will be given if you do so. If there are important fixed
values used in your code, declare them as constants.
Your run method should represent a concise summary of the overall program, calling
other methods to do much of the work of solving the problem. In particular, run should
not contain println or print statements, though it can call other methods that print
output.
Recursion: You should not write any method that calls itself. For example, don't have
playOneGame call playOneGame(...); as a way of playing another game. This
idea is called "recursion" and is not suitable for this assignment. Such a style is often
desired by students who have trouble understanding returns. If you find yourself wanting
to do that, find a different strategy involving a loop somewhere else in your code.
Honor Code: Follow the Honor Code when working on this assignment. Submit your
own work and do not look at others' solutions (outside of your pair, if you are part of a
pair). Do not give out your solution. Do not search online for solutions. Do not place a
solution to this assignment on a public web site or forum. Solutions from this quarter, past
quarters, and any solutions found online, will be electronically compared. If you need help
on the assignment, please feel free to ask.