Gridworld Part 4

We have played around with the Grid methods and the Actor methods, and now we can make actors that interact with other actors. To start with, we will example some sample actors like the Citters who can "eat" other actors like bugs. Eventually you will be fully qualified to make your own actors that can behave in a quiter interesting way with other actors. This section conclude your AP CS A curriculum. For your convenience, here is a review of how to get your IDE (BlueJ or Eclipse) running so it knows where gridworld.jar lives. It is a library that is quite complete. Details are in the Podcasts, but you can read about the installation of the library here at the College Board

Eclipse Instructions

  1. Start a New Project, and name it something (like "Bugs" for example)
  2. Select (Click once) your Project in the Package Explorer
  3. Select from the MENU Project-> Properties
  4. Click on the Java Build Path
  5. Click on the Libraries Tab
  6. Press the Add External JARs... button
  7. Select the file gridworld.jar (this was extracted from the file ap07_cs_gridworldcode.zip

BlueJ Instructions

You may find BlueJ a better IDE for this sort of activity. In order for the code to compile make sure the gridworld.jar file from ap07_cs_gridworldcode.zip is listed in the libraries.
  1. Open BlueJ Preferences
  2. Click the Libraries tab
  3. If gridworld.jar isnt already there, press the Add button and select the gridworld.jar file in the browser
  4. Click the OK button
  5. If you just added a library, you may wish to restart BlueJ

Part 4 (Set 7)

You will learn (and rememeber better) how things work by running code that tests your answers. For example, go ahead and read the first part of Part 4 (it starts on page 29) in the Student manual up to Did you know? Set 7 on page 30.

Try to answer these questions on your own. Use pp. 16-19 and Appendix B page B-1.

Critters

It is usually not a good idea to override the act method in a Critter subclass. The Critter class was designed to represent actors that process other actors and then move. If you find the act method unsuitable for your actors, you should consider extending Actor, not Critter. Usually we will override how to process the actors. The default Critters are described on page 31.

There is a Critter Folder already in the Gridworld Code folder, but for your convenience, here is the basic code for a CritterRunner. The gridworld.jar library already has Critter code, so you don't need the Critter class in your project folder, but I include it below so you can see it if you wish. Run this and obseverve how a default Critter works.

CritterRunner.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 * @author Cay Horstmann
 */

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Critter;
import info.gridworld.actor.Flower;
import info.gridworld.actor.Rock;
import info.gridworld.grid.Location;

import java.awt.Color;

/**
 * This class runs a world that contains critters. 
* This class is not tested on the AP CS A and AB exams. */ public class CritterRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(); world.add(new Location(7, 8), new Rock()); world.add(new Location(3, 3), new Rock()); world.add(new Location(2, 8), new Flower(Color.BLUE)); world.add(new Location(5, 5), new Flower(Color.PINK)); world.add(new Location(1, 5), new Flower(Color.RED)); world.add(new Location(7, 2), new Flower(Color.YELLOW)); world.add(new Location(4, 4), new Critter()); world.add(new Location(5, 8), new Critter()); world.show(); } }

Critter.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Cay Horstmann
 */

package info.gridworld.actor;

import info.gridworld.grid.Location;

import java.util.ArrayList;

