Warm-up (in case you're not ready to plunge into the main assignment yet): several of P11.4 through P11.9 (which all go together), or any of P11.11, P11.12, P11.13. Also, any of the programming exercises at the end of chapter 12.
Modify your program from homework 1 so that
At each step, you should see only the current location of the Drunkard, not everywhere (s)he has been.
the paintComponent
method doesn't change the
Drunkard, but only draws it. (The "wandering" should happen
somewhere else, e.g. as soon as the Grid is created.) The effect should
be that you can minimize-and-restore the window, or bring another window
in front and then bring yours to the front, or resize the window,
without changing the location of the Drunkard.
The Drunkard moves one step each second, using a Timer as described in Chapter 11. The simulation should run until it is stopped, rather than for a fixed 100 steps.
There can be several Drunkards wandering around at the same time, each a different color (so we can tell which one is which);
there can simultaneously be one or more Police on the screen. Police should appear visually different from Drunkards (e.g. a circle vs. a square, or if you want to get elaborate, a smiley-face with either a blue cap for Police or crossed eyes for a Drunkard). but individual Police don't need different colors. For now, Police don't move at all.
Police can now move, but unlike Drunkards, they walk a predictable pattern. A simple version would be a Police who always walks back and forth along row 3 of the grid, turning around upon reaching the left or right wall. If that's too easy, try one who walks around the edges of the grid clockwise, staying a fixed distance from the edges: for example, a Police with a distance of 1 on a 10x10 grid would walk east from (1,1) to (8,1), then turn south to (8,8), then west to (1,8), then north back to (1,1). Different Police can walk different beats, e.g. 1 square away from the edge, 3 squares away from the edge, etc.)
There should be three Buttons: "Add Drunkard", "Delete", and "Quit", which do the obvious things. "Add Drunkard" should add one at a random location on the grid, with a random color. "Delete" should delete a randomly-chosen person (either a Drunkard or a Police). See Chapter 12 for handling Buttons.
The user can create a new Police by mouse-clicking on a square of the grid. You'll have to decide what "beat" the new Police should follow: a simple answer would be "walk left and right along the row that the Police is in". See Chapter 12 for handling mouse-clicks. Note that no matter where in a square the user clicks, the Police should appear centered at the same place.
The user can change the size and shape of the window; this immediately changes the number of rows and columns in the grid. (What effect should it have on Police walking a clockwise beat?)
Extra credit: No Police or Drunkard will move onto a square that already has a Police or Drunkard on it. (This can be done in at least two ways: have each square of the grid "know" what if anything is there, or search through the list of Police and Drunkards to see if any of them have the specified coordinates. Which of these approaches, or what other approach, did you choose and why?)
As usual, don't try to do this all at once. Pick one "baby step" at a time (I recommend doing the features in the order given above), and make sure it compiles, runs, and passes its tests before you go on to another feature. And always keep in mind that I might change the assignment slightly on the day that it's due; prepare for changes.
The Drunkard and Police classes have a lot in common; represent their similarities and differences using polymorphism as in chapter 11.
Many of the features of this program involving a
collection of people (perhaps a mix of Drunkards and
Police). Implement this collection with a separate class, which will
contain either an array or an ArrayList
of
people.
Distinguish between "model" classes, which "know" about locations and movements, but nothing about graphics or pixels, and "view" classes, which "know" about graphics and pixels but not about, say, the different move rules of Drunkards and Police.
Test all the methods of "model" classes using
JUnit
(the "test case" stuff built into
BlueJ). For "view" classes you may just have to run known
test cases and look at the results, but please write down in
advance your test cases and what the results should
look like.
Your collection class will need to be able to "move all
the people" and "draw all the people's pictures". The
obvious way to do this is with a moveAll()
method and a
drawAll(Graphics2D g2)
method. But this makes the
collection class depend on graphics, even though its job really isn't
about graphics at all. Furthermore, if in the future you needed to
do something else to "all the people", the
collection class would need to be modified again, and would acquire a
dependency on yet other external classes. A way to avoid this is to
write a doToEach
that takes in an "operation"
and simply applies that operation to each person in the collection.
Use an interface to abstract the notion of "operation", using ideas from sections 11.4 and 11.5 of the textbook.
Every "interesting" method in your program should, if possible, be accompanied by a "testing" method (I recommend using JUnit) that runs various test cases on it and indicates whether it passed all its tests. (Some methods don't lend themselves to this kind of testing, in which case you should describe, in English, how you would test them and tell whether they were working correctly.)
While you work on this program, keep an error log recording mistakes you make. For each one, write down