Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

*In Java* DETAILS create an Interface that lists constants and abstract methods

ID: 3759211 • Letter: #

Question

*In Java*

DETAILS create an Interface that lists constants and abstract methods to be implemented by various Critter classes, an Abstract class which partially implements one of the Interface’s abstract methods that is identical for any of the Critter classes as well as a related Instance field and Constructor, and finally, 6 classes that represent various Critters (actually, one is an inanimate Stone) that have basic movement characteristics. All 6 Critter classes will inherit (extend) the Abstract class mentioned. Like with the previous assignment, one major purpose of inheritance is to eliminate redundant code. For this reason you should take full advantage of super class code or methods when developing your subclasses. In this case, the super class will be this Abstract class. Always remember to use final constants in place of any literal constants (anything other than 0 & 1) you would normally use in your code! Greater detail of each class follows:

1. Critter.java public interface Critter Describes what methods to be implemented by Critter subclasses and includes several constants.

Finals: Here you will define 5 int constants (final) for the direction an animal can move. The names for each of these will HAVE TO BE as follows (the model expects these names): NORTH WEST SOUTH EAST CENTER

You can assign any values to them as you see fit, as long as each is unique (may I suggest simply 0, 1, 2, 3, 4 respectively)

Fields: None. Interfaces can not be instantiated and thus, cannot contain instance fields.

Abstract Methods: (the only type of method that can exist in an Interface). These must have the following header signatures: public char getChar(); public int getMove(CritterInfo theInfo);

(CritterInfo is an interface already defined and used by an inner class of the CritterModel class. 5 of the Critter classes will simply not use this parameter. However, the Frog class uses the getNeighbor method via the theInfo parameter, discussed in the Frog.java details)

2. AbstractCritter.java public abstract class AbstractCritter implements Critter Declares an Instance variable that all subclasses must have, a constructor to initialize the instance variable, and implements the getChar method (this way this method is only implemented once and to be inherited by all Critter subclasses).

Fields: A private char field to hold the single character which represents a particular Critter and is used for display on the Critter Environment Grid (fancy name for what you see in the JPanel of the GUI).

Constructor – public AbstractCritter(final char theChar) Assigns theChar to the Instance Field (This has to be called by all subclasses to set the correct character for the class).

Abstract Methods: None declared here. The responsibility to Implement the getMove method from Critter is passed down to the inheriting subclasses as getMove has to be unique within each Critter subclass.

Non Abstract Methods/Implemented methods from the Critter Interface: public char getChar() { // Your code goes here. }

Returns the Instance Field.

3. Stone.java public class Stone extends AbstractCritter Stone is the only inanimate Critter. Several Stone objects are placed on the simulation grid during the initial instantiation and remain stationary throughout the simulation. All but one Critter dies when crashing into a Stone. Frog never moves to where a Stone is and waits until it moves elsewhere. Details to follow.

Constructor – public Stone( ) Calls the super constructor passing it an UPPERCASE S: ‘S’ char to initialize the super’s instance field.

Implemented methods from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) { // Since Stones never move this should simply return CENTER. }

4. Bat.java public class Bat extends AbstractCritter Bats have rather erratic behavior as they flutter about catching flying insects. Their direction appears random, flying in one of the 4 constant directions (CENTER is not an option since they can’t really hover).

Constructor – public Bat( ) Calls the super constructor passing it an uppercase B: ‘B’ char to initialize the super’s instance field.

Implemented method from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) { // Randomly chooses and returns one of the 4 directions: NORTH, WEST, SOUTH, EAST, each // having a 25% chance of being chosen. . }

5. Wolf.java public class Wolf extends AbstractCritter Because they are pack animals, their movement is somewhat consistent and is done in parallel with all wolves. However, they tend to travel in straight directions for some time before changing. This will require several fields to create a pattern of behavior:

Fields (all initializations are done in the Constructor & all fields should be private): myDirection: int to remember the current direction. Initialized to EAST. myCount: int to count the number of moves before a change of direction. Initialized to 0. myFirst: boolean toggles (true/false) whenever a change of direction takes place. Initialize to true. myTarget: int Details of its use is described in getMove below. Initialized to 1.

Constructor – public Wolf( ) Calls the super constructor passing it an UPPERCASE W: ‘W’ char to initialize the super’s instance field. Initialize the 4 fields to the values mentioned above.

Implemented methods from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) {

/* Begin by setting a local int variable (let’s say direction) to myDirection. This will be returned as is and not changed until the next time getMove is called. Next, increment the myCount, then: when myCount reaches myTarget, several things will happen: if myFirst is false, myTarget should be incremented. toggle myFirst to the opposite state (i.e.false to true, true to false) myCount is reset to 0 myDirection is changed (in a counterclockwise direction, i.e. if myDirection is EAST, set it to NORTH, if NORTH, set to WEST, etc. Of course, this change is what will be assigned the local direction variable next time getMove is called. return the local direction variable value. */ }

