...from the spiritual song, "Dry Bones" or "Dem Bones".
Info links: w. guitar chords , 2 versions , another version w. MIDI , cute animation w. MIDI
Let's think about a more OOP-ey way of drawing Hangman body parts. Rather than a collection of conditional statements to determine what body parts to draw, how can we get the job done "automatically"?
Consider these ideas about Hangman body parts:
You'll need to study the documentation about the BodyPart package carefully.
The first thing you should notice is how similar the BodyPart system is to the WordList system. Most parts of it should be self-explanatory, but here's some more on select portions:
This class represents an abstract non-empty body list. It has an abstract draw() method that is overriden by its subclasses to draw the specific body part. It has a visible and invisible state like a NEWord and the execute() and toggleState() methods are likewise delegated to it. You can write this class yourself.
Why do you think that "host" has a different type in ABodyState.execute() vs. ABodyState.toggleState()? This is very deliberate and it is important that you understand the reason why. Be sure to ask someone if you can't figure it out.
Note that unlike a regular list, ABodyPart has no "first". Is that a problem?
The noose is a funny thing--is it or isn't a body part? It's a body part in that it is drawn on the screen. It's a special part though, in that to draw it is to lose the game. Does the rest of the system need to know that it is drawing the noose? That is, does the rest of the system need to figure out whether or not the game has been lost? You know the mantra....
So the noose has to somehow signal the rest of the system that it has been drawn. But what is the "rest of the system" to the noose? -- It's view! So, we can use the same architecture that the whole game uses, but on a smaller scale. That is, NoosePart needs a adapter to link it to its view. How does NoosePart.draw() differ from the other concrete ody part draw() methods?
Very similar to the WordFactory, except that it makes a list of body parts. Should the noose go in first (right next to the empty list) or last?
The BodyFactory needs an ILoseAdapter (see below), which you can set to null for now. Comment out the code in NoosePart that needs it too.
We will give you a couple of concrete ABodyPart classes so you can see how the graphics are drawn. You can make the rest. Should your code depend on how many body parts are available?
That's what the ILoseAdapter is for (get it? -- Hey, it's late when I writing this!). This is the adapter that is handed to the BodyFactory who uses it to construct the NoosePart that the NoosePart uses to tell its view that the game is lost. Whew!
Who is the NoosePart's view?
The NoosePart must notify its view (the HangmanGame) who, after doing whatever it needs to do, in turn notifies the HangmanGame's view (the HangmanFrame).
A visitor pattern algorithm for the state-patterned ABodyPart . No problems here, right?
An IAlgo to paint a list of ABodyParts. What does the invisible case do? -- there's more than one choice here.
This is the algorithm on the list of body parts that will make one more body part show on the screen.
Why can't this algorithm be used to signal the end of the game?
This algorithm is of the same structure as all the other algorithms we have done so far. I think you can handle it.
At this point, we can actually write about 75% of the code for the HangmanGame class. We'll leave the Running/NonRunning state behavior for later. But for now, here's what you should do:
At this point you should be able to demonstrate: