/** ****************************************************************************** * HOMEWORK 1, 15-211 ****************************************************************************** * * This is a game board. It consists of * - a caterpillar * - several obstacles * - a pellet * * The Snake eats the food (a pellet), but stays away from obstacles and . * the walls. The more it eats, the longer it gets. * Obstacles and a pellet are randomly generated. * * The caterpillar is stored in the queue as a set of Point(x,y). * * -------------------------------------------- * | QUEUE | * | | * | front back | * -------------------------------------------- * * -------------------------------------------- * | SNAKE | * | | * | tail head | * -------------------------------------------- * * The caterpillar's move is implemented by the following two steps: * dequeue the tail Point and then * enqueue the move-in Point. * * * @author V.Adamchik * @date 12/29/04 * @see Queue * @see GameApplet *****************************************************************************/ /***************************************************************************** The Queue class must be replaced by the ArrayQueue class. *****************************************************************************/ import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.*; public class Snake extends JPanel { final static int scale = 10; // scale ratio is 1:10 private Point position; // the position of its head private char direction = 'R'; // the direction of its head private Queue body; // its entire body private boolean selfCrossing = false; //do not allow selfcrossing private int score; // the current score private Point pellet; // caterpillar's food private Queue obstacles; // do not eat them private int numObstcls; // the number of obstacles private Random rand = new Random(); private boolean stillMoving, illegalMove, initInstr=true; private int boardHeight, boardWidth; /** * Create a new caterpillar, with the given color and starting position * * @param (x,y) define the window size * @param sp the starting position */ public Snake(int x, int y) { body = new Queue(); obstacles = new Queue(); boardWidth = x/scale; boardHeight = y/scale; pellet = null; position = new Point(0,0); score = 0; numObstcls = 2; setBackground (new Color(0.5945f,1f,1f)); } /** * Set the direction of the head of the caterpillar * * @param d the direction */ public void setDirection(char d) { direction = d; } /** * Get the caterpillar's score. * * @return the current score */ public int getScore() { return score; } /** * We allow or do not allow the caterpillar to cross itself. * * @sel is a checked box */ public void setCrossing(boolean sel) { selfCrossing = sel; } /** * Pause the caterpillar * */ public void pause(boolean state) { stillMoving = state; if(illegalMove) stillMoving = false; if(state) initInstr = false; } /** * Move the caterpillar one step * * */ public void move() { if (!stillMoving) return; // find new position Point np = newPosition(); if (canMove(np)) { // check if we will eat a pellet if (np.equals(pellet)) { pellet = null; score++; body.enqueue(np); if(score%15==0) numObstcls+=5; //adaptive element!!!!! obstacles.clear(); for (int i = 0; i < numObstcls; i++) obstacles.enqueue(nextObstcl()); pellet = nextPellet(); } else // erase one segment, add another body.dequeue(); body.enqueue(np); position = np; } else illegalMove = true; repaint(); } /** * Determine whether the given point is free (so that a caterpillar * can move into it). * * @param np the point to test * @return true if point np is free */ public boolean canMove (Point np) { // get x, y coordinate int x = np.x; int y = np.y; // test playing board if (x <= 0 || y <= 0 || x >= boardWidth || y >= boardHeight) return false; // we either allow or do not allow self intersections if (!selfCrossing && body.contains(np)) return false; // we do not allow hitting obstacles if (obstacles.contains(np)) return false; return true; } /** * Calculate the next position for the caterpillar * * * @return that point */ private Point newPosition() { int x = position.x; int y = position.y; switch(direction) { case 'R': x++; break; case 'L': x--; break; case 'U': y--; break; case 'D': y++; break; } return new Point(x, y); } /** * Draw the caterpillar on the given graphics pane * * @param g the graphics pane on which to draw the caterpillar */ public void paintComponent(Graphics g) { super.paintComponent(g); if(initInstr) { instructions(g); return; } /* Draw the obstacles . */ Iterator itr = obstacles.iterator(); g.setColor(Color.red); while (itr.hasNext()) { Point p = (Point) itr.next(); g.fillRect(scale*p.x, scale*p.y, scale, scale); } /* Draw the caterpillar . */ itr = body.iterator(); while (itr.hasNext()) { Point p = (Point) itr.next(); if(p.equals(position)) g.setColor(new Color(0.5f,0f,0.5f)); else g.setColor(Color.blue); g.fillOval(scale*p.x, scale*p.y, scale, scale); } /* Draw the pellet . */ if(pellet != null) { g.setColor(Color.black); g.fillOval(scale*pellet.x, scale*pellet.y, scale, scale); } /* Display the message for illegal move. */ if(illegalMove) { g.setFont(g.getFont().deriveFont(Font.BOLD, (float)40.0)); g.setColor(Color.magenta); g.drawString("Illegal move.", scale*(12),scale*boardHeight/4); stillMoving = false; } } /** * Reset the board when the game level is changed * * @param len is either 1, 2 or 3 depending on the game level */ public void draw(int len) { int m = len + 2; int i = 0; /* Draw the caterpillar . */ body.clear(); if(len == 1) { for (i = 0; i < 15; i++) body.enqueue(new Point(i, boardHeight/2)); position = new Point(i-1, boardHeight/2); } else if(len == 2) { for (i = 1; i < 5; i++) body.enqueue(new Point(5, boardHeight/2-i)); for (i = 5; i > 0; i--) body.enqueue(new Point(i, boardHeight/2-5)); for (i = 1; i < 5; i++) body.enqueue(new Point(1, boardHeight/2-5+i)); for (i = 1; i < 10; i++) body.enqueue(new Point(i, boardHeight/2)); for (i = 0; i < 5; i++) body.enqueue(new Point(10, boardHeight/2-i)); for (i = 0; i < 5; i++) body.enqueue(new Point(10+i, boardHeight/2-5)); for (i = 0; i < 5; i++) body.enqueue(new Point(15, boardHeight/2-5+i)); for (i = 0; i < 5; i++) body.enqueue(new Point(15+i, boardHeight/2)); position = new Point(19, boardHeight/2); } else { for (i = 1; i < 5; i++) body.enqueue(new Point(20-i, boardHeight/2-1)); for (i = 0; i < 5; i++) body.enqueue(new Point(15, boardHeight/2-1-i)); for (i = 1; i < 5; i++) body.enqueue(new Point(15-i, boardHeight/2-6+i)); for (i = 0; i < 5; i++) body.enqueue(new Point(10-i, boardHeight/2-1)); for (i = 1; i < 5; i++) body.enqueue(new Point(5, boardHeight/2-i)); for (i = 5; i > 0; i--) body.enqueue(new Point(i, boardHeight/2-5)); for (i = 0; i < 10; i++) body.enqueue(new Point(1, boardHeight/2-5+i)); for (i = 1; i < 5; i++) body.enqueue(new Point(i, boardHeight/2+5)); for (i = 0; i < 6; i++) body.enqueue(new Point(5, boardHeight/2+5-i)); for (i = 0; i < 5; i++) body.enqueue(new Point(6+i, boardHeight/2)); for (i = 1; i < 5; i++) body.enqueue(new Point(10+i, boardHeight/2+i)); for (i = 0; i < 5; i++) body.enqueue(new Point(15, boardHeight/2+4-i)); for (i = 1; i < 5; i++) body.enqueue(new Point(15+i, boardHeight/2)); position = new Point(19, boardHeight/2); } /* Draw the obstacles . */ numObstcls = 2*m; obstacles.clear(); for (i = 0; i < numObstcls; i++) obstacles.enqueue(nextObstcl()); /* Draw the pellet . */ pellet = nextPellet(); direction = 'R'; illegalMove = false; score = 0; repaint(); } /** * Generate the next obstacle. * Make sure the obstacle does not touch the caterpillar * * @return the point where a new obstacle will be positioned */ public Point nextObstcl() { Point p; do { p = new Point(rand.nextInt(boardWidth-2)+1, rand.nextInt(boardHeight-2)+1); } while(obstacles.contains(p) || body.contains(p)); return p; } /** * Generate the next pellet * Make sure the pellet does not touch the caterpillar and obstacles * * @param len is either 0, 1 or 2 */ public Point nextPellet() { Point p; do { p = new Point(rand.nextInt(boardWidth-2)+1, rand.nextInt(boardHeight-2)+1); } while(obstacles.contains(p) || body.contains(p)); return p; } /** * Display the game rules * * */ public void instructions(Graphics g) { g.setFont(g.getFont().deriveFont(Font.BOLD, (float)20.0)); g.setColor(Color.black); g.drawString("Make the caterpillar longer by directing it", scale*(5),scale*boardHeight/6); g.drawString("to the food (in black).", scale*(5),scale*boardHeight*1/4); g.drawString("Use arrow keys for navigation.", scale*(5),scale*boardHeight*5/12); g.drawString("If the caterpillar hits the walls, or the ", scale*(5),scale*boardHeight*7/12); g.drawString("obstacles (in red), the game is terminated.", scale*(5),scale*boardHeight*2/3); g.setColor(Color.blue); g.drawString("Click to begin! Have fun!", scale*(5),scale*boardHeight*5/6); } }