Note: GridWorld will not be featured on the 2015 and subsequent AP CS Exams.
The Critter class from the GridWorld Case Study is used on the AP Computer Science Exam to test your understanding of inheritance, postconditions, and a variety of other topics. The multiple choice section typically features one challenging question about the Critter class. One of the four problems on the free response section will feature GridWorld. On past exams, the GridWorld free response problem has often featured either a unique usage of the Grid interface or a class that extends the Critter class.
Critter class overview
A Critter is an Actor with behavior determined by 5 methods, each of which has a specific purpose and postcondition. Unlike subclasses of Bug, subclasses of Critter should never override the act method. The act method of Critter runs each of the other 5 methods. Subclasses of Critter should override only the methods that will behave differently than the corresponding superclass method of Critter.
The term “this” and method postconditions
When used in a method’s documentation, the term “this” refers to a method’s implicit parameter. In other words, “this” refers to the object on which the method is run. For example, one of the postconditions of selectMoveLocation includes the phrase “this critter’s current location” which means the current location of the critter on which selectMoveLocation is run.
A method’s postcondition must be true immediately after the method is run. For example, one of the postconditions of makeMove is getLocation() == loc. The postcondition must be true immediately after makeMove terminates. In other words, makeMove must move this critter to loc.
Several of the Critter method postconditions prohibit changing the state of any actors or limit the actors whose states may be changed. The state of an object is the values of its instance fields. The state of an Actor includes the actor’s direction, location, color, and Grid. A Critter is an Actor, so none of these can be changed for this critter. The values of any instance fields specific to the Critter subclass must also not be changed. Reading the values of instance fields is allowed.
Subclasses that override methods of Critter must adhere to the postconditions of the original Critter methods. For example, a subclass of Critter that overrides getActors must not violate the postcondition of the getActors method of Critter.
Each method of Critter is explained below.
The getActors method of Critter
The getActors method returns a list of actors that the critter may later process in another method. getActors does not process the actors.
The postcondition of getActors prohibits changing the state of any actor, including this critter. getActors may only return a list of actors. getActors may not store anything in an instance field, nor may it change the state of any of the actors it gets.
The getActors method of Critter returns all actors that are neighbors of this critter. Subclasses that seek to get a different list of actors to process should override getActors. For example, a subclass could get all of the actors within 2 spaces of this critter.
An example of a critter that overrides getActors is BlusterCritter.
The processActors method of Critter
The processActors method may use or change the Actor objects that are elements of its parameter actors. processActors does not choose the list of actors to process.
The postcondition of processActors limits what it can do. processActors is permitted to change the state of any, all, or none of the elements of actors. processActors can change the color, direction, and location of any element in actors. processActors can even remove some or all of the elements of actors from the grid.
processActors can also change the state of this critter. processActors can change this critter’s color, direction, or instance fields specific to the subclass. processActors may not change this critter’s location. In other words, processActors may not move this critter.
processActors may add actors to the grid as long as no actors in the grid other than those in the list actors are replaced. processActors is permitted to move any or all elements of actors with the same restriction that actors not in the list must not be disturbed.
The processActors method is not required to change the state of any or all Actor objects in actors. The processActors method can be left empty if the Critter does not process actors. The Critter is permitted to, but is not required to, change the states of specific objects.
The processActors method of Critter eats (removes the the grid) all actors from actors that are not rocks or critters. Subclasses that seek to process actors in a different way should override processActors. For example, a subclass could process actors by setting each actor’s color to this critter’s color.
The getMoveLocations method of Critter
The getMoveLocations method returns a list of locations to which the critter might move. getMoveLocations does not move the critter.
Only valid locations may be included in the list returned by getMoveLocations. This means that getMoveLocations may not return a list containing null. getMoveLocations may also not return null; however, it may return an empty list.
The postcondition of getMoveLocations is the same as the postcondition of getActors. getMoveLocations may not change the state of any actor, including this critter.
The getMoveLocations method of Critter returns empty neighboring locations, including locations from which the actors were removed by processActors. Subclasses that seek to select a move location from a different list should override getMoveLocations. For example, a subclass could get all empty locations within 2 spaces of this critter.
An example of a critter that overrides getMoveLocations is QuickCrab.
The selectMoveLocation method of Critter
The selectMoveLocation method returns a location to which the Critter will move. selectMoveLocation does not move the critter.
The postcondition of selectMoveLocation requires that the method return an element of the parameter locs, the current location of this critter, or null. As with getActors and getMoveLocations, selectMoveLocation may not change the state of any actor, including this critter. Unlike the postcondition of makeMove, the postcondition of selectMoveLocation allows for code that chooses whether and where this critter will move based on a given condition.
If this critter is intended to move to a specific location from locs, selectMoveLocation should return that location. If this critter is intended to remain in its current location, selectMoveLocation should return getLocation(). If this critter is intended to remove itself from the grid, selectMoveLocation should return null.
The selectMoveLocation method of Critter returns a random location from locs or null if locs is empty. Subclasses that seek to remove this critter from the grid when certain conditions are met should override selectMoveLocation. For example, a subclass could remove itself from the grid if it is unable to eat for a given number of steps.
An example of a subclass that overrides selectMoveLocation is StockpileCritter.
The makeMove method of Critter
The makeMove method moves this critter to loc or removes this critter from the grid if loc is null.
The postcondition of makeMove requires that this critter move to loc. Any code in makeMove that determines whether or where the Critter will move violates the postcondition. This critter must move to loc. Code that determines whether this critter should move, or whether it should remove itself from the grid usually belongs in selectMoveLocation. The postcondition of makeMove also requires that the states of most actors in the grid remain unchanged. Only the actors at the old and new locations of this critter may be changed. This critter may leave a new flower at its previous location; however, it may not move some other actor to it. This critter may remove an actor at loc as part of the movement to loc.
The makeMove method of Critter moves to loc if loc is not null; otherwise, it removes this critter from the grid. Subclasses that seek to leave something at the previous location or change this critter’s state before or after this critter moves should override makeMove. For example, a subclass could turn the critter to face its new location before it moves.
GridWorld Practice Problems
GridWorld Critter Exercise Solutions