import uwcse.graphics.*;
import java.awt.Point;
import java.util.*;
import java.awt.Color;
/**
* A Caterpillar is the representation and the display of a caterpillar
*/
public class Caterpillar implements CaterpillarGameConstants {
// The body of a caterpillar is made of Points stored
// in an ArrayList
private ArrayList body = new ArrayList();
// Store the graphical elements of the caterpillar body
// Useful to erase the body of the caterpillar on the screen
private ArrayList bodyUnits = new ArrayList();
// The window the caterpillar belongs to
private GWindow window;
// Direction of motion of the caterpillar (NORTH initially)
private int dir = NORTH;
/**
* Constructs a caterpillar
*
* @param window
* the graphics where to draw the caterpillar.
*/
public Caterpillar(GWindow window) {
// Initialize the graphics window for this Caterpillar
this.window = window;
// Create the caterpillar (10 points initially)
// First point
Point p = new Point();
p.x = 5;
p.y = WINDOW_HEIGHT / 2;
body.add(p);
// Other points
for (int i = 0; i < 9; i++) {
Point q = new Point(p);
q.translate(STEP, 0);
body.add(q);
p = q;
}
// Other initializations (if you have more instance fields)
for (int i = 0; i < body.size() - 1; i++) {
Point p1 = (Point) body.get(i);
Point p2 = (Point) body.get(i + 1);
addBodyUnit(p1, p2);
}
// Display the caterpillar (call a private method)
display();
}
/**
* Moves the caterpillar in the current direction (complete)
*/
public void move() {
move(dir);
}
/**
* Move the caterpillar in the direction newDir.
* If the new direction is illegal, select randomly a legal direction of
* motion and move in that direction.
*
* @param newDir
* the new direction.
*/
public void move(int newDir) {
// true if we haven't tried the current direction yet
boolean firstTry = true;
boolean isInvalidMove;
int[] direction = { NORTH, SOUTH, EAST, WEST };
do {
// Compute the new location of the head of the caterpillar
Point head = getHead();
switch (newDir) {
case NORTH:
head.y -= STEP;
break;
case WEST:
head.x -= STEP;
break;
case SOUTH:
head.y += STEP;
break;
case EAST:
head.x += STEP;
break;
}
// if the head is no longer in the window, select a new direction
isInvalidMove = !isInWindow(head);
if (isInvalidMove) {
if (firstTry) { // first try the current direction
newDir = dir;
firstTry = false;
} else { // random selection
newDir = direction[(int) (Math.random() * 4)];
}
} else { // valid move
body.add(head);
body.remove(0);
window.remove((Shape) bodyUnits.remove(0));
addBodyUnit((Point) body.get(body.size() - 2), (Point) body
.get(body.size() - 1));
window.add((Shape) bodyUnits.get(bodyUnits.size() - 1));
dir = newDir;
}
} while (isInvalidMove);
}
/**
* Is the caterpillar crawling over itself?
*
* @return true if the caterpillar is crawling over itself and false
* otherwise.
*/
public boolean isCrawlingOverItself() {
// Is the head point equal to any other point of the caterpillar?
Point head = getHead();
for (int i = 0; i <= body.size() - 2; i ++) {
Point p = (Point) body.get(i);
if (p.equals(head)) {
return true;
}
}
return false; // CHANGE THIS!
}
/**
* Are all of the points of the caterpillar outside the garden
*
* @return true if the caterpillar is outside the garden and false
* otherwise.
*/
public boolean isOutsideGarden() {
return false; // CHANGE THIS!
}
/**
* Return the location of the head of the caterpillar (complete)
*
* @return the location of the head of the caterpillar.
*/
public Point getHead() {
return new Point((Point) body.get(body.size() - 1));
}
/**
* Increase the length of the caterpillar (by GROWTH_SPURT elements) Add the
* elements at the tail of the caterpillar.
*/
public void grow() {
}
/**
* Add a body unit to the caterpillar
*/
private void addBodyUnit(Point p, Point q) {
// Create a rectangle between p and q
Rectangle r;
if (p.y == q.y) { // horizontal rectangle
r = new Rectangle(Math.min(p.x, q.x), p.y - CATERPILLAR_WIDTH / 2,
STEP, CATERPILLAR_WIDTH, Color.RED, true);
} else { // vertical rectangle
r = new Rectangle(p.x - CATERPILLAR_WIDTH / 2, Math.min(p.y, q.y),
CATERPILLAR_WIDTH, STEP, Color.RED, true);
}
bodyUnits.add(r);
}
/**
* Display the caterpillar
*/
private void display() {
for (int i = 0; i < bodyUnits.size(); i++) {
window.add((Shape) bodyUnits.get(i));
}
}
/**
* Returns true if the given point is in the window
*/
private boolean isInWindow(Point p) {
return p.x >= 0 && p.x <= window.getWindowWidth() && p.y >= 0
&& p.y <= window.getWindowHeight();
}
}