合肥网站制作方案,凡科互动答题辅助,受欢迎的企业网站建设,wordpress插件汉化教程JavaSE#xff0c;无框架实现贪吃蛇
B站已发视频#xff1a;无swing#xff0c;纯JavaSE贪吃蛇游戏设计构建 文章目录 JavaSE#xff0c;无框架实现贪吃蛇1.整体思考2.可能的难点思考2.1 如何表示游戏界面2.2 如何渲染游戏界面2.3 如何让游戏动起来2.4 蛇如何移动 3.流程图…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{DequeNode 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 ListString 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();}
}