/**
 * A Critter is an actor that moves through its world, processing
 * other actors in some way and then moving to a new location. Define your own
 * critters by extending this class and overriding any methods of this class
 * except for act. When you override these methods, be sure to
 * preserve the postconditions. 
* The implementation of this class is testable on the AP CS A and AB exams. */ public class Critter extends Actor { /** * A critter acts by getting a list of other actors, processing that list, * getting locations to move to, selecting one of them, and moving to the * selected location. */ public void act() { if (getGrid() == null) return; ArrayList actors = getActors(); processActors(actors); ArrayList moveLocs = getMoveLocations(); Location loc = selectMoveLocation(moveLocs); makeMove(loc); } /** * Gets the actors for processing. Implemented to return the actors that * occupy neighboring grid locations. Override this method in subclasses to * look elsewhere for actors to process.
* Postcondition: The state of all actors is unchanged. * @return a list of actors that this critter wishes to process. */ public ArrayList getActors() { return getGrid().getNeighbors(getLocation()); } /** * Processes the elements of actors. New actors may be added * to empty locations. Implemented to "eat" (i.e. remove) selected actors * that are not rocks or critters. Override this method in subclasses to * process actors in a different way.
* Postcondition: (1) The state of all actors in the grid other than this * critter and the elements of actors is unchanged. (2) The * location of this critter is unchanged. * @param actors the actors to be processed */ public void processActors(ArrayList actors) { for (Actor a : actors) { if (!(a instanceof Rock) && !(a instanceof Critter)) a.removeSelfFromGrid(); } } /** * Gets a list of possible locations for the next move. These locations must * be valid in the grid of this critter. Implemented to return the empty * neighboring locations. Override this method in subclasses to look * elsewhere for move locations.
* Postcondition: The state of all actors is unchanged. * @return a list of possible locations for the next move */ public ArrayList getMoveLocations() { return getGrid().getEmptyAdjacentLocations(getLocation()); } /** * Selects the location for the next move. Implemented to randomly pick one * of the possible locations, or to return the current location if * locs has size 0. Override this method in subclasses that * have another mechanism for selecting the next move location.
* Postcondition: (1) The returned location is an element of * locs, this critter's current location, or * null. (2) The state of all actors is unchanged. * @param locs the possible locations for the next move * @return the location that was selected for the next move. */ public Location selectMoveLocation(ArrayList locs) { int n = locs.size(); if (n == 0) return getLocation(); int r = (int) (Math.random() * n); return locs.get(r); } /** * Moves this critter to the given location loc, or removes * this critter from its grid if loc is null. * An actor may be added to the old location. If there is a different actor * at location loc, that actor is removed from the grid. * Override this method in subclasses that want to carry out other actions * (for example, turning this critter or adding an occupant in its previous * location).
* Postcondition: (1) getLocation() == loc. (2) The state of * all actors other than those at the old and new locations is unchanged. * @param loc the location to move to */ public void makeMove(Location loc) { if (loc == null) removeSelfFromGrid(); else moveTo(loc); } }

ChameleonCritter (set 8)

Before you try to answer the Set 8 Questions, get the next two files and see how this subclass of Critter works. Note how only certain methods are overloaded, and the act method is untouched.

ChameleonCritter.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 * @author Cay Horstmann
 */

import info.gridworld.actor.Actor;
import info.gridworld.actor.Critter;
import info.gridworld.grid.Location;

import java.util.ArrayList;

/**
 * A ChameleonCritter takes on the color of neighboring actors as
 * it moves through the grid. 
* The implementation of this class is testable on the AP CS A and AB exams. */ public class ChameleonCritter extends Critter { /** * Randomly selects a neighbor and changes this critter's color to be the * same as that neighbor's. If there are no neighbors, no action is taken. */ public void processActors(ArrayList actors) { int n = actors.size(); if (n == 0) return; int r = (int) (Math.random() * n); Actor other = actors.get(r); setColor(other.getColor()); } /** * Turns towards the new location as it moves. */ public void makeMove(Location loc) { setDirection(getLocation().getDirectionToward(loc)); super.makeMove(loc); } }

ChameleonRunner.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 * @author Cay Horstmann
 */

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Rock;
import info.gridworld.grid.Location;

import java.awt.Color;

/**
 * This class runs a world that contains chameleon critters. 
* This class is not tested on the AP CS A and AB exams. */ public class ChameleonRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(); world.add(new Location(7, 8), new Rock()); world.add(new Location(3, 3), new Rock()); world.add(new Location(2, 8), new Rock(Color.BLUE)); world.add(new Location(5, 5), new Rock(Color.PINK)); world.add(new Location(1, 5), new Rock(Color.RED)); world.add(new Location(7, 2), new Rock(Color.YELLOW)); world.add(new Location(4, 4), new ChameleonCritter()); world.add(new Location(5, 8), new ChameleonCritter()); world.show(); } }

