业务逻辑梳理和描述

面向对象设计贪吃蛇

1.找类和对象
a.Snake类 蛇类
b.Food类 食物类
c.Ground类 障碍物类
d.GamePanel 面板类 显示蛇、食物、障碍物。
2.找类的方法(把想到的先写出来)
2.1 Snake类
move()移动
eatFood(Food food)//吃食物
changeDirection();//改变方向
drawMe();//画出自己
蛇是否碰到自己、是否碰到食物、是否碰到障碍物
2.2 Food类
isEatBySnake(Snake snake)
drawMe()
2.3 Ground类
isEatBySnake(Snake snake)
drawMe()
2.4 GamePanel 显示蛇、食物和障碍物
display()方法
重写paintComponent()

3.控制器Controller
3.1其实贪吃蛇游戏就是控制Snake,Food,GroundPanel
专门用控制器来控制这四个对象---->作为成员并通过构造函数初始化
3.2控制器要能够控制蛇的移动主要是方向的改变
我们在操作的时候主要是通过键盘事件来控制
键盘事件由键盘监听器控制,那么我们的控制器首先需要是键盘的监听器
所以我们让Controller继承KeyAdapter(适配器),重写keyPressed方法
3.3蛇每次移动都应该判断蛇是否碰到了自己、障碍物,食物等
我们可以自己写一个监听器来监听这三个事件
写一个接口SnakeListener
蛇就需要有添加这个监听器的方法,接收这个监听器的成员
给Snake添加成员和方法
3.4 控制器也要是蛇的监听器,能够监听蛇是否碰到了自己、食物、障碍物
所以让Controller实现该接口
4.组装游戏
4.1创建所有类的对象
4.2控制器可以控制游戏的开始
添加startGame();—>就是让蛇start()跑起来
4.3在snake中添加start方法启动蛇的移动
start方法的实现启动一个线程让蛇不停的移动
4.4创建一个线程SnakeDriver
4.5给蛇添加监听器/面板添加键盘事件监听器
4.6创建窗体,添加面板,启动游戏,显示界面

总结:通过前面的4步,把架子已经搭好,面向对象的设计已经基本完成
采用的是mvc的方案,接下来具体实现
5.具体实现
5.1 用什么数据结构来存储蛇身
Snake最重要的动作是蛇的移动
蛇如何移动(火车拉的方式、去尾加头的方式)
所以数据结构选择LinkedList
那么LinkedList容纳什么类型呢,是矩形好呢还是点好
(因为蛇头走过的地方,蛇身都会经过)
所以用点Point(其实就是矩形的左上角坐标,每个方块的宽度、高度固定。)
将来也方便判断是否碰到食物、障碍物、自己
给蛇添加成员
5.2 贪吃蛇完成后,蛇身就是几个方块组成的
我们可以直接把面板划分成 行列各多少个格子组成即可
定义辅助类Global
格子划分
(4,2)它的真正坐标为(4格子的宽度,2格子的高度)。注:起始坐标为左上角坐标
(x格子,y格子)-- ->真的坐标是
(x格子的宽度,y格子的高度)
注: 图形化界面和数学坐标轴不同之处在于图形化界面为向右向下为增
5.3 初始化蛇身
格子中间开始横向三个格子作为初始蛇身
Snake类的init()方法中完成
画出蛇身 完成drawMe方法
5.4 完成蛇的移动move方法
去尾巴加头的方式
去完成方向的操作
修正反方向的问题
边界的问题(穿透)
5.5 完成食物操作
食物就是一个格子,格子的宽度和高度已经定义完成是固定的
这样的话就由左上角坐标来决定
左上角坐标就是一个点
可以让食物类直接继承Point类
食物出现的位置
控制器而言,游戏开始时,不但要让蛇移动,还应该出现食物
吃食物、把去掉的尾巴加回来即可
什么时候吃食物–>当蛇头碰到食物的时候
5.6 障碍物

相关代码实现以及运行效果

控制器类:

package org.yb.control;import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;import javax.swing.JOptionPane;import org.yb.entity.Food;
import org.yb.entity.Ground;
import org.yb.entity.Snake;
import org.yb.listener.SnakeListener;
import org.yb.view.GamePanel;
/*** 控制器类* @author yb**/
public class Controller extends KeyAdapter implements SnakeListener{private Snake snake;private Food food;private Ground ground;private GamePanel gamePanel;public Controller(Snake snake, Food food, Ground ground, GamePanel gamePanel) {super();this.snake = snake;this.food = food;this.ground = ground;this.gamePanel = gamePanel;}@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stub// 返回这个事件中和键相关的整数键int keycode = e.getKeyCode();switch (keycode) {case KeyEvent.VK_UP:snake.changeDirection(Snake.UP);break;case KeyEvent.VK_DOWN:snake.changeDirection(Snake.DOWN);break;case KeyEvent.VK_LEFT:snake.changeDirection(Snake.LEFT);break;case KeyEvent.VK_RIGHT:snake.changeDirection(Snake.RIGHT);break;            }}@Overridepublic void snakeMoved(Snake snake) {System.out.println("判断蛇是否碰到身体、是否碰到食物、障碍物");if(food.isEatBySnake(snake)){snake.eatFood(food);//食物被吃掉了,就应该有新的食物产生food.addFood(ground.getPoint(snake));}if(ground.isEatBySnake(snake)|| snake.isEatSelf()){//吃到后弹出一个对话框snake.setLife(false);JOptionPane.showConfirmDialog(null, "GameOver");System.exit(0);}//显示身体、食物、障碍物gamePanel.display(snake, food, ground);}/*** 游戏开始*/public void startGame(){snake.start();food.addFood(ground.getPoint(snake));}}

食物类:

package org.yb.entity;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;import org.yb.util.Global;/*** 食物* @author yb**/
public class Food extends Point{public void drawMe(Graphics g){g.setColor(Color.red);System.out.println("食物正在画出自己.....");g.fill3DRect(x*Global.CELL_SIZE, y*Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true);}/*** 蛇是否碰到食物* 只要判断蛇头的点是否和食物的位置重合* 要得到蛇头* @param snake* @return*/public boolean isEatBySnake(Snake snake){System.out.println("判断蛇是否碰到了食物");Point head = snake.getHead();if(this.equals(head))return true;return false;}public void addFood(Point p){this.x = p.x;this.y = p.y;}
}

障碍物类:

package org.yb.entity;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;import org.yb.util.Global;/*** 障碍物* @author yb**/
public class Ground {private int[][] rocks = new int[Global.HEIGHT][Global.WIDTH];public Ground(){for(int y = 0; y < Global.HEIGHT;y++){for(int x = 0;x < Global.WIDTH;x++){if(y==0 || y==Global.HEIGHT-1)rocks[y][x] = 1;
//             if(x==0 || x==Global.WIDTH-1)
//                 rocks[y][x] = 1;}}}public boolean isEatBySnake(Snake snake){System.out.println("判断蛇是否碰到了障碍物....."); Point head = snake.getHead();for(int y = 0; y < Global.HEIGHT;y++){for(int x = 0;x < Global.WIDTH;x++){if(rocks[y][x] == 1 && head.x == x && head.y == y)return true;}}return false;}public void drawMe(Graphics g){//设置画笔颜色g.setColor(Color.yellow);System.out.println("障碍物正在画出自己.....");for(int y = 0; y < Global.HEIGHT;y++){for(int x = 0;x < Global.WIDTH;x++){if(rocks[y][x] == 1){g.fill3DRect(x * Global.CELL_SIZE, y * Global.CELL_SIZE,Global.CELL_SIZE, Global.CELL_SIZE, true);}     }}}/*** 设置食物点的位置* @return*/public Point getPoint(Snake snake){int x,y;do{x = new Random().nextInt(Global.WIDTH);y = new Random().nextInt(Global.HEIGHT); }while(rocks[y][x] == 1 || isFoodSnake(x,y,snake));return new Point(x,y);}/*** 判断食物是否出现在蛇身上*/public boolean isFoodSnake(int x,int y,Snake snake){System.out.println("执行了吗");for(Point p : snake.getBody()){ if(p.x == x && p.y == y){return true;}}return false;     }
}

蛇类:

package org.yb.entity;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;import org.yb.listener.SnakeListener;
import org.yb.util.Global;/*** 蛇* @author yb**/
public class Snake {private SnakeListener snakeListener;private boolean life = true;private LinkedList<Point> body = new LinkedList<Point>();public static final int UP = 1;public static final int DOWN = -1;public static final int LEFT = 3;public static final int RIGHT = -3;
//    private int direction;//存储当前方向private int oldDirection,newDirection;private Point tail;//存储尾巴public Snake(){init();}private void init(){int x = Global.WIDTH/2;int y = Global.HEIGHT/2;for(int i=0;i<3;i++){body.add(new Point(x-i,y));   }
//      this.direction = RIGHT;this.oldDirection = this.newDirection = RIGHT;}/*** 蛇移动的方法*/public void move(){//去尾巴tail = body.removeLast();//加头-->得到当前的头部int x = body.getFirst().x;int y = body.getFirst().y;/** 获得新的头部* 要确定方向,才能知道新的头部* 在初始化构造蛇身的时候默认的方向其实认为是向右的* 我们定义出所有的方向* 并完成changeDirection方法*///this.directionif(this.oldDirection+this.newDirection!=0)this.oldDirection = this.newDirection;switch (this.oldDirection) {case UP:y--;if(y<0) y=Global.HEIGHT-1;break;case DOWN:y++;if(y>=Global.HEIGHT)y=0;break;case LEFT:x--;if(x<0)x=Global.WIDTH-1;break;case RIGHT:x++;if(x>=Global.WIDTH)x=0;break; }body.addFirst(new Point(x,y));System.out.println("蛇正在移动.....");}/*** 吃食物* 去掉的尾巴加回来即可* @param food*/public void eatFood(Food food){body.addLast(tail);System.out.println("蛇正在吃食物.....");   }/*** 改变方向*/public void changeDirection(int direction){//      if(this.direction+direction!=0)
//      this.direction = direction;this.newDirection = direction;System.out.println("蛇正在改变方向.....");    }public void drawMe(Graphics g){System.out.println("蛇正在画出自己.....");   g.setColor(Color.BLUE);for(Point p : body){//用预定的颜色填充一个突出显示的矩形g.fill3DRect(p.x * Global.CELL_SIZE, p.y* Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE,true);}}/*** 是否吃到自己* @return*/public boolean isEatSelf(){for(int i = 1;i < body.size();i++){if(body.get(i).equals(getHead())){return true;}}return false;}public void addSnakeListener(SnakeListener snakeListener){if(snakeListener!=null)this.snakeListener = snakeListener;}public void start(){new SnakeDriver().start();}/*** 获取蛇头* @return*/public Point getHead(){return body.getFirst();}/*** 蛇的存活状态* @param life*/public void setLife(boolean life) {this.life = life;}/*** 设置公有的get、set方法* @author lenovo**/public LinkedList<Point> getBody(){return body;   }//内部类private class SnakeDriver extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubwhile(life){move();snakeListener.snakeMoved(Snake.this);try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}

蛇的监听器类:

package org.yb.listener;import org.yb.entity.Snake;
/*** 蛇的监听器* 主要监听蛇的移动* @author lenovo**/
public interface SnakeListener {/*** 该方法去监听蛇是否碰到了自己、食物、障碍物* @param snake*/public void snakeMoved(Snake snake);
}

操作界面类:

package org.yb.view;import java.awt.Graphics;import javax.swing.JPanel;import org.yb.entity.Food;
import org.yb.entity.Ground;
import org.yb.entity.Snake;/*** 操作界面* * @author yb* */
public class GamePanel extends JPanel {/*** */private static final long serialVersionUID = 1L;private Snake snake;private Food food;private Ground ground;public void display(Snake snake, Food food, Ground ground) {System.out.println("面板正在显示.....");this.snake = snake;this.food = food;this.ground = ground;repaint();//调repaint()做画的工作,相当于调用了paintComponent(Graphics g)}// 画的方法@Overrideprotected void paintComponent(Graphics g) {//把上一次面板清空super.paintComponent(g);if (snake != null && food != null && ground != null) {snake.drawMe(g);food.drawMe(g);ground.drawMe(g);}}
}

常量类:

package org.yb.util;public class Global {//把面板设置成了如下格局public static final int CELL_SIZE = 15;//格子的宽度、高度public static final int WIDTH = 20;//横向20个格子public static final int HEIGHT = 20;//纵向也20个格子
}

游戏运行入口类:

package org.yb.test;import javax.swing.JFrame;import org.yb.control.Controller;
import org.yb.entity.Food;
import org.yb.entity.Ground;
import org.yb.entity.Snake;
import org.yb.util.Global;
import org.yb.view.GamePanel;public class SnakeGameTest {/*** @param args*/public static void main(String[] args) {//实体对象的创建Snake snake = new Snake();//蛇Food food = new Food();//食物Ground ground = new Ground();//障碍物//视图对象的创建GamePanel gamePanel = new GamePanel();//游戏操作界面 //控制器的创建-->即是蛇的监听器也是键盘的监听器Controller c = new Controller(snake, food, ground, gamePanel);snake.addSnakeListener(c);//键盘监听事件,当键盘按下去c类将被其监听到,然后调用keyPressed(KeyEvent e)方法gamePanel.addKeyListener(c);//创建窗体JFrame frame = new JFrame("贪吃蛇version1.0");//width, heightframe.setSize(Global.CELL_SIZE*Global.WIDTH+25, Global.CELL_SIZE*Global.HEIGHT+50);//关闭的时候自动退出frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//放在屏幕中间frame.setLocationRelativeTo(null);//让面板获得焦点,注:键盘事件要有效,面板必须获得焦点gamePanel.setFocusable(true);//添加面板frame.add(gamePanel);//启动游戏c.startGame();//显示窗体frame.setVisible(true);}}

运行效果截图:

java 面向对象实现贪吃蛇小游戏相关推荐

  1. 面向对象编程-贪吃蛇小游戏

    页面中的地图map html结构 <div id = "map"></div> 样式 #map{width:800px;height:600pxmargin ...

  2. 手把手教你做一个Java贪吃蛇小游戏

    大家好,我是孙不坚1208,这篇博客给大家分享一下:如何做一个贪吃蛇小游戏(Java版)的exe应用程序,希望能给需要帮助的朋友带来方便. 手把手教你做一个Java贪吃蛇小游戏的exe应用程序 一.J ...

  3. Java实现贪吃蛇小游戏(附完整源码)

    今天我就从零开始来完成这个小游戏,完成的方式也是一步一步的添加功能这样的方式来实现. 第一步完成的功能:写一个界面 大家见到的贪吃蛇小游戏,界面肯定是少不了的.因此,第一步就是写一个小界面. 实现代码 ...

  4. java贪吃蛇_如何用Java还原童年回忆?在线教你完成贪吃蛇小游戏

    今天我就从零开始来完成这个小游戏,完成的方式也是一步一步的添加功能这样的方式来实现. 额,不好意思,放错了,重来 第一步完成的功能:写一个界面 大家见到的贪吃蛇小游戏,界面肯定是少不了的.因此,第一步 ...

  5. 简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

    本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public stat ...

  6. JavaScript 进阶教程(2)---面向对象实战之贪吃蛇小游戏

    目录 1 引言 2 游戏地图 3 游戏对象 3.1 食物对象 3.2 小蛇对象 3.3 游戏对象 4 游戏的逻辑 4.1小蛇的移动 4.2 让蛇自己动起来 4.2.1 自动移动 4.2.2 自调用函数 ...

  7. 用 Java 实现贪吃蛇小游戏

    程序说明 这是一个用 Java Awt 实现的贪吃蛇小游戏的完整代码 算法分析 (一)启动一个独立线程根据 direction 重绘面板实现蛇身移动效果,运行过程: 记录上次头部的坐标到 tempBo ...

  8. 贪吃蛇小游戏java实现代码分析

    贪吃蛇小游戏java实现代码分析 贪吃蛇的小游戏,网上的代码比较多,今天周五,在教研室没啥事做,在电脑中发现了一个贪吃蛇的小游戏,于是就看了下实现的源码,发现别人写的代码确实挺好的,自己也是边加注释边 ...

  9. JAVA版贪吃蛇小游戏

    这是一篇关于JAVA的贪吃蛇游戏,源代码的部分在下面正文中介绍,图片和音频的部分都放在百度云盘,需要的自行下载. 文章目录 开发环境 一.下载方法 二.运行效果展示 三.项目结构以及主程序入口 1.项 ...

最新文章

  1. BZOJ1202: [HNOI2005]狡猾的商人
  2. win10+centos7+Anaconda3+python+pytorch
  3. loadrunner脚本编写,对nginx进行压测
  4. 0066-若干个数求和问题
  5. js的三元表达式用来替换表格中的颜色
  6. 数据中心细节_当细节很重要时数据不平衡
  7. async/await处理异步
  8. JFinal EhCachePlugin的学习笔记
  9. 从计算机视觉算法实训走向落地尝试
  10. 谈谈蛋疼的问题:里式替换原则:正方形是长方形吗?
  11. android 编译太慢,如何解决android studio运行编译速度慢
  12. 服务机器人研究报告:产业链分析及投资前景预测
  13. 【Linux / 数据库】项目实战:tpshop项目在Linux系统环境搭建
  14. 如何在图片里藏其他文件
  15. CAPICAPICOM的一些知识
  16. html手机qq登陆验证码,为什么qq登陆需要验证码?qq登陆需要验证码怎么取消?...
  17. Ajax实现异步请求步骤
  18. windows 批处理文件
  19. 上汽集团 java_【上汽集团工资】工程师待遇-看准网
  20. mysql checking_高并发下MySQL出现checking permissions

热门文章

  1. 3D游戏设计作业5:改进飞碟(Hit UFO)游戏
  2. QT pro 使用DEFINES来实现条件编译
  3. mysql mvcc_MySQL MVCC介绍
  4. APP性能优化如何保障
  5. mongodb compass连接不上远程服务器(亲测 已解决)
  6. swift conversion方法
  7. 【将金令】1.15晚评:金银势如破竹,如何释放?
  8. 阶梯电价:为了提倡居民节约用电,某省电力公司执行“阶梯电价”。
  9. HID Global推出新一代门禁读卡器以及非接触式智能卡(BlackBerry 9900)
  10. Spark07:【案例】Transformation和Action