CS 161 Homework 6 - Hangman
Due Fri Mar 15 at 5:00pm
Overview
For this assignment, you will be making a simple version of the word game Hangman, This game will be played in the terminal window. In this game, the computer picks a random word from a pre-supplied list. The player then guesses a letter that they think may appear in the word. The computer checks whether the letter appears in the word and either reveals all instances of it (if it exists) or takes away one of the player's lives. The computer then displays the progress that the player has made towards guessing the word. The game continues until either all of the letters have been guessed (and the player wins) or all of the player's lives are used up (and the player loses). In either case, the computer should announce this event and the game should end.
An example exchange is below:
Welcome to Hangman! The word is: _ _ _ _ _ Guess a letter: a The word is: _ _ a _ _ Guess a letter: e Computer: I'm sorry, the word has no 'e'. You have 4 lives left. The word is: _ _ a _ _ Guess a letter: s The word is: _ _ a s s Guess a letter: l The word is: _ l a s s Guess a letter: c Congratulations, the word is 'class'! You figured out the word with 4 lives remaining. Would you like to play again? (Y/N)
If the player loses, they should see (as an example):
No more lives remaining. The word was 'class'. Would you like to play again? (Y/N)
If the user enters "Y" when asked to play again, the variables in the game (the word to guess, the guessed letters, the number of lives) should reset and the game should continue. Otherwise, the program ends.
This assignment should be completed individually. You are welcome to ask for help (either from me or from your classmates), but remember the Gilligan's Island rule!
Objectives
- To practice using
arrays
(accessing and modifying) - To practice with loops---using them with arrays and doing simple searches
- To practice breaking up code into appropriate helper methods to support testing and readability.
Necessary Files
You should download and extract the BlueJ project from the
Homework6.zip file.
This project includes a provided WordList
class that represents a list of words. Once you have created a new instance of this class, you can call the getWordArray()
method to get a String[]
that has a list of words. Further details about the class can be found in its documentation, viewable through BlueJ.
The project also contains two word lists: words1500.txt
(the default) and words127000.txt
(a bigger list). Note that these lists do not contain exactly that number of words---you'll need to get the length
of the word array you're using!
Details
First, read through all of the assignment carefully. As you do so, think about what kinds of methods you might need, what kinds of variables you may want, and what kinds of functionality you will need.
Your program will primarily exist within a HangmanGame
class (capital H, capital G), which represents your game. You will also want a HangmanGameTester
class to run and test your program.
-
Start by declaring the instance variables of your HangmanGame. Thing about what kinds of attributes you will need to keep track of!
-
You will need to keep track of both the word-to-guess (e.g., "class" in the above example), and the word-so-far (e.g., "cl_ss"---the underscores represent letters that have not been guessed yet).
- Normally you'd use a String to keep track of a word. However, for this program we're interested in the individual characters of a word. You could use methods like
word.substring(0,1)
(to fetch the first letter of the String for example). However, because Strings are immutable, it is awkward to change an individual letter in a String, such as converting a '_' to an 'a' (though think about how you could accomplish this!) -
For this reason, you need to represent both the word-to-guess and the word-so-far as arrays of chars,
char[]
. An array will let you access and change each letter using an index (so you can get and change the 3rd letter). You can easily convert a String into achar[]
using thetoCharArray()
method of the String object. (This method is used similar to your toMixed() method of the Rational class, or a toString() method of any other class!). -
(Note that you can quickly turn a
char[]
back into a String by the String constructor that takes a char[] as a parameter---you construct a String out of thechar[]
)!
- Normally you'd use a String to keep track of a word. However, for this program we're interested in the individual characters of a word. You could use methods like
- A game should also have an array of words to pick from whenever a new game is started
- There are a couple of other instance variables you will need (e.g., lives, probably a Scanner so you can get input). Take a moment to think through what you'll need, remembering that you can always add more later. Note that the player's current guess should not be an instance variable--it instead should be passed around through arguments!
-
You will need to keep track of both the word-to-guess (e.g., "class" in the above example), and the word-so-far (e.g., "cl_ss"---the underscores represent letters that have not been guessed yet).
-
Your HangmanGame should have two (2) constructors:
- The first constructor should take no parameters. This constructor will need to create a new
WordList
object and get the array of words from that object to put in the appropriate instance variable. -
The second constructor should take a single String as a parameter. This constructor should create an array of words that has only a single item in it: the word give as a parameter.
- You can use this second constructor to more easily test the code (since you'll know what the word that you're guessing is!)
- Both constructors will also need to initialize all the other instance variables. But remember, you can use the
setupGame()
helper method to do just this!
- The first constructor should take no parameters. This constructor will need to create a new
-
Your HangmanGame class will also have a number of different methods. Many of these are "helper" methods, which pull out a piece of functionality to make your code more readable and easier to debug. Write each helper method individually and test it thoroughly before you move on to the next! These methods are described below, and in the documentation at the bottom of the page (which you can find suggested method signatures).
-
setupGame()
- This method should reset all of the variables for your game (e.g., the word-to-guess, word-so-far, number of lives (5 is a good number), etc). It "clears the board" after the game is completed. You can play a new game just by calling this method again.- You will need to pick a random word-to-guess from your array of words. You can get a random index by using the Random class's nextInt() method, giving that method the length of the array as a parameter.
- Your word-so-far will need to be a char[] of the same length as the word-to-guess. You should fill this char[] with underscores ('_') to start.
- Note that if your game was created using the second "testing" constructor, then you'll be picking a word from a list of length 1. And that's okay!
-
arrayToString()
- This method should take achar[]
(such as your word-so-far) and return a String representation of it, which you can then use for printing, etc. This method needs to take each letter of the char[] and concatenate them into a String. Also put a space between each letter, that way your word-so-far will look like "c l a _ _" rather than "cla__" (the second of which is hard to read!) -
getGuess()
- This letter should prompt the user to enter a guess, and then use the Scanner to read that guess from the command-line. You can convert the String to achar
by using the charAt() method of the String class.- Use a method from the String class to make the letter read from the Scanner into a lowercase version of itself. This will make it so that "e" and 'E' are not separate guesses!
- Bonus: make sure that the letter the user guesses is actually a letter (by using the Character.isLetter() method we talked about in class). If the user gives invalid input, keep asking them to try again until they get it right!
-
containsLetter()
- This method should go through your word-to-guess and see if it contains the guessed letter. This will involve a simple linear search: loop through each character in the word-to-guess, and see if that character is the same as the guessed letter. If so, then the word-to-guess contains the letter. If you get through the whole word without finding anything, then the word-to-guess does not contain the letter. -
replaceLetter()
- This method will go through the word-so-far and replace each '_' with the guessed letter only if the letter in the word-to-guess at the index of the '_' is the one that you're trying to replace.- You will only need a single loop for this method, but your method will need to consider both the word-so-far (to see if there is an '_' to replace) and the word-to-guess (to see if the '_' is one that should be replaced).
-
leftToGuess()
- This method will go through the word-to-guess and count the number of letters that have not been guessed yet. -
playAgain()
- This method should prompt the player with whether they want to play again, and then return whether they do or not.
-
-
The final method you'll need will be your
playGame()
method. This method will control your game, using the above helper methods to do its work.- This method will work somewhat similarly to the "main" method of your GuessingGame program. You will need a loop that shows the user the word-so-far, and then prompts them for a guess. Get their guess, and then check if the guessed letter is in the word. If so, then replace that letter in the word; if not, tell them they got the letter wrong and lose a life. You'll need to check whether they are out of lives (and if so, tell them they lost), or if they have guessed all the letters (and if so, tell them they won!) If the game is over, ask them to play again--if they do want to play, then reset the board. Otherwise, your playGame() method should be finished.
- Be sure and text your code thoroughly. Use the "testing" constructor with a single word to be able to test your program with a known word. Use copious System.out.println() calls to print out what is going on in your program (but be sure to comment them out when you are done!) Include lots of inline comments that explain your code, both to help me and to help keep your place.
- Each of your methods (including all of your helper methods) should have a full Javadoc comment (complete with @param and @return tags). Hint: I suggest filling in these comments along with the skeleton (the method signatures of all your classes) when you first start--that way you will know what each method is supposed to do!
Timeline
This is a big assignment--there are lots of methods (though many of them are just a single loop). Get started early!.
Try writing at least two helper methods on each class day, but more if you can. You want to have everything except the playGame() method working by next Wednesday.
Submitting
Check and double-check that your program works, that your code is commented, and that your name is in the class comment at the top of your program!
Be sure to complete the provided README.txt file with details about your program.
Upload the entire BlueJ project to the Hwk6 folder on the submission folder on hedwig. Make sure you upload your work to the correct folder!. This assignment is due at the start of class on Fri March 15.
Extensions
There is other functionality you might consider adding. They might be fun, and you can earn up to 5 points of extra credit for completing them. Only start on these once you have finished the rest of the assignment and you are sure that works. Be sure to save a copy of your working code in case you don't finish these!
- Keep track of previously guessed letters, and tell the user if they have already guessed a letter (instead of having them lose a life). You might use an array to store the letters already guessed, and then search through that array to see what you've found. Note that an ArrayList is more appropriate for this usage, but we won't talk about those until after break!
-
Modify the program to print out a graphical representation of the hangedman! E.g.:
__O__ | / \
The hangedman should gain body parts as the game continues.
-
Alternatively, use an Applet to draw the Hangman as he appears! This involves converting your HangmanGame into an Applet (be sure to submit your text-based HangmanGame as well).
-
You can get input from the user without using the text-based Scanner by using the following static method:
JOptionPane.showInputDialog("message you want to display to the user");
This method will return a String (just like using the .next() method of Scanner), which you can then integrate into your program.
-
You can get input from the user without using the text-based Scanner by using the following static method:
Grading
This assignment will be graded on approximately the following criteria:
- Your program has appropriate instance variables and constructors [15%]
- Your program recognizes correct letters and replaces them in the word-so-far [15%]
- Your program recognizes incorrect letters causes the player to lose a life [15%]
- Your program gives appropriate output (e.g., of the word-so-far) [10%]
- Your game ends either when the player guesses all the letters or when the player loses all their lives [10%]
- Your program allows the player to play a second time, with a new word and everything [10%]
- Your code is carefully documented, with full Javadoc methods and inline comments [10%]
- Your code adheres to proper style guidelines. This means that variables are given descriptive names, tabs and braces are lined up, local variables aren't specified in the fields, etc. If you have any questions about good style, don't hesitate to ask! [10%]
- You have completed the included README.txt file [5%]
Documentation
Below is an example Javadoc from a working Hangman game.
Class HangmanGame
java.lang.Object HangmanGame
public class HangmanGame extends java.lang.Object
A program to play a game of Hangman.
Constructor Summary | |
---|---|
HangmanGame()
Creates a new HangmanGame object with a default wordList. |
|
HangmanGame(String onlyWord)
Creates a new HangmanGame object, with the wordlist containing only the given word. |
Method Summary | |
---|---|
String |
arrayToString(char[] array)
A helper method that returns a String representation of the given char[]. |
boolean |
containsLetter(char guessedLetter)
A helper method that checks if the word-to-guess contains the gussed letter |
char |
getGuess()
A helper method that prompts the user to provide a guessed letter. |
int |
leftToGuess()
A helper method which counts how many letters are left to guess |
boolean |
playAgain()
A helper method that asks the user whether they want to play again. |
void |
playGame()
A method that plays a complete game of Hangman. |
void |
replaceLetter(char guessedLetter)
A helper method that replaces blank spots in the word-so-far with the guessedLetter |
void |
setupGame()
A helper method which re-initializes variables for the start of a new game. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
HangmanGame
public HangmanGame()
- Creates a new HangmanGame object with a default wordList.
HangmanGame
public HangmanGame(String onlyWord)
- Creates a new HangmanGame object, with the wordlist containing only the given word. This enables testing of the game using a known word.
- Parameters:
-
onlyWord
- The single word in the wordlist, used for testing and debugging
Method Detail |
---|
arrayToString
public String arrayToString(char[] array)
- A helper method that returns a String representation of the given char[].
- Parameters:
-
array
- the char[] to convert to a String. - Returns:
- A String displaying the current guess of the word. Has the form "g _ e _ _ ".
containsLetter
public boolean containsLetter(char guessedLetter)
- A helper method that checks if the word-to-guess contains the gussed letter
- Parameters:
-
guessedLetter
- the letter that was guessed - Returns:
- Whether or not the guessedLetter is in the word.
getGuess
public char getGuess()
- A helper method that prompts the user to provide a guessed letter. This method converts any guesses into a single, lower-case character.
- Returns:
- a single, lower-case char that the player guessed
leftToGuess
public int leftToGuess()
- A helper method which counts how many letters are left to guess
- Returns:
- The number of letters that have not been guessed.
playAgain
public boolean playAgain()
- A helper method that asks the user whether they want to play again.
- Returns:
- Returns whether the user wants to play again or not.
playGame
public void playGame()
- A method that plays a complete game of Hangman.
replaceLetter
public void replaceLetter(char guessedLetter)
- A helper method that replaces blank spots in the word-so-far with the guessedLetter
- Parameters:
-
guessedLetter
- the letter that was guessed
setupGame
public void setupGame()
- A helper method which re-initializes variables for the start of a new game.
Resets the word to guess, the current letters guessed, the number of lives, etc.