This assignment will give you practice with arrays,
graphical user interfaces (GUIs), main
methods, reading from files
and consoles, as well as the concepts from the first and second assignment.
You will also develop a test suite.
Read this handout carefully so that you understand exactly what we are asking for. Do this before you start programming! Take notes as you read. What classes do we want? What are the method names?
If you notice parts that are unclear, please ask the Instructor or post a message on the discussion board. Any major changes/clarifications will be posted on the A3 FAQ page.
If you are not already familiar with how to play Hangman, please see the following Wikipedia entry. The major differences
between this description and the game you will design are as follows:
In this assignment, we ask you to make your own graphical Hangman game that you can play with on your own. See the following set of slides for a demonstration of what your game should look like and how it should be played.
There are certain basic requirements that we will expect in your final design: sufficient testing, documentation of your code, and a good design approach to the assignment.
The product of this assignment is visual, but this doesn't mean that the testing portion of the assignment can be left out. On the contrary, most of the underlying logic of this assignment can be thoroughly tested with JUnit.
When testing, you do not have to worry about testing for malicious input (e.g. non-alphabetic characters, arrays whose dimensions don't match), but your code should be as versatile as possible. Also, make sure to cover both typical and boundary conditions in your tests, just like in the previous Assignment.
In order for your game to be as user-friendly as possible, you will need to consider various error conditions (see below), but they are specified explicitly.
For this assignment, we expect you again to follow the style rules laid out in A2 Rules, plus JavaDoc comments.
We expect proper JavaDoc comments for:
A brief reminder: JavaDoc comments must begin with /**
and end with
*/
, and the following tags can be used to denote special roles within
your comments:
@param
name desc : add a parameter called name
with description desc to the parameter list for this method. @return
desc : add a description of the return value.We also expect non-JavaDoc comments throughout your code, especially in sections where the purpose of your code is not immediately clear.
The Hangman game is composed of three major parts:
For this assignment, we provide you with "starter code" that implements some of the HangmanGUI, HangmanListener, and PlayHangman classes. You must complete the parts missing from the provided classes, as well as write any new classes that are necessary. Assume that the code we have given you should be in the final product; this means that none of the method signatures that we have already specified should be changed in your final design.
When approaching this design, certain components are more important than others. Rather than programming the entire assignment at once, implement this assignment in stages, and make sure the current stage is working properly before moving on to the next.
The required parts are specified in the following sections.
The Hangman
class represents the basic functionality of the
game. You will not be provided with starter code for this part of the assignment. That means you have to write this class from scratch, following good design principles:
think about the variables and methods that are required to support the process of playing the Hangman game, as it was illustrated in the PDF slides (see above).
You must NOT have unnecessary or redundant components that do not contribute to the game's functionality!
Take a look at TicTacToe.java
, which we wrote in class, for ideas about how to
write your own "engine" class.
You MUST use arrays to represent information for this assignment! For example, to represent the word that the player needs to guess. Although you might be able to use String manipulation for this purpose, that would likely be more difficult and would defeat the purpose of this assignment. In other words, you must not use StringTokenizer
anywhere, and you should minimize the usage of String's substring
and indexOf
methods.
The following are some suggestions for the operations that your class should perform:
Here are some IMPORTANT rules and restrictions for your class:
You MUST implement a method that gives a "hint" to the player. The "hint" consists of revealing the leftmost hidden letter in the word that is being guessed. Note that you should reveal only one letter to the player, even if that letter occurs multiple times in the word! So the player should be able to guess that letter (for example, if they think it occurs again later on in the word).
(NEW!) However, if the letter that was revealed by the hint does not occur again in the rest of the word, AND the player guesses that letter, then the player must be penalized - the attempt should count as a miss and a warning message should pop up, saying: "There are no more X's in the word!", where X is the letter that was guessed. Though, this letter should not be added to the list of incorrectly guessed letters (that wouldn't make sense, since the letter WAS in the word, only it was revealed by a hint, rather than a correct guess).
String
representation of the game. You should follow this format:
Word: _ A _ _ _ _ _ _ _
Misses: K, T
Guesses left: 3
Notice that on the first line all the letters (or underscores) are separated by ONE space, and words are separated by THREE spaces. The word here is "CAPE VERDE".
If there are no misses, you should leave it blank:
Word: _ _ _ _ _ _
Misses:
Guesses left: 5
As always, you should make your code more efficient by using private helper methods (we will be looking for this during the marking!).
You should also build a tester for this class (HangmanTester.java
), to
make sure that it behaves the way you planned.
This PlayHangman
class is the driver for this game. This class contains
a main
method, so it can be invoked from the command prompt. The game can
be played in three ways:
java PlayHangman <pathToDictionary> <maxGuesses>where :
<pathToDictionary>
is the path and name of the file that contains the dictionary of words.
<maxGuesses>
is the maximum number of incorrect guesses a player is allowed to make.
java PlayHangman <pathToDictionary>where :
<pathToDictionary>
is the path and name of the file that contains the dictionary of words.
The value of the maximum mistakes allowed should be set to a default of 6.
java PlayHangmanIn this case, the user should get to choose the dictionary file and enter the value of the maximum mistakes allowed (you decide what the best way to do this is!).
This class should allow the user to play the Hangman game using the other game components (Hangman
, HangmanGUI
, and HangmanListener
).
The Graphical
User Interface (GUI) is the window-based interface that will display the game
to the user in a JFrame
and allow the user to play the game by
clicking on JButton
s to select letters or to get a hint.
HangmanGUI
class The HangmanGUI
class inherits from the JFrame
class and is for display purposes only. The window contains:
Its main functions
are to initialize and display all the appropriate values when the game is started, and to update the values (ex. the hidden word)
when a letter is selected or when the user presses the hint button. Even then, it relies on the
HangmanListener
class
to determine when to update and what values to use.
The design of the HangmanGUI
and its relation to the other
classes is intentionally unspecified here, because this design component is left
for you to decide. See the HangmanGUI
starter code.
To understand fully what this class does, make sure you read the
last paragraph of the next class, describing how you will
attach a "listener" to the HangmanGUI
.
HangmanListener
class This class extends the MouseAdapter
class, and its basic function
is to listen for mouse events. When attached to a button or window, it knows when
the mouse has interacted with that component in any way, and will execute the appropriate
method. Five methods are available for such purposes, in the cases where the mouse
enters the component, exits the component, is pressed, is released, or is clicked.
For this assignment, you only need to concern yourself with the click action.
Most of the HangmanListener
class is provided for you, and contains
a method that can be used to attach the HangmanListener
to the HangmanGUI
,
as well as the signature and the starting line for the mouseClicked
method. This method is invoked every time somebody clicks the
mouse on a component that the HangmanListener
is "attached" to. You are
required to fill in the remaining functionality for the mouseClicked
method, making it respond to the click event by manipulating the HangmanGUI
objects
appropriately.
How do you attach a HangmanListener
object
to the graphic component whose clicks it is listening for? Easy: check out the code that you used in Week 10's Lab. There, a
MouseAdapter
class was attached to a JButton
object by calling that
object's addMouseListener()
method. All graphic components (JFrame
s, JButton
s)
have such methods. To identify which listener it is attaching, your
HangmanGUI
class will have to take in a HangmanListener
instance as a parameter in its constructor.
To make sure you get this part right: read and understand the Week 10 Lab
code; if necessary, build a few small JFrame
/JButton
classes and experiment with
adding your Listener
through the addMouseListener
method
until you're comfortable with it.
The combination of the Hangman
, HangmanGUI
and HangmanListener
components produces the overall behavior of the game.
When the game is first invoked from the command line, the following connections
are formed:
Hangman
object is created. HangmanListener
object is created.HangmanGUI
is created, using the reference
to the HangmanListener
object and the Hangman
object.
Once the constructors are done, the connections between the objects produce the
following behavior when a player clicks on a letter or the hint button in the
HangmanGUI
:
HangmanListener
is invoked whenever a button is clicked
in the HangmanGUI
window.HangmanListener
tells the HangmanGUI
object what
selection was made.HangmanGUI
decides what to do with the selection and tells
the Hangman
object what to do.Hangman
object tells the HangmanGUI
how
to update itself. If the player wins the game, a congratulatory message should pop up. If the player loses, the hidden word should be revealed AND a message should pop up to inform the player of their loss.
The user should also have the option of playing again, once the current game has ended (either in a win or a loss). If the user decides to play again, then a new game must be started - with a new word to guess (chosen randomly again from the dictionary) and the same value for the maximum mistakes allowed variable.
The dictionary file contains a list of possible words for the player to guess. It has the following properties:
Even though we assume a non-malicious player for this game, there are certain error conditions that you must anticipate:
If the user specifies the wrong number of arguments on the command-line, then the game should NOT begin and an
error message should pop (this is already taken care of - see the HangmanGUI
starter code).
If the number of arguments on the command-line is correct, you can assume that they are of the correct type - i.e. the first optional argument
is a String
filename and the second optional argument is an integer value (for the maximum allowed mistakes).
If the user specifies an incorrect filename -- i.e., the file with that path and name does not exist -- then the game should stop and an error message should pop up.
(hint: you should do this by "catching" the IOException
that is thrown, using a try-and-catch block, which you will learn about in lecture)
If the user specifies a maximum number of incorrect guesses that exceeds 26 (the number of letters in the English alphabet), then the game stops and an error messsage should pop up.
Whenever the user is supposed to enter a value and press "OK", but instead clicks on "Cancel", the game must always stop and an appropriate error message should pop up.
In the GUI, once the player has clicked on a letter to make a guess, the player should not be able to guess that letter again.
WARNING: This section should only be considered if you have completed ALL of the other parts of this assignment, including testing and JavaDoc comments.
If you have completed the rest of the assignment, kudos will go out to students who add enhancements to their game, either in the form of extra features or more elaborate functionality. This is your chance to be creative, have fun and impress us with you imagination.
The course website describes how you hand in your assignment. This section tells you what to hand in:
Hangman.java
HangmanTester.java
HangmanGUI.java
HangmanListener.java
PlayHangman.java
A summary and justification of the major design decisions you made (in a file called "design.txt") - for example, why you designed the "engine" class (Hangman.java
) the way you did. You can also discuss any major challenges you encountered, or describe any enhancements you made to the Hangman game in your code. This will greatly assist us in the marking of your assignment, so it is important that you submit this file (marks will be deducted if this file is missing!).
(Note: your description should be as general as possible - do NOT get into small implementation details. Ex. don't talk about why you used a for-loop instead of a while-loop in a particular method - that's not a major design decision! Instead, talk about what kind of methods you have, and why. You can also talk about how you decided to represent information in your program).
Remember that spelling, including case, count in Java: your files must be named exactly as above.
NOTE: Other than the signoff statement,
only hand in the files that end with the .java
suffix. Be careful about this, because in the same place as your
.java
files you may also have files with the extension
.class
(that is, they end with the .class
suffix), but otherwise have the same name. Two particular pitfalls:
Microsoft operating systems often do not display file extensions unless they've been told to do so.
DrJava creates "backup files", which means that
you'll see filenames like "Hangman.java~
".
Notice the ~
at the end. It indicates that the file is
a backup file, which happens to be an older version of your program.
Don't hand these in.
Since .class
files cannot be read by TAs or run with
our testing programs, submitting the wrong files might cause you to
fail the assignment.