CrabCritters (set 9)

CrabCritter.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 * @author Cay Horstmann
 */

import info.gridworld.actor.Actor;
import info.gridworld.actor.Critter;
import info.gridworld.grid.Grid;
import info.gridworld.grid.Location;

import java.awt.Color;
import java.util.ArrayList;

/**
 * A CrabCritter looks at a limited set of neighbors when it eats and moves.
 * 
* This class is not tested on the AP CS A and AB exams. */ public class CrabCritter extends Critter { public CrabCritter() { setColor(Color.RED); } /** * A crab gets the actors in the three locations immediately in front, to its * front-right and to its front-left * @return a list of actors occupying these locations */ public ArrayList getActors() { ArrayList actors = new ArrayList(); int[] dirs = { Location.AHEAD, Location.HALF_LEFT, Location.HALF_RIGHT }; for (Location loc : getLocationsInDirections(dirs)) { Actor a = getGrid().get(loc); if (a != null) actors.add(a); } return actors; } /** * @return list of empty locations immediately to the right and to the left */ public ArrayList getMoveLocations() { ArrayList locs = new ArrayList(); int[] dirs = { Location.LEFT, Location.RIGHT }; for (Location loc : getLocationsInDirections(dirs)) if (getGrid().get(loc) == null) locs.add(loc); return locs; } /** * If the crab critter doesn't move, it randomly turns left or right. */ public void makeMove(Location loc) { if (loc.equals(getLocation())) { double r = Math.random(); int angle; if (r < 0.5) angle = Location.LEFT; else angle = Location.RIGHT; setDirection(getDirection() + angle); } else super.makeMove(loc); } /** * Finds the valid adjacent locations of this critter in different * directions. * @param directions - an array of directions (which are relative to the * current direction) * @return a set of valid locations that are neighbors of the current * location in the given directions */ public ArrayList getLocationsInDirections(int[] directions) { ArrayList locs = new ArrayList(); Grid gr = getGrid(); Location loc = getLocation(); for (int d : directions) { Location neighborLoc = loc.getAdjacentLocation(getDirection() + d); if (gr.isValid(neighborLoc)) locs.add(neighborLoc); } return locs; } }

CrabRunner.java

/* 
 * AP(r) Computer Science GridWorld Case Study:
 * Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * @author Chris Nevison
 * @author Barbara Cloud Wells
 * @author Cay Horstmann
 */

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Bug;
import info.gridworld.actor.Flower;
import info.gridworld.actor.Rock;
import info.gridworld.grid.Location;

/**
 * This class runs a world that contains crab critters. 
* This class is not tested on the AP CS A and AB exams. */ public class CrabRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(); world.add(new Location(7, 5), new Rock()); world.add(new Location(5, 4), new Rock()); world.add(new Location(5, 7), new Rock()); world.add(new Location(7, 3), new Rock()); world.add(new Location(7, 8), new Flower()); world.add(new Location(2, 2), new Flower()); world.add(new Location(3, 5), new Flower()); world.add(new Location(3, 8), new Flower()); world.add(new Location(6, 5), new Bug()); world.add(new Location(5, 3), new Bug()); world.add(new Location(4, 5), new CrabCritter()); world.add(new Location(6, 1), new CrabCritter()); world.add(new Location(7, 4), new CrabCritter()); world.show(); } }
  1. Why doesn't CrabCritter override the processActors method?
  2. Describe the process a CrabCritter uses to find and eat other actors. Does it always eat all neighboring actors? Explain.
  3. Why is the getLocationsInDirections method used in CrabCritter?
  4. If a CrabCritter has location (3, 4) and faces south, what are the possible locations for actors that are returned by a call to the getActors method?
  5. What are the similarities and differences between the movements of a CrabCritter and a Critter?
  6. How does a CrabCritter determine when it turns instead of moving?
  7. Why don't the CrabCritter objects eat each other?

Exercises

DarkeningChameleonCritter.java

AgingCameleon.java

