JAVA程序设计(16)----- 贪食蛇游戏制作 LinkedList 初级应用

来源:互联网 发布:sqlserver count if 编辑:程序博客网 时间:2024/04/30 15:37

主要是LinkedList应用,JFrame,HAS-A的组合关系,Timer应用,键盘监听器(适配器)应用,方法的重写 等练习

原始制作顺序为:

面板 1.SnakeFrame  -------> 可动的点 2.Snake ------> 然后在Snake上加入方向3. Dirction --------> Snake 加入LinkedList 做成连续的蛇  并制作单节蛇 4. SnakeNode------------>制作可以吃的5.Egg  ,将游戏中硬代码提出 写成6.SnakeContext 。

1.SnakeFrame部分

package com.lovo.snake;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.image.BufferedImage;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.Timer;/** * 类:贪食蛇 面板 * @author Abe */@SuppressWarnings("serial")public class SnakeFrame extends JFrame {private Timer timer;private Image offImage = new BufferedImage(SnakeContext.GAME_SIZE,SnakeContext.GAME_SIZE, 1);private Snake snake = new Snake();private Egg egg = new Egg();private int counter = 0;private JLabel jl;private int level = 0;private boolean gameOver = false;/** * 构造器 初始化 */public SnakeFrame() {this.setSize(SnakeContext.GAME_SIZE, SnakeContext.GAME_SIZE);this.setResizable(false);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setLayout(null);jl = new JLabel("分数:" + counter + "分");jl.setBounds(50, 0, 400, 25);this.add(jl);/** * 键盘监听器 */this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {Direction newDir = snake.getDir();switch (e.getKeyCode()) {case KeyEvent.VK_W:case KeyEvent.VK_UP:newDir = Direction.UP;break;case KeyEvent.VK_S:case KeyEvent.VK_DOWN:newDir = Direction.DOWN;break;case KeyEvent.VK_A:case KeyEvent.VK_LEFT:newDir = Direction.LEFT;break;case KeyEvent.VK_D:case KeyEvent.VK_RIGHT:newDir = Direction.RIGHT;break;}if (snake.getDir() != newDir) {snake.changeDir(newDir);}}});/** * F2 重置游戏键盘监听器(可写在上面一起)单独好看点 */this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {int obj = e.getKeyCode();if (obj == KeyEvent.VK_F2) {for (int i = 0; i < snake.getLength(); i++) {snake.remove();}snake = new Snake();counter = 0;timer.start();repaint();gameOver = false;}}});/** * Timer */timer = new Timer(SnakeContext.INTERVAL, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Object obj = e.getSource();if (obj == timer && gameOver == false) {snake.move();SnakeNode tempHead = snake.getHead();if (!snake.eatEgg(egg)) {snake.remove();jl.setText("分数:" + counter + "分"+ "                  按F2可刷新游戏");} else {counter += 100;do {egg = new Egg();} while (isRepeat(0,egg.getX(), egg.getY()));if (counter % 100 == 0) {if (level < 200) {level += 20;}timer.setDelay(SnakeContext.INTERVAL);}}repaint();/** * 死亡判定,撞墙 撞自己 */int x = tempHead.getX();int y = tempHead.getY();if ((x < SnakeContext.WALL_X)|| (x > SnakeContext.WALL_X+ SnakeContext.SQUARE_SIZE- SnakeContext.SNAKE_SIZE)|| (y < SnakeContext.WALL_Y)|| (y > SnakeContext.WALL_Y+ SnakeContext.SQUARE_SIZE- SnakeContext.SNAKE_SIZE)) {timer.stop();gameOver = true;} else if (isRepeat(1,x, y)) {timer.stop();gameOver = true;}}}});timer.start();}/** * 方法:输入坐标筛查重复 */public boolean isRepeat(int firstIndex,int x, int y) {for (int i = firstIndex; i < snake.getList().size(); i++) {SnakeNode temp = snake.getList().get(i);if (temp.getX() == x && temp.getY() == y) {return true;}}return false;}/** * 重写:绘图方法 */@Overridepublic void paint(Graphics g) {Graphics offG = offImage.getGraphics();// 所有的画笔换成offGsuper.paint(offG);Graphics2D g2d = (Graphics2D) offG;offG.setColor(Color.black);g2d.setStroke(new BasicStroke(5));offG.drawRect(SnakeContext.WALL_X, SnakeContext.WALL_Y,SnakeContext.SQUARE_SIZE, SnakeContext.SQUARE_SIZE);g2d.setStroke(new BasicStroke(1));snake.draw(offG);egg.draw(offG);g.drawImage(offImage, 0, 0, null);}/** * main方法 窗口可见 * @param args */public static void main(String[] args) {new SnakeFrame().setVisible(true);}}


2.Snake部分

package com.lovo.snake;import java.awt.Graphics;import java.util.LinkedList;/** * 类:蛇 * @author Abe 属性:X Y 坐标 */public class Snake {private Direction dir = Direction.RIGHT;private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>();/** * 构造器 */public Snake(){for (int i = 0; i < SnakeContext.SNAKE_LENGTH; i++) {list.add(new SnakeNode(SnakeContext.SNAKE_X , SnakeContext.SNAKE_Y + i * SnakeContext.SNAKE_SIZE));}}/** * 方法:改变方向 * @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;}}/** * 方法:获得现在方向 * @return */public Direction getDir() {return dir;}/** * 获得蛇头 */public SnakeNode getHead(){return list.get(0);}/** * 获得长度 * @return */public int getLength(){return list.size();}/** * 方法:移动 */public void move() {SnakeNode head = getHead();int x = head.getX();int y = head.getY();switch(dir){case UP: y -= SnakeContext.SPEED;break;case DOWN: y += SnakeContext.SPEED;break;case LEFT: x -= SnakeContext.SPEED;break;case RIGHT: x += SnakeContext.SPEED;break;}list.addFirst(new SnakeNode(x, y));}/** * 方法:移出最后一个 */public void remove(){list.removeLast();}/** * 方法:绘制蛇身上有节点 */public void draw(Graphics g){for(SnakeNode tempNode : list){tempNode.draw(g);}}/** * 吃蛋 * @return */public boolean eatEgg(Egg egg){SnakeNode head = getHead();return head.getX() == egg.getX() && head.getY() == egg.getY();}public LinkedList<SnakeNode> getList() {return list;}}

3.Dirction方向枚举

package com.lovo.snake;/** * 枚举:上下左右 * @author Abe */public enum Direction {UP,DOWN,LEFT,RIGHT}

4.
package com.lovo.snake;import java.awt.Color;import java.awt.Graphics;/** * 类:单节的蛇 * @author Abe * */public class SnakeNode {private int x;private int y;private int size = SnakeContext.SNAKE_SIZE;/** * 构造器 * @param x * @param y */public SnakeNode(int x, int y) {this.x = x;this.y = y;}/** * 获得蛇 节点横纵坐标 *  * @return */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);}}

