贪吃蛇

来源:互联网 发布:javascript格式化xml 编辑:程序博客网 时间:2024/04/29 16:23
<pre name="code" class="java">package com.lovo;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.awt.Stroke;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import javax.swing.JFrame;import javax.swing.Timer;@SuppressWarnings("serial")public class GameFrame extends JFrame {private int total = 0;private Image offImage = new BufferedImage(GameContext.GAME_SIZE, GameContext.GAME_SIZE, 1);private Timer timer = null;private Snake snake = null;private Egg egg = null;private boolean acceptNextKey = true;public GameFrame() {this.setTitle("贪吃蛇");this.setSize(GameContext.GAME_SIZE, GameContext.GAME_SIZE);this.setResizable(false);this.setLocationRelativeTo(null);this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {save();System.exit(0);}});this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (acceptNextKey) {Direction newDir = snake.getDir();switch (e.getKeyCode()) {case KeyEvent.VK_W: //上newDir = Direction.UP;break;case KeyEvent.VK_S: // 下newDir = Direction.DOWN;break;case KeyEvent.VK_A: // 左newDir = Direction.LEFT;break;case KeyEvent.VK_D: // 右newDir = Direction.RIGHT;break;case KeyEvent.VK_F2: // 重新开始resetGame();return;}if (snake.getDir() != newDir) { // 如果新方向不同于蛇原来的方向snake.changeDir(newDir); // 调用蛇的changeDir方法修改蛇的方向acceptNextKey = false;}}}});load();// 读取存档if(snake == null) {// 没有存档resetGame();}timer = new Timer(GameContext.INTERVAL, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {snake.move();// 调用蛇的move方法让蛇向前移动acceptNextKey = true;if(!snake.eatEgg(egg)) {// 没有吃到蛋snake.removeTail();}else {total += GameContext.MARK_PER_EGG;egg = new Egg();// 重新创建一颗蛋}SnakeNode head = snake.getHead();int x = head.getX();int y = head.getY();// 判断蛇有没有咬到自己或者撞到围墙if(snake.eatSelf() || (x < GameContext.WALL_X || x > GameContext.WALL_X + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE ||y < GameContext.WALL_Y || y > GameContext.WALL_Y + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE)) {snake.setAlive(false);timer.stop();}else {repaint();}}});timer.start();}@Overridepublic void paint(Graphics g) {// 使用双缓冲方式消除窗口闪烁(见下面步骤1-2-3)// 1. 获得内存中图像的画笔Graphics offG = offImage.getGraphics();// 2. 用offG在内存中绘制窗口上的所有内容super.paint(offG);// 消除残影Graphics2D g2d = (Graphics2D) offG;// 将Graphics转成其子类型Graphics2D并设置粗细Stroke oldStroke = g2d.getStroke();// 记录画笔粗细(保存现场)g2d.setStroke(new BasicStroke(GameContext.WALL_WIDTH));// 将画笔加粗offG.setColor(Color.BLACK);// 设置画笔为黑色int x = GameContext.WALL_X, y = GameContext.WALL_Y;offG.drawRect(x, y, GameContext.SQUARE_SIZE, GameContext.SQUARE_SIZE);// 绘制围墙g2d.setStroke(oldStroke);// 还原画笔粗细(恢复现场)if(snake != null) snake.draw(offG);// 调用蛇的draw方法绘制蛇 if(egg != null) egg.draw(offG);// 调用蛋的draw方法绘制蛋offG.setColor(Color.RED);offG.drawString("分数: " + total, 50, 40);// 绘制得分// 3. 将内存中绘制好的图直接画到窗口上(双缓冲)g.drawImage(offImage, 0, 0, null);// 第二个和第三个参数是绘图的位置}private void resetGame() {snake = new Snake();egg = new Egg();total = 0;}// 读档private void load() {File f = new File("game.sav");if(f.exists()) {ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream(f));GameRecord record = (GameRecord) ois.readObject();if(record != null) {snake = record.getSnake();egg = record.getEgg();total = record.getScore();}}catch(IOException e) {e.printStackTrace();}catch (ClassNotFoundException e) {e.printStackTrace();}finally {if(ois != null) {try {ois.close();}catch (IOException e) {e.printStackTrace();}}}}}// 存档private void save() {ObjectOutputStream oos = null;try {oos = new ObjectOutputStream(new FileOutputStream("game.sav"));if(snake != null && snake.isAlive()) {GameRecord record = new GameRecord();record.setSnake(snake);record.setEgg(egg);record.setScore(total);oos.writeObject(record);}else {File f = new File("game.sav");if(f.exists()) {f.deleteOnExit();}}}catch(IOException e) {e.printStackTrace();}finally {if(oos != null) {try {oos.close();}catch (IOException e) {e.printStackTrace();}}}}}

package com.lovo;import java.awt.Graphics;import java.io.Serializable;import java.util.LinkedList;/** * 蛇 *  * @author XWJ * */@SuppressWarnings("serial")public class Snake implements Serializable {private Direction dir = Direction.LEFT; // 方向private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>(); // 装蛇的所有节点的容器(链表)private boolean alive = true;// 蛇是否活着/** * 构造器 */public Snake() {// 初始化5个节点for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) {list.add(new SnakeNode(GameContext.SNAKE_X + i* GameContext.SNAKE_SIZE, GameContext.SNAKE_Y));}}/** * 改变方向 *  * @param newDir 新的方向 */public void changeDir(Direction newDir) {if (!((dir == Direction.LEFT && newDir == Direction.RIGHT)|| (dir == Direction.RIGHT && newDir == Direction.LEFT)|| (dir == Direction.UP && newDir == Direction.DOWN) || (dir == Direction.DOWN && newDir == Direction.UP))) {dir = newDir;}}/** * 获得蛇前进的方向 */public Direction getDir() {return dir;}/** * 获得蛇头 */public SnakeNode getHead() {return list.get(0); // 容器中的第一个节点就是蛇头}/** * 吃蛋 *  * @param egg 蛋 * @return 吃到蛋返回true否则返回false */public boolean eatEgg(Egg egg) {SnakeNode head = getHead();return head.getX() == egg.getX() && head.getY() == egg.getY();}/** * 蛇有没有咬到自己 *  * @return 咬到自己返回true否则返回false */public boolean eatSelf() {SnakeNode head = getHead();for (int i = 1; i < list.size(); i++) {SnakeNode temp = list.get(i);if (temp.getX() == head.getX() && temp.getY() == head.getY()) {return true;}}return false;}/** * 向前移动 */public void move() {SnakeNode head = getHead();int x = head.getX(), y = head.getY();int size = GameContext.SNAKE_SIZE;switch (dir) {case UP:y -= size;break;case DOWN:y += size;break;case LEFT:x -= size;break;case RIGHT:x += size;break;}SnakeNode newHead = new SnakeNode(x, y); // 创建新的蛇头节点list.addFirst(newHead); // 头上加一个节点}/** * 删除蛇尾 */public void removeTail() {list.removeLast();}/** * 绘制蛇 */public void draw(Graphics g) {// 绘制蛇身上的每个节点for (SnakeNode node : list) {node.draw(g);}}public boolean isAlive() {return alive;}public void setAlive(boolean alive) {this.alive = alive;}}

package com.lovo;import java.awt.Color;import java.awt.Graphics;import java.io.Serializable;/** * 蛇身上的节点 * @author XWJ * */@SuppressWarnings("serial")public class SnakeNode implements Serializable {private int x, y;private int size = GameContext.SNAKE_SIZE;/** * 构造器 */public SnakeNode(int x, int y) {this.x = x;this.y = y;}/** * 蛇节点的横坐标 */public int getX() { return x; }/** * 蛇节点的纵坐标 */public int getY() { return y; }/** * 绘制 */public void draw(Graphics g) {g.setColor(Color.GREEN);g.fillRect(x, y, size, size);g.setColor(Color.BLACK);g.drawRect(x, y, size, size);}}

package com.lovo;import java.io.Serializable;@SuppressWarnings("serial")/** * 游戏存档 * @author XWJ * */public class GameRecord implements Serializable {private Snake snake;private Egg egg;private int score;public Snake getSnake() {return snake;}public void setSnake(Snake snake) {this.snake = snake;}public Egg getEgg() {return egg;}public void setEgg(Egg egg) {this.egg = egg;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}}

package com.lovo;public class GameContext {/** * 蛇的长度 */public static final int SNAKE_LENGTH = 10;/** * 蛇头初始位置的横坐标 */public static final int SNAKE_X = 270;/** * 蛇头初始位置的纵坐标 */public static final int SNAKE_Y = 290;/** * 蛇节点的大小 */public static final int SNAKE_SIZE = 20;/** * 游戏窗口的大小 */public static final int GAME_SIZE = 600;/** * 游戏场地的大小 */public static final int SQUARE_SIZE = 500;/** * 刷新周期 */public static final int INTERVAL = 200;/** * 围墙起点的横坐标 */public static final int WALL_X = 50;/** * 围墙起点的纵坐标 */public static final int WALL_Y = 50;/** * 围墙厚度 */public static final int WALL_WIDTH = 5;/** * 蛋的大小 */public static final int EGG_SIZE = SNAKE_SIZE;/** * 吃一个蛋的得分 */public static final int MARK_PER_EGG = 5;}

package com.lovo;import java.awt.Color;import java.awt.Graphics;import java.io.Serializable;@SuppressWarnings("serial")public class Egg implements Serializable {private int x, y;private int size = GameContext.EGG_SIZE;public Egg() {x = (int)(Math.random() * GameContext.SQUARE_SIZE / GameContext.EGG_SIZE) * GameContext.EGG_SIZE + GameContext.WALL_X;y = (int)(Math.random() * GameContext.SQUARE_SIZE / GameContext.EGG_SIZE) * GameContext.EGG_SIZE + GameContext.WALL_Y;}public int getX() {return x;}public int getY() {return y;}public void draw(Graphics g) {g.setColor(Color.ORANGE);g.fillOval(x, y, size, size);}}

package com.lovo;public enum Direction {UP, DOWN, LEFT, RIGHT}

package com.lovo;class GameRunner {public static void main(String[] args) {new GameFrame().setVisible(true);}}


                                             
0 0
原创粉丝点击