Java学习(8):贪吃蛇游戏
根据视频编写的贪吃蛇游戏
主方法
public class Start { public static void main(String[] args) { new Yard().launch(); } }
import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Panel; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; /** * * @author xcx * @time 2017年7月28日下午3:44:48 */ public class Yard extends Frame { //设置游戏结束字体 Font goFont = new Font("宋体",Font.ITALIC|Font.BOLD,50); //游戏开始的线程 PaintThread paintThread = new PaintThread(); //游戏得分 public static int score = 0; //判断蛇是否死掉 private static boolean flag = true; //行数与列数 public static final int ROWS = 30; public static final int COLS = 30; // 每个格子的边长 public static final int BLOCK_SIZE = 15; //定义一条蛇,一个蛋 Snake s = new Snake(); Egg e = new Egg(); // 加入双缓冲 Image offScreenImage = null; public void launch() { setLayout(null); setLocation(200, 200); setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE); setVisible(true); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { setVisible(true); System.exit(0); } }); // 添加键盘控制事件 addKeyListener(new KeyMonitor()); // 运行线程 paintThread.start(); } @Override public void paint(Graphics g) { // 保存画笔额颜色 Color color = g.getColor(); // 设置画笔的颜色 g.setColor(Color.gray); g.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE); g.setColor(Color.DARK_GRAY); // 画出横线 for (int i = 0; i < ROWS; i++) { g.drawLine(0, BLOCK_SIZE * i, BLOCK_SIZE * COLS, BLOCK_SIZE * i); } // 画出竖线 for (int i = 0; i < ROWS; i++) { g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * ROWS); } g.setColor(Color.yellow); g.drawString("score"+score, 10, 60); if(flag == false){ g.setFont(goFont); g.drawString("game over", 100, 180); paintThread.gameOver(); } // 还原画笔的颜色 g.setColor(color); s.eat(e); e.draw(g); s.draw(g); } @Override public void update(Graphics g) { if (offScreenImage == null) { offScreenImage = this.createImage(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE); } Graphics gOff = offScreenImage.getGraphics(); paint(gOff); g.drawImage(offScreenImage, 0, 0, null); } //停止 public static void stop(){ flag = false; } // 不断刷新界面 private class PaintThread extends Thread { private boolean running = true; @Override public void run() { while (running) { repaint(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } public void gameOver(){ running = false; } } //键盘监听事件 private class KeyMonitor extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { s.keyPressed(e); } } }
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; /** * * @author xcx * @time 2017年7月28日下午3:45:03 */ public class Snake { // 蛇的头结点和尾结点 private Node head = null; private Node tail = null; private int size = 0; // 自己定义一个头 private Node node = new Node(20, 30, Dir.L); public Snake() { head = node; tail = node; size = 1; } // 将一个结点添加到尾巴上 public void addToTail() { Node node = null; switch (tail.dir) { case L: node = new Node(tail.row, tail.col + 1, tail.dir); break; case R: 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 D: node = new Node(tail.row - 1, tail.col, tail.dir); break; } tail.next = node; node.prev = tail; tail = node; size++; } // 将一个结点添加到头上 public void addToHead() { Node node = null; switch (head.dir) { case L: node = new Node(head.row, head.col - 1, head.dir); break; case R: 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 D: node = new Node(head.row + 1, head.col, head.dir); break; } node.next = head; head.prev = node; head = node; size++; } // 从蛇的尾巴删除一个结点 private void deleteFromTail() { if (size == 0) return; tail = tail.prev; tail.next = null; } // 将蛇画出 public void draw(Graphics g) { if (size <= 0) return; move(); for (Node node = head; node != null; node = node.next) { node.draw(g); } } // 蛇移动一下 private void move() { addToHead(); deleteFromTail(); checkDead(); } // 检查蛇是否死掉 private void checkDead() { // 判断蛇是否撞在了墙上 if (head.row < 0 || head.row > Yard.ROWS || head.col < 0 || head.col > Yard.COLS) { Yard.stop(); } // 判断蛇是否撞在了自己的身上 for (Node node = head.next; node != null; node = node.next) { if (this.getRect().intersects(node.getRect())) { Yard.stop(); } } } // 键盘按下后蛇头方向改变 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_RIGHT: if (head.dir != Dir.L) head.dir = Dir.R; break; case KeyEvent.VK_UP: if (head.dir != Dir.D) head.dir = Dir.U; break; case KeyEvent.VK_DOWN: if (head.dir != Dir.U) head.dir = Dir.D; break; } } // 蛇吃蛋 public void eat(Egg e) { if (this.getRect().intersects(e.getRect())) { e.reAppear(); addToTail(); Yard.score += 5; } } // 判断蛇头所在的格子 private Rectangle getRect() { return new Rectangle(Yard.BLOCK_SIZE * head.col, Yard.BLOCK_SIZE * head.row, head.w, head.h); } // 定义结点内部类 private class Node { // 结点的高度与宽度 int w = Yard.BLOCK_SIZE; int h = Yard.BLOCK_SIZE; // 所在的位置 int row, col; // 结点的方向 Dir dir = Dir.L; // 后一个结点 Node next = null; // 前一个结点 Node prev = null; Node(int row, int col, Dir dir) { this.row = row; this.col = col; this.dir = dir; } void draw(Graphics g) { Color color = g.getColor(); g.setColor(Color.black); g.fillRect(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h); g.setColor(color); } // 判断节点所在的格子 private Rectangle getRect() { return new Rectangle(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h); } } }
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.Random; /** * * @author xcx * @time 2017年7月28日下午3:45:11 */ public class Egg { // 设置蛋的颜色 Color color = Color.green; // 出现的坐标 private int row, col; // 蛋的高与宽 private int w = Yard.BLOCK_SIZE; private int h = Yard.BLOCK_SIZE; private static Random r = new Random(); public Egg(int x, int y) { this.row = x; this.col = y; } public Egg() { this(r.nextInt(Yard.ROWS), r.nextInt(Yard.COLS)); } public void reAppear() { this.row = r.nextInt(Yard.ROWS) ; this.col = r.nextInt(Yard.COLS) ; } // 画出一个蛋 public void draw(Graphics g) { Color c = g.getColor(); g.setColor(color); g.fillOval(Yard.BLOCK_SIZE * row, Yard.BLOCK_SIZE * col, w, h); g.setColor(c); if (color == Color.green) { color = Color.red; } else { color = Color.green; } } // 得到蛋所在的格子 public Rectangle getRect() { return new Rectangle(Yard.BLOCK_SIZE * row, Yard.BLOCK_SIZE * col, w, h); } }
/** * *@author xcx *@time 2017年7月28日下午4:14:38 */ public enum Dir { L,R,U,D }