import java.util.ArrayList;
import java.awt.Color;
import info.gridworld.actor.*;
public class AgingChameleon extends ChameleonCritter
{
	// instance variables - replace the example below with your own
	private double DARKENING_FACTOR; 


	
	public AgingChameleon()
	{
		DARKENING_FACTOR = 0.05;
	}

	/** 
 * Randomly selects a neighbor and changes this critter's color to be the 
 * same as that neighbor's. If there are no neighbors, no action is taken. 
 */ 
public void processActors(ArrayList actors) 
{ 
  int n = actors.size(); 
  if (n == 0) 
  { 
    darken(); 
    return; 
  } 
             
  int r = (int) (Math.random() * n); 
  Actor other = actors.get(r); 
  setColor(other.getColor()); 
} 
  
/** 
 * Darkens this critter's color by DARKENING_FACTOR. 
 */     
private void darken() 
{ 
  Color c = getColor(); 
  int red = (int) (c.getRed() * (1 - DARKENING_FACTOR)); 
  int green = (int) (c.getGreen() * (1 - DARKENING_FACTOR)); 
  int blue = (int) (c.getBlue() * (1 - DARKENING_FACTOR)); 
 
  setColor(new Color(red, green, blue));    
}  
}

CameleonRunner.java

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Rock;
import info.gridworld.grid.Location;

import java.awt.Color;

/**
 * This class runs a world that contains chameleon critters. 
* This class is not tested on the AP CS A and AB exams. */ public class ChameleonRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(); world.add(new Location(5, 5), new Rock(Color.PINK)); world.add(new Location(7, 2), new Rock(Color.YELLOW)); world.add(new Location(4, 4), new AgingChameleon()); world.add(new Location(5, 8), new AgingChameleon()); world.show(); } }

ChameleonKid.java

/**
 * Override the getActors method to only return actors that are in front and behind the 
 * ChameleonCritterKid. This solution uses the getLocationsInDirections method found in 
 * CrabCritter to find the actors in the required directions and uses the CrabCritterÕs version of 
 * getActors. 
 */

 
import info.gridworld.actor.Actor; 
import info.gridworld.actor.Critter; 
import info.gridworld.actor.Flower; 
import info.gridworld.grid.Location; 
import info.gridworld.grid.Grid; 
 
import java.util.ArrayList; 
 
/** 
 * A ChameleonKid takes on the color of neighboring actors  
 * that are in front or behind as it moves through the grid. 
*/ public class ChameleonKid extends ChameleonCritter { /** * Gets the actors for processing. The actors must be contained in the * same grid as this critter. Implemented to return the actors that * occupy neighboring grid locations in front or behind this critter. * @return a list of actors that are neighbors of this critter */ public ArrayList getActors() { ArrayList actors = new ArrayList(); int[] dirs = { Location.AHEAD, Location.HALF_CIRCLE }; for (Location loc : getLocationsInDirections(dirs)) { Actor a = getGrid().get(loc); if (a != null) actors.add(a); } return actors; } /** * Finds the valid adjacent locations of this critter in different * directions. * @param directions - an array of directions (which are relative to the * current direction) * @return a set of valid locations that are neighbors of the current * location in the given directions */ public ArrayList getLocationsInDirections(int[] directions) { ArrayList locs = new ArrayList(); Grid gr = getGrid(); Location loc = getLocation(); for (int d : directions) { Location neighborLoc = loc.getAdjacentLocation(getDirection() + d); if (gr.isValid(neighborLoc)) locs.add(neighborLoc); } return locs; } }

RockHound.java

/*
 * Override processActors to remove all rocks 
 * from the list of neighboring locations. 
 */
import info.gridworld.actor.Actor; 
import info.gridworld.actor.Rock; 
import info.gridworld.actor.Critter; 
import info.gridworld.grid.Location; 
 
import java.util.ArrayList; 
 
public class RockHound extends Critter 
{ 
  /** 
   * Processes the actors. Implemented to "eat" (i.e. remove) all rocks  
   * 
* Precondition: All objects in actors are contained in the * same grid as this critter. * @param actors the actors to be processed */ public void processActors(ArrayList actors) { for (Actor a : actors) { if (a instanceof Rock) a.removeSelfFromGrid(); } } }