6. Mouse.java public class Mouse extends AbstractCritter Mice move in a zigzag (right-left-right-left, etc.) motion. Their overall direction then is NORTH-WEST-NORTHWEST, or WEST-SOUTH-WEST-SOUTH, or SOUTH-EAST... etc.. The general direction of this zigzag motion should be chosen at random intervals. How you go about accomplishing this will be up to you but, try to maintain a specific direction for some time.

Fields (all initializations are done in the Constructor & all fields should be private): You will have to decide just what you need here in order to fulfill the zigzag/random direction of a Mouse.

Constructor – public Mouse( ) Calls the super constructor passing it an UPPERCASE M: ‘M’ char to initialize the super’s instance field. Initialize all other Mouse class instance fields.

Implemented methods from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) {

/* Like the Wolf and Bat, the movement of the mouse will be determined by what getMove returns (NORTH, WEST, SOUTH, EAST) to the calling model object (the program using your Critter classes. */ }

7. Turtle.java public class Turtle extends AbstractCritter As we all know, turtles move rather slowly. As such, they will only move 1/3 as many times as all other Critters (excluding the Stone, of course, which doesn’t move at all). The Turtle getMove method can return a direction of CENTER as needed, which will keep it from moving.

Also, each Turtle object will make its first (following instantiation) actual move (none CENTER) based on some randomly chosen value (NORTH, WEST, SOUTH, EAST) and each Turtle will begin movement following some randomly chosen interval (they will not all start moving at the same time).

When a Turtle does move (every 3 calls to getMove), if one randomly chosen boolean value is true and a second randomly chosen int value of: 0-1 -move NORTH 2-3 -move EAST 4 -move SOUTH 5-7 -move WEST 8-12 move CENTER If this randomly chosen boolean value is false, then the direction based on the second random (int) value is: 0-3 -move SOUTH 4-5 -move WEST 6-7 -move NORTH 8-10 -move EAST Note: The first group uses a range of 13 (0-12) & the second group uses a range of 11 (0-10) & doesn’t have CENTER.

Fields (all initializations are done in the Constructor & all fields should be private): Whatever you might need to satisfy the movement of a Turtle.

Constructor – public Turtle( ) Calls the super constructor passing it an UPPERCASE T: ‘T’ char to initialize the super’s instance field. Initialize all necessary instance fields of this class.

Implemented methods from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) { /* This is based on the rules for a Turtle mentioned above. */ }

