Assignment 4: Inheritance, Abstract Classes, and Final
Objectives:
- Create a small game and practice inheritance/implementing child classes.
- Apply abstraction as appropriate.
- Be able to justify design decisions.
Due: Wednesday, Oct 19 before class
Recommendation: Complete at least through part 2 before Monday, for timely completion of the assignment and to identify any issues/questions/comments you may have.
Set Up
Cloning the Repository
In your terminal, go to the directory where you are keeping your repositories for CSCI209. Clone the repository for this assignment. Add your name to the README file.
Part 0: Background and Preparing for Assignment
Compiling and Running the Code
- Compile the code using javac *.java or javac Game.java.
- Run the game by executing java Game
You should see a black pop-up window with a little dude--the professor--in the bottom right corner of the screen, walking. - Using the arrow keys, move the professor around the screen. Use the space bar to stop him.
- To stop the program, close the window.
- To see what I'm hoping to see when you're done (if you also do
the extra credit), go into the
demoClasses
directory and run
java -cp Game.jar Game
Your Goblin's movement may not be as aggressive as mine.
Understanding the Code
To help you with understanding the code, here are the Javadocs for the game code. Refer back to them while completing the assignment, as it may help you to figure out what is inherited and who can do what.
- Start by looking at
Game.java
. There is a lot of code that you don't need to worry about. Focus on themain
andplay
methods as well as the instance variables.The
main
method creates a new Game object, including setting up the window.main
also calls theplay
method, which starts the game running.The
play
method creates the professor and takes the professor's turn (which moves the professor). The professor's direction is determined by pressing keys. - Then, look at
GamePiece.java
. (This class contains some less-than-ideal coding practices. Bear with me--you'll fix them soon!)Note the instance variables, the constructor, and the available methods--especially the
takeTurn(Game game)
method. - Now, look at
Human.java
. Look at the class's constructor and thetakeTurn
method. Hopefully, you're now seeing how the pieces fit together.
Part 1: Creating Child Classes (60 pts)
There should be a lot more thinking than there is coding for this part. The amount of code you need to write is not huge. Think about the behavior of each class and how that should be implemented.
~~~ FAQ ~~~ Don't look at this until after you've attempted to solve this part.
- Create a
Goblin
class, which inherits fromGamePiece
. There are several animated gifs to choose from. A Goblin should "chase" the professor instead of just standing there, which is what the inheritedGamePiece
'stakeTurn
method does. Since you are overriding the takeTurn method, the method should have the same signature (e.g., the same parameters) as the parent's takeTurn method. How can you make the compiler help enforce that the child class's method has the same signature as the parent?Some slides to help frame your thinking.
The implementation of
Goblin
'stakeTurn
method should look completely different from theHuman
'stakeTurn
method. They do not move in the same ways. Consider this hypothetical: if theGoblin
was so much likeHuman
, why wouldn't I have told you to make theGoblin
a child ofHuman
? I probably would have. So, their implementations are probably pretty different.If you are tempted to change the method signature or write code that violates encapsulation, stop and think about what objects are available to you and if they have any methods that could be useful.
- Create a
Treasure
class, whose image is the gem. The gem will move around the window, periodically and randomly. Note that theTreasure
should not change positions every timetakeTurn
is called withinplay
. In other words, sometimes, the Treasure'stakeTurn
method is called, but it doesn't move. Also, note that the top 20 pixels of the window (indicated byYMIN_DISPLAY
) are covered by the menu bar. - Clean up your classes. Is there irrelevant code?
Part 2: Updating the Game Class (15 pts)
- Update the
Game
class to have instance variables for the Goblin and Treasure objects. - Edit
Game
'splay
method. Create a Goblin object and a Treasure object. Start the Goblin in the upper left corner. The Treasure should start in the center of the window. - Call the Treasure and Goblin's
takeTurn
methods. - Call the Treasure and Goblin's
draw
methods to display them.
Part 3: Using Abstract Class in the Game Application (35)
Cannot be completed until after Wednesday's class.
Refactoring
This assignment is an example of a typical design/implementation process. Start with the original code design: inheritance from GamePiece class. You realize it could be designed better, so you change the design/implementation. With the revision, it is now easier to add new functionality to Game. This is called refactoring. You are not adding functionality, but you are changing the code to improve its design/readability/maintainability in some way.
Now for the refactoring of your code:
- First, clean up your code. If you did not use
the
@Override
annotation on thetakeTurn
methods of your child classes, you should add that. If you get errors, fix the errors (most likely caused by not using the appropriate parameters). - Modify the
GamePiece
class so that it is anabstract
class with anabstract
takeTurn
method. - Modify the
Game
class'splay
method to have an array ofGamePiece
objects, which contains theGamePiece
objects that you just created. Iterate through the objects, calling thetakeTurn
anddraw
method on each object. (If you're getting errors, you likely didn't override thetakeTurn
method correctly.) Is there any other way you can make the code more concise? - Make all appropriate methods in the
GamePiece
class befinal
methods. - Test your new code.
The coding for this part of the assignment should be straightforward. The explanations to the questions below are more important.
Documenting Design Decisions
You are going to document your design decisions in
the README.md
file, under "Design Decisions".
- In the section labeled "Making GamePiece Abstract", discuss
why making
GamePiece
abstract
is a better approach to the code's design - In the section labeled "Calling an Abstract Method", explain
why we can call the
takeTurn
method on aGamePiece
object--a method that is abstract on an object of an abstract class--and the application does the "right" thing - In the section labeled "Choices of Final Methods", justify
your choices of making methods
final
. - In the section labeled "Adding a New Goblin", describe all the steps a programmer would need to take to add a new bad guy that has a different movement behavior (e.g., zig-zags across the screen) to the game. Be clear, concise, and explicit. Don't talk about the zig-zag behavior in particular--I am just giving you a concrete idea of a different behavior. It should be clear to a programmer how to add a new bad guy to the game. (You can make an ordered list in Markdown to make the steps easily read.
- After you push your code to GitHub, look at how the README is displayed in your browser to make sure it looks as you expect--with headings and paragraphs under those headings.
Extra Credit (up to 15 points)
Complete all of the above requirements before doing extra credit. A good implementation of above, using best design practices, is much preferred to completing the extra credit.
Add the overlap
method to
the GamePiece
class. The signature
for overlap
will look something like
public boolean overlaps( GamePiece gp )
. It will
return true iff the GamePiece overlaps the GamePiece passed to
the overlap
method as a parameter. Note that, if you
haven't done so already, you'll need to adjust the value of the
img_width
or char_width
variables
of the respective child classes, depending on the size of animated
gif you chose. Try a value of 15 to start.
There is a lot more that can be done on this assignment--actually making the game stop, implementing winning or losing, adding goblins (with different types of movements), ... Be creative, but keep the code neat.
Submission
As usual, put all of your code in your GitHub repository that you and I can access.
Grading (115 pts)
You will be evaluated based on the following criteria:
- (80 pts) correctness and OO style of your classes, including use of abstract, final
- (15 pts) adding abstraction
- (20 pts) Documentation of design decisions