Here is an example implementation of the five classes:
```java
import java.util.Random;
public abstract class Critter {
protected int x; // x-coordinate on the grid
protected int y; // y-coordinate on the grid
public Critter() {
this.x = 0;
this.y = 0;
}
public abstract char getChar();
public abstract int getMove();
public void move() {
int move = getMove();
switch (move) {
case 0: // North
this.y = (this.y - 1 + Grid.HEIGHT) % Grid.HEIGHT;
break;
case 1: // East
this.x = (this.x + 1) % Grid.WIDTH;
break;
case 2: // South
this.y = (this.y + 1) % Grid.HEIGHT;
break;
case 3: // West
this.x = (this.x - 1 + Grid.WIDTH) % Grid.WIDTH;
break;
}
}
}
public class Bird extends Critter {
private Random random;
public Bird() {
super();
this.random = new Random();
}
@Override
public char getChar() {
return 'B';
}
@Override
public int getMove() {
return random.nextInt(4);
}
}
public class Frog extends Critter {
private Random random;
private int moveCounter;
public Frog() {
super();
this.random = new Random();
this.moveCounter = 0;
}
@Override
public char getChar() {
return 'F';
}
@Override
public int getMove() {
if (moveCounter == 0) {
moveCounter = 3;
return random.nextInt(4);
} else {
moveCounter--;
return -1; // Stay in the same direction
}
}
}
public class Mouse extends Critter {
private int moveCounter;
public Mouse() {
super();
this.moveCounter = 0;
}
@Override
public char getChar() {
return 'M';
}
@Override
public int getMove() {
switch (moveCounter % 4) {
case 0: // West
return 3;
case 1: // North
return 0;
case 2: // East
return 1;
case 3: // South
return 2;
}
return -1;
}
@Override
public void move() {
super.move();
moveCounter++;
}
}
public class Turtle extends Critter {
private int moveCounter;
public Turtle() {
super();
this.moveCounter = 0;
}
@Override
public char getChar() {
return 'T';
}
@Override
public int getMove() {
switch (moveCounter % 20) {
case 0: case 1: case 2: case 3: case 4: // South
return 2;
case 5: case 6: case 7: case 8: case 9: // West
return 3;
case 10: case 11: case 12: case 13: case 14: // North
return 0;
case 15: case 16: case 17: case 18: case 19: // East
return 1;
}
return -1;
}
@Override
public void move() {
super.move();
moveCounter++;
}
}
public class Grid {
public static final int WIDTH = 10;
public static final int HEIGHT = 10;
private Critter[][] grid;
public Grid() {
this.grid = new Critter[WIDTH][HEIGHT];
}
public void addCritter(Critter critter) {
int x = critter.x;
int y = critter.y;
grid[x][y] = critter;
}
public void removeCritter(Critter critter) {
int x = critter.x;
int y = critter.y;
grid[x][y] = null;
}
public void update() {
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
Critter critter = grid[i][j];
if (critter != null) {
critter.move();
}
}
}
}
public void display() {
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
Critter critter = grid[i][j];
if (critter != null) {
System.out.print(critter.getChar() + " ");
} else {
System.out.print("- ");
}
}
System.out.println();
}
}
}
public class Main {
public static void main(String[] args) {
Grid grid = new Grid();
Critter bird = new Bird();
Critter frog = new Frog();
Critter mouse = new Mouse();
Critter turtle = new Turtle();
grid.addCritter(bird);
grid.addCritter(frog);
grid.addCritter(mouse);
grid.addCritter(turtle);
for (int i = 0; i < 10; i++) {
grid.update();
grid.display();
System.out.println();
}
}
}
```
This implementation creates a `Critter` abstract class which defines the basic behavior of a critter and provides common methods for moving and updating the critter's position. Each critter class (`Bird`, `Frog`, `Mouse`, `Turtle`) extends the `Critter` class and overrides the `getChar` and `getMove` methods based on their specific behavior. The `Grid` class manages the grid and tracks the critters. In the `Main` class, a grid is created, critters are added to it, and then the grid is updated and displayed for 10 rounds.
Critters move around in a world of finite size, but the word is toroidal (going off the end to the right brings you back to the left and vice versa; going off the end to the top brings you back to the bottom and vice versa).
You are allowed to include a constructor for your classes if you want, although it must be a zero-argument constructors (one that takes no arguments).
You are to implement five classes. The behavior of each class is described below.
Class
getChar
getMove
Bird
B
Randomly selects one of the four directions each time
Frog
F
Picks a random direction, moves 3 in that direction, repeat (same as bird, but staying in a single direction longer)
Mouse
M
West 1, north 1, repeat (zig zag to the NW)
Turtle
T
South 5, west 5, north 5, east 5, repeat (clockwise box)
1 answer