Complete the GiraffeCritter practice problem before reviewing the solution.
Review the GiraffeCritter
solution with AP CS Tutor Brandon Horn.
public class GiraffeCritter extends Critter
{
private int hungrySteps = 0;
public ArrayList<Actor> getActors()
{
ArrayList<Actor> flowers = new ArrayList<Actor>();
for (int row = getLocation().getRow() - NECK_SIZE;
row <= getLocation().getRow() + NECK_SIZE;
row++)
{
for (int col = getLocation().getCol() - NECK_SIZE;
col <= getLocation().getCol() + NECK_SIZE;
col++)
{
Location loc = new Location(row, col);
if (getGrid().isValid(loc) && getGrid().get(loc) instanceof Flower)
flowers.add(getGrid().get(loc));
}
}
return flowers;
// Alternative is to return all actors within range here and find flowers in processActors
}
public void processActors(ArrayList<Actor> actors)
{
int flowersEaten = 0;
for (Actor a : actors)
{
if (flowersEaten < STOMACH_SIZE)
{
a.removeSelfFromGrid();
flowersEaten++;
}
}
if (flowersEaten == STOMACH_SIZE)
hungrySteps = 0;
else
hungrySteps++;
}
public Location selectMoveLocation(ArrayList<Location> locs)
{
if (hungrySteps >= MAX_HUNGRY_STEPS)
return null;
else if (hungrySteps == 0)
return getLocation();
else
return super.selectMoveLocation(locs);
}
}
Overriding the correct methods is an important part of this problem. As with all creatures that extend Critter
, you must not override act
.
GiraffeCritter
gets a different list of actors to process than Critter
, so it must override getActors
. Specifically, GiraffeCritter
gets flowers within NECK_LENGTH
rows and NECK_LENGTH
columns. You cannot get the list of actors to process in processActors
since you would violate the postcondition when removing an actor that is not in the parameter actors
.
GiraffeCritter
processes actors differently than Critter
, so it must override processActors
. Specifically, GiraffeCritter
attempts to eat a certain number of flowers and keeps track of how many flowers have been eaten. The postcondition of processActors
permits the state of GiraffeCritter
to be changed, so you can update the instance field that tracks how many steps the GiraffeCritter
has been hungry.
GiraffeCritter
moves differently than Critter
, so it must override at least one of the methods that control movement. Overriding selectMoveLocation
results in code that does not violate the postconditions of any method. Since the postcondition of selectMoveLocation
prohibits changing the state of any actor, the private instance field cannot be updated. You cannot call removeSelfFromGrid
in selectMoveLocation
. Doing so would violate the postcondition that prohibits changing the state of any actor.
It is not possible to achieve the desired behavior without violating any postconditions by overriding only makeMove
. The postcondition of makeMove
requires that a call to getLocation
immediately after a call to makeMove
return loc
(the parameter to makeMove
). You cannot make a decision about whether to move or not in makeMove
. You must move to the parameter loc
.