无swing,高级javaSE毕业之贪吃蛇游戏(含模块构建,多线程监听服务),已录制视频
JavaSE,无框架实现贪吃蛇
B站已发视频:无swing,纯JavaSE贪吃蛇游戏设计构建
文章目录
- JavaSE,无框架实现贪吃蛇
- 1.整体思考
- 2.可能的难点思考
- 2.1 如何表示游戏界面
- 2.2 如何渲染游戏界面
- 2.3 如何让游戏动起来
- 2.4 蛇如何移动
- 3.流程图制作
- 4.模块划分
- 5.模块完善
- 5.0常量优化
- 5.1监听键盘服务
- i.输入存储
- ii.键盘监听
- 5.2棋盘类方法(地图)
- i.节点渲染
- ii.边界判断
- iii.地图显示
- iV.食物生成
- V.地图初始化
- 5.3蛇类方法
- i.蛇体初始化
- ii.自定义异常
- iii.食物监测
- iV.自我碰撞监测
- V.移动
- 6.业务流程编写
本篇文章没有使用任何框架,纯JavaSE编写的贪吃蛇。主要探讨点为程序设计,比如流程绘制,模块划分。
如果需要源代码,公众号’一只学Java的飞哥呀’,回复贪吃蛇,即可获取源码和讲义。此外附赠1年前用GUI写的贪吃蛇
JavaSE无框架实现贪吃蛇效果
贪吃蛇JavaSE无框架
JavaGUI实现贪吃蛇效果,但文章内容并无涉及GUI代码编写,仅仅在公众号上提供相应代码
贪吃蛇GUI
1.整体思考
- 游戏明面上的组成部分有2。蛇、地图。在JavaSE的知识体系内。地图可以使用
二维数组
表示,蛇可以用一维数组
表示 - 通过在控制台打印数组的形式,来静态展示贪吃蛇游戏
- 游戏本质上是一组连续的图片,每一秒打印一次数组,以此让游戏动起来
- 游戏需要通过用户敲击键盘,实现方向移动。程序需要监听键盘输入,并将输入结果传递给蛇,以此操作蛇的移动
2.可能的难点思考
2.1 如何表示游戏界面
public class GameMap{private static int row = 20;private static int col = 20;// String的二维数组, 用来表示地图public static String[][] gameMap = new String[row][col]; // 初始化地图public GameMap() {// o 为地图, * 为蛇, @ 为食物for (int i = 0; i < gameMap.length; ++i) {for (int j = 0; j < gameMap[0].length; ++j) {gameMap[i][j] = "o";}}}//...
}// Node的一维列表, 用来表示蛇的坐标
public class Node{int x;int y;public Node() {}public Node(int x, int y) {this.x = x;this.y = y;}
}public class Snake{Deque<Node> snakeLoc = new ArrayDeque<>(); // ...
}
2.2 如何渲染游戏界面
打印地图,相当于渲染游戏界面
void printMap() {// 循环打印map
}
2.3 如何让游戏动起来
用循环,持续不断的打印界面,就可以形成动起来的效果
while(true) {// ...printMap(map, snake);// ...
}
2.4 蛇如何移动
蛇的移动属于蛇对象的行为,因此我们可以在Snake类中封装move方法,移动的本质是:蛇尾移动到蛇头.
public class Snake{// 返回尾坐标,头坐标public void move(int[] direction) {// 获取蛇尾坐标Node lastNode = snakeLoc.removeLast();// 移动Node newNode = moveTo(direction);// 添加到蛇头snakeLoc.addFirst(newNode);}private Node moveTo(Node node, int[] direction) {// 获取头节点Node firstNode = snakeLoc.getFirst();// 执行移动逻辑int x = firstNode.getX();int y = firstNode.getY();x += direction[0];y += direction[1];firstNode.setX(x);firstNode.setY(y);return firstNode;}
}
3.流程图制作
4.模块划分
5.模块完善
5.0常量优化
public interface Constants {/*** 蛇的标记*/String SNAKE_FLAG = "o";/*** 地图的标记*/String MAP_FLAG = "*";/*** 食物的标记*/String FOOD_FLAG = "@";/*** 地图行数*/int row = 10;/*** 地图列数*/int col = 10;
}
5.1监听键盘服务
考虑到还在JavaSE的范畴,swing的键盘监听功能我们不会去使用,而网上有没有找到合适的代替方案。因此,我们采用最原始的方法,Scanner输入,来代替监听功能。但scanner会有阻塞现象,一旦把主游戏进程阻塞,那么后续的流程都将无法进行。因此,我们需要开启子线程来监听用户输入
i.输入存储
/*** 存储用户的输入*/
public class StoreInput{private static String input = "a";/** w* a s d*/private static List<String> validDir = Arrays.asList("w", "a", "s", "d");public static void set(String in) {if (validDir.contains(in)) {input = in; }}public static int[] get() {if ("w".equals(input)) {int[] dir = {0, 1};return dir;}else if ("a".equals(input)) {int[] dir = {-1, 0};return dir; }else if ("s".equals(input)) {int[] dir = {0, -1};return dir;}else {int[] dir = {1, 0};return dir;}}
}
ii.键盘监听
/*** 监听器, 监听输入*/
public class ScanerListener{public void start() {// 创建线程new Thread(new Runnable() {Scanner scanner = new Scanner(System.in);@Overridepublic void run() {while(true) {if (scanner.hasNext()) {// 存储最后一个字符int length = scanner.next().length();char inputChar = scanner.next().charAt(length - 1);StoreInput.set(String.valueOf(inputChar));}}}}).start();}
}
5.2棋盘类方法(地图)
- 地图节点渲染(蛇/食物 坐标渲染)
- 地图边界判断
i.节点渲染
// 地图坐标更新
public static void updateMap(Node node, String type) {gameMap[node.getX()][node.getY()] = type;
}
ii.边界判断
// 判断是否到达地图边缘
public static boolean isValid(Node node) {if (node.getX() < 0 || node.getX() >= Constants.row || node.getY() < 0 || node.getY() >= Constants.col) {// 非法return false; }// 合法return true;
}
iii.地图显示
循环打印地图数组
public void show() { for (int i = 0; i < gameMap.length; ++i) {for (int j = 0; j < gameMap[0].length; ++j) {System.out.print(gameMap[i][j]);System.out.print(" ");}System.out.println();}
}
iV.食物生成
private static Random random = new Random();private static Node food = new Node(1, 1);/*** 生成食物, 且保证不是在蛇的身体上*/
public static void generateFood() {// 循环生成成对坐标, 并且坐标不能落在蛇体上int x = 0;int y = 0;do {x = random.nextInt(Constants.row);y = random.nextInt(Constants.col);}while( isSnake(x, y) );food = new Node(x, y);updateMap(food, Constants.SNAKE_FLAG);
}/*** 返回食物节点*/
public static Node getFood() {return food;
}private static boolean isSnake(int x, int y) {return gameMap[x][y].equals(Constants.SNAKE_FLAG);
}
V.地图初始化
1.初始化食物,地图,蛇
// 初始化地图
public GameMap() {// o 为地图, * 为蛇, @ 为食物for (int i = 0; i < gameMap.length; ++i) {for (int j = 0; j < gameMap[0].length; ++j) {gameMap[i][j] = Constants.MAP_FLAG;}}generateFood();
}
5.3蛇类方法
初步完善如下功能:
- 位置移动
- 自我碰撞监测
- 食物监测
i.蛇体初始化
public class Snake{// 初始化贪吃蛇public Snake() {Node node = new Node(Constants.row / 2, Constants.col / 2);snakeLoc.addFirst(node);GameMap.updateMap(node, Constants.SNAKE_FLAG);Node node1 = new Node(node.getX() + 1, node.getY());snakeLoc.addLast(node1);GameMap.updateMap(node1, Constants.SNAKE_FLAG);}
}
ii.自定义异常
public SnakeException extends RuntimeException{public SnakeException(String msg) {super(msg);}
}
iii.食物监测
/*** 监测食物*/
public void detectFood(Node firstNode) {boolean flag = isFood(firstNode);if (flag) {System.out.println("吃掉!");// 长度增加longgerSelf();// 随机生成食物GameMap.generateFood();}
}/*** 增长自己*/
private void longgerSelf(){// 获取当前方向int[] dir = StoreInput.get();// 方向取反, 获得尾巴需要添加的方向int x = -1 * dir[0];int y = -1 * dir[1];// 在尾部添加节点Node lastNode = snakeLoc.getLast();Node newNode = new Node(lastNode.getX() + x, lastNode.getY() + y);// 添加节点到尾部snakeLoc.addLast(newNode);// 更新节点GameMap.updateMap(newNode, Constants.SNAKE_FLAG);
}/*** 判断节点是否是食物* @param firstNode*/
private boolean isFood(Node firstNode) {Node foodNode = GameMap.getFood();return firstNode.getX() == foodNode.getX() && firstNode.getY() == foodNode.getY();
}
iV.自我碰撞监测
/*** 传入新的头节点, 判断是否和身体节点冲突*/
public boolean detectSelf(Node firstNode) {// 判断是否和余下的节点冲突for (Node node : snakeLoc) {if (node.getX() == firstNode.getX() && node.getY() == firstNode.getY()) {return true;}}return false;
}
V.移动
因为我们已经有输入存储
模块,我们可以直接从中获取
// 返回尾坐标,头坐标
public void move() {// 获取蛇尾坐标Node lastNode = snakeLoc.removeLast();// 获取方向int[] direction = StoreInput.get();// 移动Node newNode = moveTo(direction);// 墙体监测if (!GameMap.isValid(newNode)) {throw new SnakeException("撞墙!游戏结束");}// 自我碰撞监测if (detectSelf(newNode)) {throw new SnakeException("撞到自己!游戏结束");}// 返回更改坐标GameMap.updateMap(lastNode, Constants.MAP_FLAG);GameMap.updateMap(newNode, Constants.SNAKE_FLAG);// 食物探测detectFood(newNode);// 添加到蛇头snakeLoc.addFirst(newNode);
}private Node moveTo(int[] direction) {// 获取头节点Node firstNode = snakeLoc.getFirst();// 执行移动逻辑int x = firstNode.getX();int y = firstNode.getY();x += direction[0];y += direction[1];// 创建新节点return new Node(x, y);
}
6.业务流程编写
游戏类,主要控制全局的游戏流程
public class SnakeGame {// 创建地图private static GameMap map = new GameMap();// 创建蛇对象private static Snake snake = new Snake();// 创建监听服务private static ScanerListener listener = new ScanerListener();public static void main(String[] args) {// 开启游戏// 启动键盘监听服务listener.start();try {while(true) {// 绘图map.show();// 睡眠1秒try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}// 移动蛇snake.move();// 清空控制台cls();}} catch(SnakeException e) {e.printStackTrace();}}private static void cls() {
// System.out.print("Everything on the console will cleared");System.out.print("\033[H\033[2J");System.out.flush();}
}
相关文章:
无swing,高级javaSE毕业之贪吃蛇游戏(含模块构建,多线程监听服务),已录制视频
JavaSE,无框架实现贪吃蛇 B站已发视频:无swing,纯JavaSE贪吃蛇游戏设计构建 文章目录 JavaSE,无框架实现贪吃蛇1.整体思考2.可能的难点思考2.1 如何表示游戏界面2.2 如何渲染游戏界面2.3 如何让游戏动起来2.4 蛇如何移动 3.流程图…...
Kafka3.0.0版本——消费者(消费者组详细消费流程图解及消费者重要参数)
目录 一、消费者组详细消费流程图解二、消费者的重要参数 一、消费者组详细消费流程图解 创建一个消费者网络连接客户端,主要用于与kafka集群进行交互,如下图所示: 调用sendFetches发送消费请求,如下图所示: (1)、Fet…...
算法通关村-----位运算在海量元素中查找重复元素的妙用
用4KB内存寻找重复元素 问题描述 给定一个数组,包含从1到N的整数,N最大为32000,数组可能还有重复值,且N的取值不定,若只有4KB内存可用,如何打印数组中所有的重复元素。 问题分析 Java中存储整数使用int…...
RabbitMQ: Publish/Subscribe结构
生产者 package com.qf.mq2302.publishSub;import com.qf.mq2302.utils.MQUtils;import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection;public class EmitLog {private static final String EXCHANGE_NAME "logs";public static void main…...
单片机-蜂鸣器
简介 蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电 蜂鸣器主要分为 压电式蜂鸣器 和 电磁式蜂鸣器 两 种类型。 压电式蜂鸣器 主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后&…...
华为云云耀云服务器L实例评测 | 分分钟完成打地鼠小游戏部署
前言 在上篇文章【华为云云耀云服务器L实例评测 | 快速部署MySQL使用指南】中,我们已经用【华为云云耀云服务器L实例】在命令行窗口内完成了MySQL的部署并简单使用。但是后台有小伙伴跟我留言说,能不能用【华为云云耀云服务器L实例】来实现个简单的小游…...
Android——数据存储(二)(二十二)
1. SQLite数据库存储 1.1 知识点 (1)了解SQLite数据库的基本作用; (2)掌握数据库操作辅助类:SQLiteDatabase的使用; (3)可以使用命令操作SQLite数据库; …...
appium环境搭建
一.appium环境搭建 1.python3 python3的下载安装这里就不多做介绍了,当然你也可以选择自己喜欢的语音,比如java… 2.jdk 1)下载地址 官网(需登录账号): https://www.oracle.com/java/technologies/downloads/ 百度网盘&…...
十五、Webpack打包图片-js-Vue、Label命令、resolve模块解析
一、webpack打包图片 (1)加载图片案例准备 为了演示我们项目中可以加载图片,我们需要在项目中使用图片,比较常见的使用图片的方式是两种: img元素,设置src属性;其他元素(比如div&…...
ARM指令集--数据处理指令
数据处理指令:数学运算,逻辑运算 立即数 立即数的本质 就是包含在指令当中的数,属于指令的一部分 立即数的优点:取指的时候就可以将其读取到CPU,不用单独去内存读取,速度快 立即数的缺点:不…...
Excel embed into a webpage
无法编辑嵌入式 Excel 网页版 工作簿,但具有适当权限的人员可能能够在 Excel 中打开嵌入的工作簿,他们可以在其中编辑数据。 通过制作一个浏览器,打开并编辑它 https://onedrive.live.com/embed? resid5FC97855340825A9%21135& aut…...
uniapp点击事件在小程序中无法传参
这个问题很是神奇,第一次遇到。在h5中,点击事件可以正常传参,打包小程序后确失效了。 修改:for循环中的key,使用 index就好了...
ssprompt:一个LLM Prompt分发管理工具
阅读顺序 🌟前言🔔ssprompt介绍命令介绍Metafile介绍版本依赖规则 🌊 PromptHubGitHub Token 🚀 Quick Install系统依赖pip安装Linux, macOS, Windows (WSL)Windows (Powershell) 🚩 Roadmap🌏 项目交流讨论…...
修复 ChatGPT 发生错误的问题
目录 ChatGPT 发生错误?请参阅如何修复连接错误! 修复 ChatGPT 发生错误的问题 基本故障排除技巧 检查 ChatGPT 的服务器状态 检查 API 限制 检查输入格式 清除浏览数据 香港DSE是什么? 台湾指考是什么? 王湘浩 生平 …...
《热题100》字符串、双指针、贪心算法篇
思路:对于输入的的字符串,只有三种可能,ipv4,ipv6,和neither ipv4:四位,十进制,无前导0,小于256 ipv6:八位,十六进制,无多余0(00情况不允许),不…...
大数据组件Sqoop-安装与验证
🥇🥇【大数据学习记录篇】-持续更新中~🥇🥇 个人主页:beixi 本文章收录于专栏(点击传送):【大数据学习】 💓💓持续更新中,感谢各位前辈朋友们支持…...
运算符重载(个人学习笔记黑马学习)
1、加号运算符重载 #include <iostream> using namespace std; #include <string>//加号运算符重载 class Person { public://1、成员函数重载号//Person operator(Person& p) {// Person temp;// temp.m_A this->m_A p.m_A;// temp.m_B this->m_B p…...
2023.9.6 Redis 的基本介绍
目录 Redis 的介绍 Redis 用作缓存和存储 session 信息 Redis 用作数据库 消息队列 消息队列是什么? Redis 用作消息队列 Redis 的介绍 特点: 内存中存储数据:奠定了 Redis 进行访问和存储时的快可编程性:支持使用 Lua 编写脚…...
2023-09-08力扣每日一题
链接: 2651. 计算列车到站时间 题意: 不看日期只看时间 解: ? 实际代码: 还看!你怎么肥四?int findDelayedArrivalTime(int arrivalTime, int delayedTime) {return (arrivalTimedelayed…...
adb-linux 调试桥
这里写自定义目录标题 摘要:一、简介二、adb使用参考连接 摘要: adb 可替代网络、串口等调试手段,可以方便的进行文件传输、终端登录等 一、简介 ADB的全称为Android Debug Bridge,即调试桥,方便调试设备或调试开发…...
入门人工智能 —— 使用 Python 进行文件读写,并完成日志记录功能(4)
入门人工智能 —— 使用 Python 进行文件读写(4) 入门人工智能 —— 使用 Python 进行文件读写打开文件读取文件内容读取整个文件逐行读取文件内容读取所有行并存储为列表 写入文件内容关闭文件 日志记录功能核心代码:完整代码:运…...
使用Caffeine实现帖子的缓存来优化网站的运行速度
导入依赖 <!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.7</version>…...
Webpack5 搭建Vue项目(进阶版)
Webpack5 搭建Vue项目(进阶版) 提示:中间隔了好长时间,我胡汉三又回来继续更新了!!!😂😂😂 文章目录 Webpack5 搭建Vue项目(进阶版)前…...
论文阅读:Distortion-Free Wide-Angle Portraits on Camera Phones
论文阅读:Distortion-Free Wide-Angle Portraits on Camera Phones 今天介绍一篇谷歌 2019 年的论文,是关于广角畸变校正的。 Abstract 广角摄影,可以带来不一样的摄影体验,因为广角的 FOV 更大,所以能将更多的内容…...
力扣每日一题---207. 课程表
Problem: 207. 课程表 文章目录 解题方法复杂度Code 解题方法 y总的 Topsort 模板题 复杂度 时间复杂度: 添加时间复杂度, 示例: O ( n ) O(n) O(n) 空间复杂度: 添加空间复杂度, 示例: O ( n ) O(n) O(n) Code class Solution {int res 0; public…...
在Kubernetes环境中有关Nginx Ingress与API Gateway的连接问题
文章目录 小结问题解决参考 小结 在Kubernetes环境中是通过Nginx Ingress来从外部访问Kubernetes内部的环境,并用API Gateway来分发请求,碰到了 502 Bad gateway.的问题,并尝试解决。 问题 从外部通过Nginx Ingress访问Kubernetes内部的环…...
c语言练习44:深入理解strstr
深入理解strstr strstr作用展示: #include <stdio.h> #include <string.h> int main() {char str[] "This is a simple string";char* pch;pch strstr(str, "simple");/*strncpy(pch, "sample", 6);*/printf("%s…...
渗透测试漏洞原理之---【业务安全】
文章目录 1、业务安全概述1.1业务安全现状1.1.1、业务逻辑漏洞1.1.2、黑客攻击目标 2、业务安全测试2.1、业务安全测试流程2.1.1、测试准备2.1.2、业务调研2.1.3、业务建模2.1.4、业务流程梳理2.1.5、业务风险点识别2.1.6 开展测试2.1.7 撰写报告 3、业务安全经典场景3.1、业务…...
CentOS查看CPU、内存、网络流量和磁盘 I/O
安装 yum install -y sysstat sar -d 1 1 rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rmerge)/s wrqm/s: 每秒进行 merge 的写操作数目。即 delta(wmerge)/s r/s: 每秒完成的读 I/O 设备次数。即 delta(rio)/s w/s: 每秒完成的写 I/O 设备次数。即 delta(wio)/s rsec/s:…...
无人机航线规划
无人机航线规划,对于无人机的任务执行有着至关重要的作用,无人机在从起点飞向目的点的过程中,如何规划出一条安全路径,并且保证该路径代价最优,是无人机航线规划的主要目的。其中路径最优的含义是,在无人机…...
网站建设与管理 教学设计/大作设计网站
鼠标滚动事件 关于滚动事件这方面,其实是比较乱的。 滚轮事件的兼容性差异有些不拘一格,不是以往的IE8-派和其他派,而是FireFox派和其他派。 包括IE6在内的浏览器是使用onmousewheel,而FireFox浏览器一个人使用DOMMouseScroll. 经…...
金乡县住房与城乡建设局网站/百度网站搜索排名
Lua调C类和函数(cocos2d-x的方式来将C类注册进Lua环境) https://www.cnblogs.com/mokey/p/8042093.html Lua和C交互 学习记录之九:在Lua中以面向对象的方式使用C注册的类 https://www.cnblogs.com/chevin/p/5897220.html cocos2dx lua 绑定之一:自动绑…...
做网站有多难/天津seo诊断技术
1)JQuery语法 jquery语法是为HTML元素的选取编制,可以对元素执行某些操作。 基础语法是:$(selector).action() 美元符号定义JQuery 选择符(selector)"查询"和“查找”HTML元素 JQuery action()执行对元素的操作 如&…...
wordpress微店插件下载地址/北京搜索引擎关键词优化
一、代码 module decoder_38(a,b,c,out);input a,b,c; //输入端口output reg [7:0]out; //高位在前,低位在后,共8位always(a,b,c)begin //敏感列表,当a,b,c中的一个发生变化就执行begin后面的语句。case({a,b,c}) //花括号将a,b,c拼接…...
高端的网站建设公司哪家好/发布项目信息的平台
针对 SpringBoot JPA sqlserver 这种生成的表没有注释的情况 ,通过代码更新注释方法整理如下: // SpringBoot JPA 可以直接引入 jdbcTemplate Bean Autowired private JdbcTemplate jdbcTemplate;private void setTableComment(String tableName, Str…...
ping wordpress/北京搜索关键词优化
#hadoop之shell命令 ##一、启动命令 启动hadoop:start-dfs.sh,start-yarn.sh 关闭hadoop:stop-dfs.sh,stop-yarn.sh 启动hdfs时可在任意节点,启动yarn得在相应yarn的主节点上执行 hadoop fs -命令(hado…...