DarterFish
A darter fish darts two cells forward if both the first and second cells in front of it are empty. If the first cell is empty but the second cell is not, then the darter fish moves forward only one space. If the first cell is not empty, then the darter reverses its direction but does not change its location.
Design Issues
Although normal fish and darters exhibit different behavior when moving,
they also share many similarities. For example, the id
,
color
, location
, and direction
accessor methods have nothing to do with the particular type of fish being
modeled. Rather than repeat the code for all the methods with the same
behavior, I wanted my DarterFish
class to extend
Fish
. My DarterFish
objects would inherit certain
data and behavior defined in the Fish
superclass, but redefine
other behavior by providing new implementations in the subclass.
I decided that my first step would be to modify the
nextLocation
method, which defines how the fish chooses where
to move.
Programming Exercise: DarterFish, Step 1
- Create a subclass of the
Fish
calledDarterFish
. (It would probably be easiest to start by copying and pasting from the first class you created above, changing its name and the names of its constructors.)NOTE: Unlike theTest your new class, using the fileWhitefish
class,DarterFish
does not need any extra instance variables. For testing purposes, though, color them yellow (where do you do that?) and display them usingLittleFishDisplay
orNarrowFishDisplay
(where do you do that?). Use a larger display for normal fish.testDarters.dat
. As always, identify what you expect your test results to be before you run your tests. Do you expect the darter fish to behave any differently from objects of theFish
superclass? Do they behave differently?Copy the
nextLocation
method from theFish
class into theDarterFish
class, but then delete its internal code (none of which is very useful for this class).Add code to find and return a location according to the algorithm given above: A darter fish darts two cells forward if both the first and second cells in front of it are empty. If the first cell is empty but the second cell is not, then the darter fish moves forward only one space. If the cell in front is not empty, the fish does not move. So, the
nextLocation
method should either return the current location (the darter fish cannot move), the location in front of the fish (if the darter can move there but no farther), or the location two cells in front (if the darter can move there).How would you find the cell in front of a darter fish? How would you find the cell in front of that?- Start the simulation program, reading in the file
testDarters.dat
. Write out your expected results. Which darters do you think will move? Where do you expect each one to move to? (You can write up your expected and actual results in a Markdown table, using the vertical bar (`|`) between columns.)In determining your expected results, it helps to know that the Step behavior in the graphical user interface processes the objects in the grid in row-major order. For example, if there are fish at locations (3, 1), (3, 4), (5, 1), and (5, 3), they will be processed in that order: the fish in row 3, left-to-right, then the fish in row 5, left-to-right.- Test the simulation program by running just one step, then saving the results to a new file. (You can find "Save grid as..." under the File menu.) Add your actual results to your table. Compare your expected and actual results. Do they match up? If not, see if you can figure out why, and add your analysis below your table of expected and actual results.
It's OK if the expected and actual results don't match; this is very common in testing. In fact, the goal of testing is to find such differences, analyze them, and address them.Modify your code to address any discrepencies you found between expected and actual results, and re-test. (You don't have to add the results of your additional test(s) to your table.)- Let the simulation program run for many steps. What happens? Is this the full desired behavior for darter fish?
Changing Direction
So far, my fish were correctly determining where to move when they could do
so, and the move
method inherited from the Fish
class was correctly moving them there. What it wasn't doing, though, was
changing direction when the fish could not move.
When darters can't move forward, they should reverse direction without moving. Darter fish could also be called "pacer fish" because they pace back and forth.
I looked again at the move
method in the Fish
class, and confirmed that this was the method I needed to redefine to
correctly implement changing direction.
Programming Exercise: DarterFish, Step 2
- Copy the
move
method from theFish
class into theDarterFish
class. In this case, the existing code is close to the right behavior, but not exactly what you need. Modify the method so that it changes location when it can, and reverses direction when it can't. (How do you know when it can't move and should change direction? How do you change the direction to the reverse of what it is currently?)- Create a new table of expected results. Which darters will move? Which will change direction?
- Again, test the simulation program by reading in
testDarters.dat
, running just one step, and saving the results to a file. Add your actual results to your table. Compare your expected and actual results. Do they match up? If not, see if you can figure out why, and add your analysis below your table of expected and actual results. Then modify your code to address any discrepencies you found between expected and actual results, and re-test. (You don't have to add the results of your additional test(s) to your table.)- Let the simulation program run for many steps. What happens? Is this the full desired behavior for darter fish?
- Run the simulation program with a mix of fish classes in it. (You can manually populate an environment with multiple fish types, or use the
darterAndNormalFish.dat
data file.)
Analysis Questions: Testing DarterFish
- Each of the five rows of east-facing and west-facing fish in
testDarters.dat
could be considered a different test case, and each south-facing fish could also be considered a different test case, for a total of 9 test cases. What conditions do each of these test cases test? What is the difference between the test of the 3 east/west-facing fish in row 7 and the two east/west-facing fish in row 9? (Remember that rows start at 0, so row 7 is the eighth row.)