Java实现简单的贪吃蛇小游戏(使用线程、内部类、双向链表等)

来源:互联网 发布:java写接口供别人调用 编辑:程序博客网 时间:2024/05/16 09:33

使用Java中Frame来实现一个简单的贪吃蛇小游戏,游戏中使用了线程、内部类、双向链表等。

主要包含四个类:

Snake:生成蛇、蛇的移动、添加、碰撞判断

Egg:生成一个食物、画出食物

Yard:生成一个窗体、实现贪吃蛇的主要功能

Dir:四个方向,上下左右

实现效果图:


Snake.java

import java.awt.Color;import java.awt.Graphics;import java.awt.Rectangle;import java.awt.event.KeyEvent;import java.util.Map;/** *  * @Description * @author CCQ * @date 2017年6月22日 下午5:22:03 * */public class Snake {private Node head = null;  //蛇头private Node tail = null;  //蛇尾private int size = 0;      //蛇长度private Node n = new Node(20,20, Dir.L); //初始化蛇的位子private Yard y;public Snake(Yard y) {head = n;tail = n;size = 1;this.y = y;}/** * 加一段在尾巴上 */public 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++;}/** * 加一段在头上 */public void addHead() {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++;}//画出一条蛇public void drow(Graphics g) {if (size <= 0) {return;}move();for (Node n = head; n != null; n = n.next) {n.drow(g);}}//蛇移动public void move() {addHead();deleteFromTail();checkDead();}//检查是否碰撞public void checkDead() {if (head.row <3 || head.col < 1 || head.row > Yard.ROWS - 2 || head.col > Yard.COLS - 2) {y.stop();}for (Node n = head.next; n != null; n = n.next) {if (head.row == n.row && head.col == n.col) {y.stop();}}}//删出蛇尾public void deleteFromTail() {if (size == 0)return;tail = tail.prev;tail.next = null;}//定义一个内部类,实现蛇的生成,双向链表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;      //链表,前一个指针public Node(int row, int col, Dir dir) {super();this.row = row;this.col = col;this.dir = dir;}void drow(Graphics g) {Color c = g.getColor();g.setColor(Color.BLACK);g.fillRect(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h);g.setColor(c);}}//吃食物public void eat(Egg e) {if (this.getRect().intersects(e.getRect())) {boolean isSuccess = false;while(!isSuccess){Map<String, Integer> map = e.reAppear();for(Node n = head;n!=null;n=n.next){if(n.row != map.get("row") || n.col != map.get("col")){isSuccess = true;}}}this.addToTail();y.setScore(y.getScore() + 5);}}public Rectangle getRect() {return new Rectangle(Yard.BLOCK_SIZE * head.col, Yard.BLOCK_SIZE * head.row, head.w, head.h);}// 键盘事件,控制蛇的方向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;}}}

Egg.java

import java.awt.Color;import java.awt.Graphics;import java.awt.Rectangle;import java.util.HashMap;import java.util.Map;import java.util.Random;/** *  * @Description 生成食物 * @author CCQ * @date 2017年6月23日 上午9:23:59 * */public class Egg {int row, col;int w = Yard.BLOCK_SIZE;int h = Yard.BLOCK_SIZE;private static Random r = new Random();public Egg(int row, int col) {super();this.row = row;this.col = col;}public Egg() {this(r.nextInt(Yard.ROWS - 5) +3, r.nextInt(Yard.COLS - 3) +2);}//重新设计生成食物public Map<String, Integer> reAppear() {this.row = r.nextInt(Yard.ROWS - 5) +3;this.col = r.nextInt(Yard.COLS - 3) +2;Map<String, Integer> map = new HashMap<String, Integer>();map.put("row", this.row);map.put("col", this.col);return map;}public Rectangle getRect() {return new Rectangle(Yard.BLOCK_SIZE * this.col, Yard.BLOCK_SIZE * this.row, this.w, this.h);}//画出食物public void drow(Graphics g) {Color c = g.getColor();g.setColor(Color.GREEN);g.fillOval(Yard.BLOCK_SIZE * col, Yard.BLOCK_SIZE * row, w, h);g.setColor(c);}}

Yard.java

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;/** *  * @Description  * @author CCQ * @date 2017年6月23日 下午6:24:06 * */public class Yard extends Frame {private static final long serialVersionUID = 1L;public static final int ROWS = 30;        //定义行数public static final int COLS = 30;        //定义列数public static final int BLOCK_SIZE = 15;private Font fontGameOver = new Font("宋体", Font.BOLD, 50);private int score= 0;                     //计算获得分数private boolean gameOver = false;         //是否死亡Snake s = new Snake(this);Egg e = new Egg();Image offScreenImage = null;PaintThread paintThread = new PaintThread();public int getScore() {return score;}public void setScore(int score) {this.score = score;}/** * 生成一个窗口 */public void launch() {this.setLocation(450, 150);this.setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});this.setVisible(true);this.addKeyListener(new KeyMonitor());new Thread(paintThread).start();}//解决窗口闪烁@Overridepublic 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 void stop() {this.gameOver = true;}//画出方格@Overridepublic 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 = 3; i <= ROWS -1; i++) {g.drawLine(BLOCK_SIZE, BLOCK_SIZE * i, (COLS - 1) * BLOCK_SIZE, BLOCK_SIZE * i);}// 画竖线for (int j = 1; j <= COLS -1; j++) {g.drawLine(BLOCK_SIZE * j, BLOCK_SIZE * 3, BLOCK_SIZE * j, (ROWS - 1)* BLOCK_SIZE);}g.setColor(Color.YELLOW);g.drawString("分数:"+score+"  按F5可以重新开始", 10, 40);if(gameOver){g.setColor(Color.RED);g.setFont(fontGameOver);g.drawString("GAME OVER",85, 225);paintThread.pause();}g.setColor(c);s.eat(e);e.drow(g);s.drow(g);}private class PaintThread implements Runnable {private boolean pause = false;private boolean running = true;@Overridepublic void run() {while (running) {try {if(pause) continue; else repaint();Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}public void pause() {this.pause = true;}public void reStart() {this.pause = false;new Yard().launch();gameOver = false;}}//绑定键盘事件private class KeyMonitor extends KeyAdapter {@Overridepublic void keyPressed(KeyEvent e) {int key = e.getKeyCode();if(key == KeyEvent.VK_F5) {paintThread.reStart();}s.keyPressed(e);}}public static void main(String[] args) {new Yard().launch();}}

Dir.java

/** *  * @Description  蛇的方向 * @author CCQ * @date 2017年6月22日 下午5:33:05 * */public enum Dir {//左 上 右 下L,U,R,D}


原创粉丝点击