BlusterCritter.java

Override the getActors and processActors methods to create the new behavior required of the BlusterCritter. Create two new methods to lighten and darken the color of the BlusterCritter. To darken a BlusterCritter, subtract one from the red, green, and blue components as long as they are greater than 0 (or use the same process as the Flower class to darken the critter). To lighten a BlusterCritter, add one to the red, green, and blue components as long as they are less than 255.

import info.gridworld.actor.Actor; 
import info.gridworld.actor.Rock; 
import info.gridworld.actor.Critter; 
 
import info.gridworld.grid.Location; 
 
import java.util.ArrayList; 
import java.awt.Color; 
 
public class BlusterCritter extends Critter 
{ 
 
  private int courageFactor;  
  
  public BlusterCritter(int c) 
  { 
    super(); 
    courageFactor = c; 
  } 
/** 
   * Gets the actors for processing. The actors must be contained in the  
   * same grid as this critter. Implemented to return the actors that  
   * occupy neighboring grid locations within two steps of this critter 
   * @return a list of actors that are neighbors of this critter 
   */ 
  public ArrayList getActors() 
  { 
    ArrayList actors = new ArrayList(); 
         
    Location loc = getLocation(); 
    for(int r = loc.getRow() - 2; r <= loc.getRow() + 2; r++ ) 
      for(int c = loc.getCol() - 2; c <= loc.getCol() + 2; c++) 
      { 
        Location tempLoc = new Location(r,c); 
        if(getGrid().isValid(tempLoc)) 
        { 
          Actor a = getGrid().get(tempLoc); 
          if(a != null && a != this) 
            actors.add(a); 
        } 
      } 
    return actors;     
  } 
 
  /** 
   * Processes the actors. Implemented to count all the actors within 
   * 2 locations of this critter.  If there are fewer than courageFactor 
   * critters in these locations, this BlusterCritter lightens, otherwise 
   * it darkens. 
   * Precondition: All objects in actors are contained in the 
   * same grid as this critter. 
   * @param actors the actors to be processed 
   */ 
  public void processActors(ArrayList actors) 
  { 
    int count = 0; 
    for(Actor a: actors) 
    if(a instanceof Critter) 
      count++; 
    if(count < courageFactor) 
      lighten(); 
    else 
      darken(); 
  } 
/** 
   * Darkens this critter's color by subtracting 1 from red, green, and  
   * blue components if they are greater than 0. To darken the color  
   * faster, subtract a slightly larger value. 
   */ 
  private void darken() 
  { 
    Color c = getColor(); 
    int red = c.getRed(); 
    int green = c.getGreen(); 
    int blue = c.getBlue(); 
 
    if(red > 0) red--; 
    if(green > 0) green--; 
    if(blue > 0) blue--; 
 
    setColor(new Color(red, green, blue));    
        
 
    // this segment of code uses same logic as the flower class to darken  
    // an object's color  
    // to use this technique add DARKENING_FACTOR as a class instance  
    // variable; then replace the active code for darken with the  
    // following five lines of code 
 
    // private static final double DARKENING_FACTOR = 0.05; 
 
    // Color c = getColor(); 
    // int red = (int) (c.getRed() * (1 - DARKENING_FACTOR)); 
    // int green = (int) (c.getGreen() * (1 - DARKENING_FACTOR)); 
    // int blue = (int) (c.getBlue() * (1 - DARKENING_FACTOR)); 
 
    // setColor(new Color(red, green, blue));    
  } 
  /* 
   * Lightens this critter's color by adding 1 to the red, green, and blue
   * components if they are less than 255. To lighten the color faster,  
   * add a slightly larger value. 
   */ 
  private void lighten() 
  { 
    Color c = getColor(); 
    int red = c.getRed(); 
    int green = c.getGreen(); 
    int blue = c.getBlue(); 
 
    if(red < 255) red++; 
    if(green < 255) green++; 
    if(blue < 255) blue++; 
 
    setColor(new Color(red, green, blue));    
  }  
} 
 

 

