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

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.

  1. 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 a char[] using the toCharArray() 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 the char[])!
    • 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!
  2. 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!
  3. 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 a char[] (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 a char 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.
  4. 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.
  5. 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.
  6. 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!

Grading

This assignment will be graded on approximately the following criteria:

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.