业务逻辑梳理和描述

面向对象设计贪吃蛇

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. R语言Logistic回归模型案例基于AER包的affair数据分析
  2. 011_学生管理系统二
  3. 6700设置上网教程
  4. 20171117-构建之法:现代软件工程-阅读笔记
  5. SEO是企业发展的永恒主题
  6. 前端学习(1433):vue是什么
  7. JAVA如何隐藏异常堆栈_java – 如何在控制台上停止打印异常堆栈跟踪?
  8. 红橙Darren视频笔记 CoordinatorLayout:实现自定义behavior
  9. oracle 更新flwid,Oracle分析函数RANK(),ROW_NUMBER(),LAG()等的使用方法
  10. asp 后台批量管理程序
  11. (1)封装JSON数据的三种方式
  12. python 成语库_python实现成语找一找
  13. 【SAP Abap】SAP Eclipse ADT开发环境配置与应用
  14. 驱动人生安装驱动计算机无法启动,驱动人生安装驱动时无法启用这个硬件解决方法 如何获得system权限...
  15. 微信小程序 — 公立医院申请
  16. 2022-2028全球与中国Microsoft Dynamics ERP咨询服务市场现状及未来发展趋势
  17. ubuntu命令安装中文语言包_Ubuntu安装中文语言包
  18. iOS开发---本地通知(UILocalNotification)
  19. BOLL布林带定向策略
  20. AlarmManager定时不准确

热门文章

  1. 电脑系统安装视频教程
  2. 应用内评分_自考书院:2020年10月02358单片机原理及应用试题和评分参考
  3. Tushare Day2——了解stock_basic数据并根据行业和地区进行统计
  4. [0CTF 2016]piapiapia 详细解题思路及做法
  5. [学习日记]重构简易RSSREADER的UML类图
  6. WINDOWS 10 多网卡域名解析策略配置方法
  7. 全志H616:OLED屏应用 — IIC协议
  8. Go语言实现Playing on a chessboard
  9. jieba简易教程:分词、词性标注、关键词抽取
  10. 【Python爬虫】:爬取干货集中营上的全部美女妹子(翻页处理)