5.Egg 可以吃的蛋蛋 呵呵

package com.lovo.snake;import java.awt.Color;import java.awt.Graphics;/** * 蛋 * @author Abe */public class Egg {private int x, y;private int size = SnakeContext.EGG_SIZE;/** * 构造器:将中间的游戏进行面板等分,在节点上随机位置出现Egg */public Egg() {x = ((int) (Math.random() * (SnakeContext.SQUARE_SIZE / SnakeContext.SNAKE_SIZE))* SnakeContext.SNAKE_SIZE + (SnakeContext.WALL_X));y = ((int) (Math.random() * (SnakeContext.SQUARE_SIZE / SnakeContext.SNAKE_SIZE))* SnakeContext.SNAKE_SIZE + (SnakeContext.WALL_Y));}/** * 绘制蛋蛋 * @param g */public void draw(Graphics g) {g.setColor(Color.orange);g.fillOval(x, y, size, size);}/** * 获得蛋蛋的横纵坐标 * @return */public int getX() {return x;}public int getY() {return y;}}

6.硬代码的去除

package com.lovo.snake;/** * 类:硬代码数据提出专门编写一类 方便修改 * @author Abe * */public class SnakeContext {/** * 蛇的大小 */public static final int SNAKE_SIZE = 25;/** *  蛋的大小 */public static final int EGG_SIZE = SNAKE_SIZE;/** * 蛇的长度 */public static final int SNAKE_LENGTH = 5;/** * 蛇的初始位置 * 要人为计算好初始位置,处于节点上,不然没法吃蛋。 * 如果愿意,也可以将XY坐标通过运算强制转到节点上,这只是数学问题了,懒得做了。 * 具体还是: X / 单份长度 * 单份长度 + 初始位置 */public static final int SNAKE_X = 250;public static final int SNAKE_Y = 250;/** * 蛇的初始速度 */public static final int SPEED = SNAKE_SIZE;/** * 游戏窗口大小 */public static final int  GAME_SIZE = 600;/** * 游戏场地大小 */public static final int SQUARE_SIZE = 500;/** * 刷新周期 */public static final int INTERVAL = 300;/** * 围墙起点坐标 */public static final int WALL_X = 50;public static final int WALL_Y = 50;}

到此为止游戏制作完成,而且能够完美运行。不过尚有一个小BUG 手速快的朋友找找看 呵呵~~O(∩_∩)O~

1 0
原创粉丝点击