8. Frog.java public class Frog extends AbstractCritter The movement of a frog is a bit less complicated than some of our other Critters. Frogs never jump into Stones and thus, never die unless encountering another Critter. Generally, a frog will continue in the same direction unless a counter (one of the fields) is zero. If the counter is zero then a random value should be chosen (in this case, use the Math.random() which returns a double in the range of 0..1.0 (1.0 exclusive). If the result is < 0.25, your direction field should be set to NORTH, else if < 0.5, go SOUTH, < .75, go EAST otherwise go WEST (Remember, this change of direction only occurs when the counter is zero).

All other random number generation (for the other Critters) can use the Random class (returns int in a specified range) of which we are most familiar.

After the test for counter == 0 and the above mentioned direction change, the counter should be incremented, then checked to see if it equals 3. If so, reset it to zero (this will be noted the next time getMove is called on the Frog.

Next, if the neighbor of the Frog (based on the current direction) is the Stone (see code below for example of using theInfo class getNeighbor method), getMove should set the returning value to CENTER (thus keeping the frog from encountering a Stone). Otherwise, the return value should be set to the current direction (This suggests a local variable used to avoid multiple return statements. Finally, return this value. Your code inside getMove of Frog based on the previous discussion and the use of getNeighbor: . . . if (theInfo.getNeighbor(myDirection) == 'S') { result = CENTER; // If a Stone, sit still. }else { result = myDirection; } return result; }

Fields (all initializations are done in the Constructor & all fields should be private): myDirection: int to remember the current direction. myCount: int to count the number of moves before a change of direction.

Constructor – public Frog( ) Calls the super constructor passing it an UPPERCASE F: ‘F’ char to initialize the super’s instance field. myDirection: Initialized to CENTER. myCount: Initialized to 0.

Implemented method from the Critter Interface: Implements the super getMove method: public int getMove(CritterInfo theInfo) { /* This is based on the discussion above (previous page). */ }

Whenever Critters collide, one will pass on and will be eliminated from the simulation. All Critters except Frogs will die when they run into a Stone. These unfortunate occurrences are implemented in the Model portion of the simulation and should not be a concern of the Critter related classes.

Explanation / Answer

Provided Java code for Interfaces (Critter, CritterInfo), Classes (Stone, Bat, Wolf, Mouses, Turtle, and Frog)  and abstract class (AbstractCritter) as per your requirements.

//Critter.java
public interface Critter
{
public final int NORTH = 0;
public final int WEST = 1;
public final int SOUTH = 2;
public final int EAST = 3;
public final int CENTER = 4;
//Abstract Methods
public char getChar();
public int getMove(CritterInfo theInfo);
}

//CritterInfo.java
public interface CritterInfo
{
public int getX();
public int getY();
public char getNeighbor(int direction);
public int getHeight();
public int getWidth();
}

//AbstractCritter.java
import java.util.Random;

public abstract class AbstractCritter implements Critter
{
private char criLetter;
private Random ranObj;

//Constructor
public AbstractCritter(final char theChar)
{
  criLetter = theChar;
  ranObj = new Random();
}
//Abstract Methods
public char getChar()
{
  return criLetter;
}
protected Random getRandomObj()
{
  return ranObj;
}
}
//Stone.java
public class Stone extends AbstractCritter
{
//Constructor
public Stone()
{
  // Construct super class.
  super('S');
}
//method definition of getMove
public int getMove(CritterInfo theInfo)
{
  return CENTER;
}
}

//Bat.java
public class Bat extends AbstractCritter
{

//Constructor
public Bat()
{
  super('B');
}

public int getMove(CritterInfo theInfo)
{
  int choice = getRandomObj().nextInt(4);
  int direction = -1;
  switch (choice)
  {
   case 0: direction = NORTH;
     break;
   case 1: direction = WEST;
     break;
   case 2: direction = SOUTH;
     break;
   case 3: direction = EAST;
     break;
  }
  return direction;
}
}

//Wolf.java
public class Wolf extends AbstractCritter
{

// Fields
private int myDirection;
private int myCount;
private boolean myFirst;
private int myTarget;

// Constructor
public Wolf() {

  super('W');
  myDirection = EAST;
  myCount = 0;
  myFirst = true;
  myTarget = 1;
}

public int getMove(CritterInfo theInfo) {
  int localDirection = myDirection;
  myCount++;
  if (myCount == myTarget) {

   if (!myFirst) {
    myTarget++;
   }
   myFirst = !myFirst;
   myCount = 0;
   if (++myDirection > 3) {
    myDirection = NORTH;
   }
  }
  return localDirection;
}
}

//Mouse.java
public class Mouse extends AbstractCritter
{
// Constants
private final int CARDINAL_POINTS = 4;
private final int MAX_DIAGONAL_TRAVEL = 50;

// Declare variables
private int myDirection;
private int myCount;
private int myTarget;
private boolean randomDirection;

// Constructor
public Mouse()
{
  super('M');
  myDirection = getRandomObj().nextInt(CARDINAL_POINTS);
  randomDirection = getRandomObj().nextBoolean();
  myCount = 0;
  myTarget = getRandomObj().nextInt(MAX_DIAGONAL_TRAVEL);
}

// Method definition of getMove
public int getMove(CritterInfo theInfo)
{
  int lDirection = myDirection;

  if (myCount != 0) {

   if (randomDirection) {

    if (!isEven(myCount)) {
     lDirection = myDirection + 1;

     if (lDirection > EAST) {
      lDirection = NORTH;
     }
    }
   } else {

    if (!isEven(myCount)) {
     lDirection = myDirection - 1;

     if (lDirection < NORTH) {
      lDirection = EAST;
     }
    }
   }
  }

  if (++myCount >= myTarget)
  {
   myDirection = getRandomObj().nextInt(CARDINAL_POINTS);
   randomDirection = getRandomObj().nextBoolean();
   myCount = 0;
   myTarget = getRandomObj().nextInt(MAX_DIAGONAL_TRAVEL);
  }
  return lDirection;
}
// Method definition of isEven
private boolean isEven(final int theValue)
{
  return (theValue % 2) == 0;
}
}

//Turtle.java
public class Turtle extends AbstractCritter {
private int myCount;

// Constructor
public Turtle()
{
  super('T');
  myCount = getRandomObj().nextInt(3);
}
//methods from the Critter Interface
public int getMove(CritterInfo theInfo)
{
  int lDirection = -1;
  boolean flag = getRandomObj().nextBoolean();
  int direction = getRandomObj().nextInt(4);
  if (myCount == 2) {
   if (flag) {
    switch (direction) {
    case 0:
     lDirection = NORTH;
     break;
    case 1:
     lDirection = EAST;
     break;
    case 2:
     lDirection = SOUTH;
     break;
    case 3:
     lDirection = WEST;
     break;
    default:
     break;
    }
   } else {
    switch (direction) {
    case 0:
     lDirection = SOUTH;
     break;
    case 1:
     lDirection = WEST;
     break;
    case 2:
     lDirection = NORTH;
     break;
    case 3:
     lDirection = EAST;
     break;
    default:
     break;
    }
   }
   myCount = 0;
  } else {
   lDirection = CENTER;
   myCount++;
  }
  return lDirection;
}
}

//Frog.java
public class Frog extends AbstractCritter
{
private int myDirection;
private int myCount;
// Constructor
public Frog()
{
  super('F');
  myDirection = CENTER;
  myCount = 0;
}
//method from the Critter Interface
public int getMove(CritterInfo theInfo) {

  double randomValue = getRandomObj().nextDouble();
  int lDirection = -1;
  if (myCount == 0) {
   if (isLessThan(randomValue, .25)) {
    myDirection = NORTH;
   } else if (isLessThan(randomValue, 0.5)
     && isGreaterThan(randomValue, 0.24)) {
    myDirection = SOUTH;
   } else if (isLessThan(randomValue, 0.75)
     && isGreaterThan(randomValue, 0.74)) {
    myDirection = EAST;
   } else {
    myDirection = WEST;
   }
  }

  if (++myCount > 3) {
   myCount = 0;
  }

  if (theInfo.getNeighbor(myDirection) == 'S') {
   lDirection = CENTER;
  } else {
   lDirection = myDirection;
  }
  return lDirection;
}

private boolean isLessThan(double theFirst, double theSecond) {
  return Double.compare(theFirst, theSecond) < 0;
}

private boolean isGreaterThan(final double theFirst, final double theSecond) {
  return Double.compare(theFirst, theSecond) > 0;
}
}