主要的蛇的类
import java.awt.Color; import java.awt.Graphics; import java.awt.HeadlessException; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.util.Random; public class Snake { private Node head = null; private Node tail = null; int size = 0; private boolean live = true; /** * 判断蛇是否活着 * @return true则活着 false则死亡 */ public boolean isLive() { return live; } /** * 设置蛇的生死 * @param live true则活着 false则死亡 */ void setLive(boolean live){ this.live = live; } private Yard y; Node n = new Node(15, 15, Dir.L); /** * 构造方法 * @param y */ public Snake(Yard y){ this.y = y; head = n; tail = n; size++; } /** * 将一个结点添加到蛇的链表中 */ void addToTail(){ Node node = null; switch (tail.dir) { case L: node = new Node(tail.row, tail.col+1, tail.dir); break; case U: node = new Node(tail.row+1, tail.col, tail.dir); break; case R: node = new Node(tail.row, tail.col-1, tail.dir); break; case D: node = new Node(tail.row-1, tail.col, tail.dir); break; } tail.next = node; node.prev = tail; tail = node; size++; } /** * 将一个结点从蛇的尾巴处删除 */ void deleteFromTail(){ if(size == 0) return; tail = tail.prev; tail.next = null; size--; } /** * 设置使蛇的位置向前移动一步 */ void move(){ addToHead(); deleteFromTail(); checkDead(); } /** * 蛇的重画方法 * @param g */ void draw(Graphics g){ if(!isLive() || size == 0) { return; } move(); for(Node node = head ; node != null ; node = node.next){ node.draw(g); } } /** * 将一个结点加到蛇链表的头部 */ void addToHead(){ Node node = null; switch (head.dir) { case L: node = new Node(head.row, head.col-1, head.dir); break; case U: node = new Node(head.row-1, head.col, head.dir); break; case R: node = new Node(head.row, head.col+1, head.dir); break; case D: node = new Node(head.row+1, head.col, head.dir); break; } node.next = head; head.prev = node ; head = node ; size++; } /** * 保存蛇单个结点信息的类 */ private class Node{ int w = Yard.BLOCK_SIZE; int h = Yard.BLOCK_SIZE; Dir dir = Dir.L; int row,col; Node next = null; Node prev = null; public Node(int row,int col,Dir dir){ this.row = row; this.col = col; this.dir = dir; } //蛇单个节点的画法 public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.BLACK); g.fillRect(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h); g.setColor(c); } } /** * 键盘监听 * @param e */ public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: if(head.dir != Dir.R) head.dir = Dir.L; break; case KeyEvent.VK_UP: if(head.dir != Dir.D) head.dir = Dir.U; break; case KeyEvent.VK_RIGHT: if(head.dir != Dir.L) head.dir = Dir.R; break; case KeyEvent.VK_DOWN: if(head.dir != Dir.U) head.dir = Dir.D; break; case KeyEvent.VK_F2: if(!this.isLive()){ y.snake = new Snake(y); } break; } } /** * 吃食物 * @param f */ public void eatFood(Food f){ if(this.getRect().intersects(f.getRect())){ f.setPos(); y.setScore(); this.addToTail(); } } /** * 通过检测来设置蛇的生死 */ public void checkDead(){ if(head.col < 0 || head.col > Yard.COLS || head.row < 3 || head.row > Yard.ROWS-1){ setLive(false); } if(size >= 4){ for(Node node = head.next;node != null ; node = node.next){ if(head.row == node.row && head.col == node.col){ setLive(false); } } } } public Rectangle getRect(){ return new Rectangle(head.col*Yard.BLOCK_SIZE,head.row*Yard.BLOCK_SIZE,Yard.BLOCK_SIZE,Yard.BLOCK_SIZE); } }
吃的食物的类
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.Random; public class Food { int row,col; int h = Yard.BLOCK_SIZE; int w = Yard.BLOCK_SIZE; private static Random rd = new Random(); int step = 0; public Food(int row ,int col) { this.row = row; this.col = col; } public void draw(Graphics g){ Color c = g.getColor(); if(step == 0){ g.setColor(Color.RED); step++; }else if(step == 1){ g.setColor(Color.green); step++; }else { g.setColor(Color.WHITE); step = 0; } g.fillOval(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h); g.setColor(c); } public Rectangle getRect(){ return new Rectangle(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h); } void setPos(){ this.row = rd.nextInt(Yard.ROWS-3)+3; this.col = rd.nextInt(Yard.COLS); } }
方向的枚举
public enum Dir { L,U,R,D }
主界面的类
import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; class Yard extends Frame{ PaintThread pt = null; /** * 速度 设置数字越大 越慢 */ public static final int SPEED = 4; /** * 行数 */ public static final int ROWS = 30; /** * 列数 */ public static final int COLS = 30; /** * 行列的宽度 */ public static final int BLOCK_SIZE = 15; /** * 在游戏窗口中加入一条蛇 */ public Snake snake = new Snake(this); /** * 在游戏窗口中加入一个食物 */ public Food food = new Food(10,10); private Font font = new Font("宋体", Font.BOLD,30 ); private Image offScreenImage = null; //分数 private int score = 0; public int getScore() { return score; } public void setScore() { this.score += 5; } /** * 窗口构建函数 */ public void launch(){ pt = new PaintThread(); this.setLocation(200, 200); this.setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); this.setVisible(true); this.addKeyListener(new KeyMonitor()); this.setResizable(false); //开始重画线程 new Thread(pt).start(); } /** * 主方法 * @param args */ public static void main(String[] args){ new Yard().launch(); } /** * 重写的paint方法 用来画出各个元素 */ @Override public void paint(Graphics g) { Color c = g.getColor(); g.setColor(Color.GRAY); g.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE); g.setColor(Color.DARK_GRAY); //画出横线 for(int i=1; i<ROWS; i++) { g.drawLine(0, BLOCK_SIZE * i, COLS * BLOCK_SIZE, BLOCK_SIZE * i); } for(int i=1; i<COLS; i++) { g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * ROWS); } snake.eatFood(food); g.setColor(Color.YELLOW); g.drawString("score :" + score, 10, 50); food.draw(g); if(snake.isLive()) { snake.draw(g); }else{ g.setColor(Color.YELLOW); g.setFont(font); g.drawString("Game Over!", 125, 225); } g.setColor(c); } /** * 重写的update用来防止屏幕闪烁 */ @Override public void update(Graphics g) { if(offScreenImage == null){ offScreenImage = this.createImage(COLS*BLOCK_SIZE, ROWS*BLOCK_SIZE); } Graphics graphics = offScreenImage.getGraphics(); paint(graphics); g.drawImage(offScreenImage, 0, 0, null); } /** * 重画线程 */ private class PaintThread implements Runnable{ private boolean flag = true; private boolean pause = false; @Override public void run() { while(flag){ if(!pause) repaint(); try { Thread.sleep(25*SPEED); } catch (InterruptedException e) { e.printStackTrace(); } } } public void stopPaintThread(){ flag = !flag; } public void pausePaintThread(){ pause = !pause; } } /** * 键盘监听类 */ private class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if(key == KeyEvent.VK_SPACE){ pt.pausePaintThread(); } snake.keyPressed(e); } } }