QuickCrab.java

This solution overrides the getMoveLocations method. In this solution, an additional method was created to find good locations two spaces away and add them to the ArrayList that getMoveLocations returns.
import info.gridworld.actor.Actor; 
import info.gridworld.actor.Critter; 
import info.gridworld.grid.Grid; 
import info.gridworld.grid.Location; 
 
import java.awt.Color; 
import java.util.ArrayList; 
 
/** 
 * A QuickCrab looks at a limited set of neighbors when it  
 * eats and moves.
*/ public class QuickCrab extends CrabCritter { public QuickCrab() { setColor(Color.CYAN); } /** * @return list of empty locations * two locations to the right and two locations to the left */ public ArrayList getMoveLocations() { ArrayList locs = new ArrayList(); Grid g = getGrid(); addIfGoodTwoAwayMove(locs,getDirection() + Location.LEFT); addIfGoodTwoAwayMove(locs,getDirection() + Location.RIGHT); if (locs.size() == 0) return super.getMoveLocations(); return locs; } /** * Adds a valid and empty two away location in direction dir to the * ArrayList locs. * To be a valid two away location, the location that is one away in * direction dir must also be valid and empty. */ private void addIfGoodTwoAwayMove(ArrayList locs,int dir) { Grid g = getGrid(); Location loc = getLocation(); Location temp = loc.getAdjacentLocation(dir); if(g.isValid(temp) && g.get(temp) == null) { Location loc2 = temp.getAdjacentLocation(dir); if(g.isValid(loc2) && g.get(loc2)== null) locs.add(loc2); } } }

KingCrab.java

This solution overrides the processActors method. This solution also includes two new methods, distanceFrom and moveOneMoreAway, to move an actor away from the KingCrab.
import info.gridworld.actor.Actor; 
import info.gridworld.actor.Critter; 
import info.gridworld.grid.Grid; 
import info.gridworld.grid.Location; 
 
import java.awt.Color; 
import java.util.ArrayList; 
 
/** 
 * A KingCrab looks at a limited set of neighbors when it  
 * eats and moves.
*/ public class KingCrab extends CrabCritter { public KingCrab() { setColor(Color.PINK); } /** * Computes the rounded integer distance between two given locations. */ public int distanceFrom(Location loc1, Location loc2) { int x1 = loc1.getRow(); int y1 = loc1.getCol(); int x2 = loc2.getRow(); int y2 = loc2.getCol(); double dist = Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) + .5; return (int)Math.floor(dist); } /* * This method moves the Actor to a location that is one location * further away from this KingCrab and returns true. If there is no * location that is one location further away, the method returns false. */ private boolean moveOneMoreAway(Actor a) { ArrayList locs = getGrid().getEmptyAdjacentLocations(a.getLocation()); for(Location loc:locs) { if(distanceFrom(getLocation(), loc) > 1) { a.moveTo(loc); return true; } } return false; } /* * Each actor in the list actors is told to move one location further * away from this KingCrab. If that is not possible, the actor is * removed from the grid. */ public void processActors(ArrayList actors) { for (Actor a : actors) { if (!moveOneMoreAway(a)) { a.removeSelfFromGrid(); } } } }

Set 10-12 Questions

After you understand these subclasses of Critter, try answering the questions in Sets 10, 11 and 12 in the Student Manual.

Group Activity

  1. Specify: Each group specifies a new creature that extends Critter. The specifications must describe the properties and behavior of the new creature in detail.
  2. Design: The groups exchange specifications. Each group reads the specification that it received and determines the needed variables and basic algorithms for the creature.
  3. Code: Each group implements the code for the creature in the specification that it received.
  4. Test: Each group writes test cases for the creature that it specified in step 1. Test cases are exchanged as in step 2. The recipients verify that the implementations meet the specifications.

Good Luck!

Ok! That's all there is to know! Now it is a matter of practicing and learning how to answer the questions that will ask you to peice together new Actors, Bugs and Critters from these handy tools!