- 浏览: 6804 次
- 性别:
- 来自: 北京
最新评论
-
yanhuadesan:
写的相当不错,正好今天我也在写这个来着,学习了
代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager
通过上一节的分离我们可以使程序的流程更清楚,但是这些功能还是冗杂在一个类中,添加和修改功能的时候就要不断对这个类进行改动,而此类中涉及内容过多,在更改一个功能的时候要考虑其他功能的实现,那么这样改起来肯定是相当麻烦的。所以我们要将不同的功能封装出来,比如分数记录器,蛇,地图等。
这一节我们要做的是将蛇分离出来作为单个的类(Snake),首先看原来的代码:
package snakes; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Random; import javax.swing.JOptionPane; import javax.swing.JPanel; public class GamePanel extends JPanel implements KeyListener { private static final long serialVersionUID = -7269846451378790762L; private static final Random random = new Random(); /** * 分数 */ private int score = 0; /** * 每一个单元格的尺寸,像素 */ private final int sellSize = 20; /** * 地图横向包含的单元格数 */ private final int tableWidth = 30; /** * 地图纵向包含的单元格数 */ private final int tableHeight = 20; /** * 贪吃蛇的点链表 */ private final LinkedList<Point> snake = new LinkedList<Point>(); private final Direction[] da = { Direction.UP, Direction.DOWM, Direction.LEFT, Direction.RIGHT }; /** * 贪吃蛇行进方向 */ private Direction direction; /** * 虫子的位置 */ private Point target = new Point(random.nextInt(tableWidth), random.nextInt(tableHeight)); /** * 贪吃蛇初始长度 */ private final int initsnakeLenght = 3; private final Map<Integer, Direction> keyMap = new HashMap<Integer, Direction>(); /** * 移动速度 */ private volatile long speed = 1; private volatile long crrTime = System.currentTimeMillis(); public GamePanel () { initSnakeDirection(); initKeyMap(); initSnake(); initGameLoop(); } /** * 判断贪吃蛇是否撞墙或撞到自己 * * @return */ protected boolean checkSnack() { return !isAgainstWall() && !isAgainstSelf(); } /** * 绘制地图 * * @param g * 画布 */ private void drawMap(Graphics g) { g.setColor(new Color(0x555555)); for (int i = 0; i < tableWidth; i++) { for (int j = 0; j < tableHeight; ++j) { g.drawRect(i * sellSize, j * sellSize, sellSize, sellSize); } } } /** * 绘制蛇 * * @param g * 画布 */ private void drawSnake(Graphics g) { drawSnakeBody(g); drawSnakeHead(g); } /** * 绘制蛇身 * * @param g * 画布 */ private void drawSnakeBody(Graphics g) { g.setColor(new Color(0x3399cc)); for (Point p : snake) { g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } } /** * 绘制蛇头 * * @param g * 画布 */ private void drawSnakeHead(Graphics g) { g.setColor(new Color(0x115599)); Point p = snake.peek(); g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } /** * 绘制目标点(虫子) * * @param g * 画布 */ private void drawTarget(Graphics g) { g.setColor(new Color(0xdd7744)); g.fillRect(target.x * sellSize, target.y * sellSize, sellSize, sellSize); } /** * 随机生成方向 * * @return 方向 */ private Direction getRandomDirection() { return da[random.nextInt(4)]; } /** * 初始化游戏线程 */ private void initGameLoop() { /** * 游戏主循环线程 */ new Thread() { @Override public void run() { while (true) { if (System.currentTimeMillis() - crrTime > 500 / speed) { synchronized (GamePanel.class) { moveSnake(); if (!checkSnack()) { JOptionPane.showMessageDialog(null, "Game Over!"); return; } } repaint(); crrTime = System.currentTimeMillis(); } } }; }.start(); } /** * 初始化按键和方向的映射 */ private void initKeyMap() { keyMap.put(KeyEvent.VK_UP, Direction.UP); keyMap.put(KeyEvent.VK_DOWN, Direction.DOWM); keyMap.put(KeyEvent.VK_LEFT, Direction.LEFT); keyMap.put(KeyEvent.VK_RIGHT, Direction.RIGHT); } /** * 初始化蛇链表 */ private void initSnake() { Point p = new Point(random.nextInt(tableWidth - initsnakeLenght >> 1) + initsnakeLenght, random.nextInt(tableHeight - initsnakeLenght >> 1) + initsnakeLenght); snake.add(p); for (int i = 0; i < initsnakeLenght - 1; ++i) { p = direction.getPreviousPoint(p); snake.add(p); } } /** * 初始化蛇运行方向 */ private void initSnakeDirection() { direction = getRandomDirection(); } /** * 判断蛇头是否撞到自己的身体,是则返回true,否返回false * * @return */ private boolean isAgainstSelf() { Point p = snake.getFirst(); Iterator<Point> it = snake.iterator(); it.next(); while (it.hasNext()) { Point pBody = it.next(); if (p.equals(pBody)) { return true; } } return false; } /** * 判断蛇头是否撞到墙壁,是则返回true,否返回false * * @return */ private boolean isAgainstWall() { Point p = snake.getFirst(); int x = p.x, y = p.y; return x < 0 || x >= tableWidth || y < 0 || y >= tableHeight; } @Override public void keyPressed(KeyEvent e) {} @Override public void keyReleased(KeyEvent e) { Direction newd = keyMap.get(e.getKeyCode()); if (newd != null && direction.isAvailable(newd)) { direction = newd; synchronized (GamePanel.class) { moveSnake(); if (!checkSnack()) { JOptionPane.showMessageDialog(null, "Game Over!"); return; } } repaint(); crrTime = System.currentTimeMillis(); } } @Override public void keyTyped(KeyEvent e) {} /** * 移动贪吃蛇,包括吃虫 */ private void moveSnake() { snake.addFirst(direction.getNextPoint(snake.getFirst())); if (snake.getFirst().equals(target)) { target = new Point(random.nextInt(tableWidth), random.nextInt(tableHeight)); ++speed; ++score; } else { snake.removeLast(); } } /** * 绘制图形 */ @Override protected void paintComponent(Graphics g) { g.clearRect(0, 0, tableWidth * sellSize, tableHeight * sellSize); drawMap(g); drawSnake(g); drawTarget(g); } }
/* -------------------------------------分割线--------------------------------------------------------------------- */
要进行Snake类的封装首先要做的就是找到跟蛇有关的变量和方法(在Java中“方法”这个词比较常用,我也随大众吧):
贪吃蛇链表snake,行进方向direction,初始长度initsnakeLength(之前Length打错了,在此改正),碰撞检测checkSnake、isAgainstWall、isAgainstSelf,绘制蛇drawSnake、drawSnakeHead、drawSnakeBody,随机生成方向getRandomDirection,初始化蛇运行方向initSnakeDirection,移动蛇moveSnake。
然后将这些变量和方法移动到Snake类中:
在分离的过程中Sanke中需要用到sellSize,tableWidth,speed,score等变量,我们暂时先复制过来,并在构造的时候将这些变量先当做构造函数的参数传递给Snake(稍后有处理办法)。
这一阶段重构后的代码:
package snakes; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.Iterator; import java.util.LinkedList; import java.util.Random; public class Snake { /** * 分数 */ private int score; /** * 每一个单元格的尺寸,像素 */ private int sellSize; /** * 地图横向包含的单元格数 */ private int tableWidth; /** * 地图纵向包含的单元格数 */ private int tableHeight; private Point target; private volatile long speed; /** * 贪吃蛇的点链表 */ private static final Random random = new Random(); private final LinkedList<Point> snake = new LinkedList<Point>(); private final Direction[] da = { Direction.UP, Direction.DOWM, Direction.LEFT, Direction.RIGHT }; private Direction direction = da[random.nextInt(4)]; /** * 贪吃蛇初始长度 */ private final int initSnakeLenght = 3; public Snake (int score, long speed, int sellSize, int tableWidth, int tableHeight, Point target) { this.score = score; this.speed = speed; this.sellSize = sellSize; this.tableWidth = tableWidth; this.tableHeight = tableHeight; this.target = target; initSnakeDirection(); initSnake(); } /** * 判断贪吃蛇是否撞墙或撞到自己 * * @return */ public boolean checkSnack() { return !isAgainstWall() && !isAgainstSelf(); } /** * 绘制蛇 * * @param g * 画布 */ public void drawSnake(Graphics g) { drawSnakeBody(g); drawSnakeHead(g); } /** * 绘制蛇身 * * @param g * 画布 */ private void drawSnakeBody(Graphics g) { g.setColor(new Color(0x3399cc)); for (Point p : snake) { g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } } /** * 绘制蛇头 * * @param g * 画布 */ private void drawSnakeHead(Graphics g) { g.setColor(new Color(0x115599)); Point p = snake.peek(); g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } public Direction getDirection() { return direction; } /** * 随机生成方向 * * @return 方向 */ private Direction getRandomDirection() { return da[random.nextInt(4)]; } /** * 初始化蛇链表 */ private void initSnake() { Point p = new Point(random.nextInt(tableWidth - initSnakeLenght >> 1) + initSnakeLenght, random.nextInt(tableHeight - initSnakeLenght >> 1) + initSnakeLenght); snake.add(p); for (int i = 0; i < initSnakeLenght - 1; ++i) { p = getDirection().getPreviousPoint(p); snake.add(p); } } /** * 初始化蛇运行方向 */ private void initSnakeDirection() { setDirection(getRandomDirection()); } /** * 判断蛇头是否撞到自己的身体,是则返回true,否返回false * * @return */ private boolean isAgainstSelf() { Point p = snake.getFirst(); Iterator<Point> it = snake.iterator(); it.next(); while (it.hasNext()) { Point pBody = it.next(); if (p.equals(pBody)) { return true; } } return false; } /** * 判断蛇头是否撞到墙壁,是则返回true,否返回false * * @return */ private boolean isAgainstWall() { Point p = snake.getFirst(); int x = p.x, y = p.y; return x < 0 || x >= tableWidth || y < 0 || y >= tableHeight; } /** * 移动贪吃蛇,包括吃虫 */ public void moveSnake() { snake.addFirst(getDirection().getNextPoint(snake.getFirst())); if (snake.getFirst().equals(target)) { target = new Point(random.nextInt(tableWidth), random.nextInt(tableHeight)); ++speed; ++score; } else { snake.removeLast(); } } public void setDirection(Direction direction) { this.direction = direction; } }
package snakes;
import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Map; import java.util.Random; import javax.swing.JOptionPane; import javax.swing.JPanel; public class GamePanel extends JPanel implements KeyListener { private static final long serialVersionUID = -7269846451378790762L; private static final Random random = new Random(); private Snake snake; /** * 分数 */ private int score = 0; /** * 每一个单元格的尺寸,像素 */ private final int sellSize = 20; /** * 地图横向包含的单元格数 */ private final int tableWidth = 30; /** * 地图纵向包含的单元格数 */ private final int tableHeight = 20; /** * 虫子的位置 */ private Point target = new Point(random.nextInt(tableWidth), random.nextInt(tableHeight)); private final Map<Integer, Direction> keyMap = new HashMap<Integer, Direction>(); /** * 移动速度 */ private volatile long speed = 1; private volatile long crrTime = System.currentTimeMillis(); public GamePanel () { snake = new Snake(score, speed, sellSize, tableWidth, tableHeight, target); initKeyMap(); initGameLoop(); } /** * 绘制地图 * * @param g * 画布 */ private void drawMap(Graphics g) { g.setColor(new Color(0x555555)); for (int i = 0; i < tableWidth; i++) { for (int j = 0; j < tableHeight; ++j) { g.drawRect(i * sellSize, j * sellSize, sellSize, sellSize); } } } /** * 绘制目标点(虫子) * * @param g * 画布 */ private void drawTarget(Graphics g) { g.setColor(new Color(0xdd7744)); g.fillRect(target.x * sellSize, target.y * sellSize, sellSize, sellSize); } /** * 初始化游戏线程 */ private void initGameLoop() { /** * 游戏主循环线程 */ new Thread() { @Override public void run() { while (true) { if (System.currentTimeMillis() - crrTime > 500 / speed) { synchronized (GamePanel.class) { snake.moveSnake(); if (!snake.checkSnack()) { JOptionPane.showMessageDialog(null, "Game Over!"); return; } } repaint(); crrTime = System.currentTimeMillis(); } } }; }.start(); } /** * 初始化按键和方向的映射 */ private void initKeyMap() { keyMap.put(KeyEvent.VK_UP, Direction.UP); keyMap.put(KeyEvent.VK_DOWN, Direction.DOWM); keyMap.put(KeyEvent.VK_LEFT, Direction.LEFT); keyMap.put(KeyEvent.VK_RIGHT, Direction.RIGHT); } @Override public void keyPressed(KeyEvent e) {} @Override public void keyReleased(KeyEvent e) { Direction newd = keyMap.get(e.getKeyCode()); if (newd != null && snake.getDirection().isAvailable(newd)) { snake.setDirection(newd); synchronized (GamePanel.class) { snake.moveSnake(); if (!snake.checkSnack()) { JOptionPane.showMessageDialog(null, "Game Over!"); return; } } repaint(); crrTime = System.currentTimeMillis(); } } @Override public void keyTyped(KeyEvent e) {} /** * 绘制图形 */ @Override protected void paintComponent(Graphics g) { g.clearRect(0, 0, tableWidth * sellSize, tableHeight * sellSize); drawMap(g); snake.drawSnake(g); drawTarget(g); } }
做到这里,如果要运行的话,会发现有个问题,就是当贪吃蛇吃到虫子以后,虫子不会消失,也不会产生新的虫子,如果记录score的话也不会更改。这是因为我们把这些变量复制到Snake,在吃虫的时候更改的是在snake中的变量,而显示的时候却是原来的变量。
有些人想到的解决办法是:在Snake类中公开这些变量,让GamePanel在绘制的时候获取这些变量,这样不就解决了吗?
这样虽然解决了问题,但是仔细想想,score是游戏的得分,tableWidth、tableHeight、sellSize是地图的尺寸,而且targe是虫子,这些变量其实并不属于Snake,所以这样不符合逻辑,不可行。
一个合理的方法是:score等属性还是放在GamePanel中(先不管GamePanel有多乱,现在要做的是把Snake弄清楚),在Snake中保存一个GamePanel的成员,在需要更改这些属性的时候调用GamePanel中的方法。
对于tableWidth、tableHeight、sellSize这类的属性我们可以通过在GamePanel添加getter和setter方法访问,score和speed需要添加increase方法,target比较麻烦,首先在蛇在移动过程中要判断是否吃到虫,如果吃到就要重新放置一条虫子,显然放置虫子的操作不应该归蛇管(让蛇放虫子,那直接放到嘴边岂不方便),可以在GamePanel中添加resetTarget方法。那么判断是否吃到虫应该放到哪里?这个就仁者见仁智者见智了,我个人倾向于放到Snake类里面,然后让GamePanel提供一个target的访问方法。
现在距离完成只有一步之遥,加油吧!
最后,我们可以进行一些小的改进,比如可以把初始化方向作为一个工具类,提供不同的初始化方案(随机、固定、读取配置文件等等),然后将命名调整一下,代码顺序调整一下等等。
下面展示重构后的Snake类(完整的源代码已经上传,接下来的几节都会有对应的源码,方便大家查看和运行):
package snakes; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.Iterator; import java.util.LinkedList; import java.util.Random; public class Snake { /** * 贪吃蛇初始长度 */ private final int initSnakeLenght = 3; /** * 贪吃蛇的点链表 */ private final LinkedList<Point> snakeList = new LinkedList<Point>(); private Direction direction; private GamePanel panel; private static final Random random = new Random(); private DirectionGenerator directionGenerator = new RandomDirectionGenerator(); public Snake (GamePanel panel) { this.panel = panel; initDirection(); initList(); } /** * 判断贪吃蛇是否可行,即没有撞墙或撞到自己 * * @return 可行则返回true,不可行(撞墙或撞到自己)则返回false */ public boolean checkAvailable() { return !isAgainstWall() && !isAgainstSelf(); } /** * 绘制蛇身 * * @param g * 画布 */ private void drawBody(Graphics g) { int sellSize = panel.getSellSize(); g.setColor(new Color(0x3399cc)); for (Point p : snakeList) { g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } } /** * 绘制蛇头 * * @param g * 画布 */ private void drawHead(Graphics g) { g.setColor(new Color(0x115599)); Point p = snakeList.peek(); int sellSize = panel.getSellSize(); g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } /** * 绘制蛇 * * @param g * 画布 */ public void draw(Graphics g) { drawBody(g); drawHead(g); } public Direction getDirection() { return direction; } public DirectionGenerator getDirectionGenerator() { return directionGenerator; } /** * 初始化蛇运行方向 */ private void initDirection() { setDirection(directionGenerator.generateDirection()); } /** * 初始化蛇链表 */ private void initList() { int tableWidth = panel.getTableWidth(), tableHeight = panel.getTableHeight(); Point p = new Point(random.nextInt(tableWidth - initSnakeLenght >> 1) + initSnakeLenght, random.nextInt(tableHeight - initSnakeLenght >> 1) + initSnakeLenght); snakeList.add(p); for (int i = 0; i < initSnakeLenght - 1; ++i) { p = getDirection().getPreviousPoint(p); snakeList.add(p); } } /** * 判断蛇头是否撞到自己的身体,是则返回true,否返回false * * @return */ private boolean isAgainstSelf() { Point p = snakeList.getFirst(); Iterator<Point> it = snakeList.iterator(); it.next(); while (it.hasNext()) { Point pBody = it.next(); if (p.equals(pBody)) { return true; } } return false; } /** * 判断蛇头是否撞到墙壁,是则返回true,否返回false * * @return */ private boolean isAgainstWall() { int tableWidth = panel.getTableWidth(), tableHeight = panel.getTableHeight(); Point p = snakeList.getFirst(); int x = p.x, y = p.y; return x < 0 || x >= tableWidth || y < 0 || y >= tableHeight; } /** * 移动贪吃蛇,包括吃虫 */ public void move() { snakeList.addFirst(getDirection().getNextPoint(snakeList.getFirst())); if (snakeList.getFirst().equals(panel.getTarget())) { panel.resetTarget(); panel.increaseScore(); panel.increaseSpeed(); } else { snakeList.removeLast(); } } /** * 设置蛇的运行方向 * * @param direction */ public void setDirection(Direction direction) { this.direction = direction; } public void setDirectionGenerator(DirectionGenerator directionGenerator) { this.directionGenerator = directionGenerator; } }
方向生成器DirectionGenerator和实现类:
package snakes; public interface DirectionGenerator { public Direction generateDirection(); }
package snakes; import java.util.Random; public class RandomDirectionGenerator implements DirectionGenerator { private static final Direction[] directionArray = { Direction.UP, Direction.DOWM, Direction.LEFT, Direction.RIGHT }; private static final Random random = new Random(); @Override public Direction generateDirection() { return directionArray[random.nextInt(4)]; } }
下节预告:进一步封装类
- snakes.zip (16.2 KB)
- 下载次数: 11
发表评论
-
代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager
2012-10-21 22:50 1069继续题外话: 上一篇忘记发布到博客频道了,都没有人看到,这次 ... -
代码重构-以贪吃蛇为示例(四)-继续封装
2012-10-19 10:55 780题外话:本人第一次写技术文章,希望寻求鼓励啊,发了四篇了一个评 ... -
代码重构-以贪吃蛇为示例(二)-分离入口、内部类,抽离函数
2012-10-16 22:19 1245面对这么乱的代码,第一步就是把想关性不太大的部分抽离出去。具 ... -
代码重构-以贪吃蛇为示例(一)-重构之前
2012-10-16 15:56 1026题外话: 今天中午做到电脑前没事干,就写个贪吃蛇游戏,写着写 ... -
代码重构-以贪吃蛇为示例(序)
2012-10-16 15:22 973在正文之前,先说点题外话。 首先,作为一名学习了2年Ja ...
相关推荐
在本篇博客“代码重构-以贪吃蛇为示例(四)-继续封装”中,作者通过实现贪吃蛇游戏来阐述代码重构的重要性和具体实践。贪吃蛇游戏是许多程序员学习编程时的入门项目,它包含了基本的逻辑控制、用户输入处理以及游戏...
在本篇博客“代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager”中,作者通过重构一个贪吃蛇游戏的代码,深入探讨了软件开发中的两个重要概念:分数管理(Scoring)和速度管理(SpeedManager)。...
【Android 示例程序 Snake 贪吃蛇代码】是一款经典的Android平台上的游戏开发示例,它基于Java编程语言实现,展示了如何在Android环境中构建一个简单的2D游戏。此项目旨在帮助开发者理解和学习Android游戏开发的基本...
13--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码13--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码13--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码13...
2--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码2--...
41--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码41--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码41--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码41...
54--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码54--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码54--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码54...
1--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--[贪吃蛇].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码1--...
8--[贪吃蛇大作战].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码8--[贪吃蛇大作战].zip源码scratch2.0 3.0编程项目源文件源码案例素材源代码8--[贪吃蛇大作战].zip源码scratch2.0 3.0编程项目源文件源码...
【Java-snake贪吃蛇代码分享】是一款基于Java编程语言开发的小型游戏,适用于初学者进行编程实践。这个项目旨在帮助新手理解Java的基础语法、控制结构、对象与类的概念,以及游戏开发的基本流程。通过分析和运行这个...
在这个资源中,我们拥有了用VC++实现的贪吃蛇游戏的源代码,这为我们深入理解游戏逻辑、掌握C++编程技术提供了一个宝贵的实践平台。 首先,让我们了解VC++。Visual C++是Microsoft公司开发的一款集成开发环境(IDE...
通过研究这个C语言版的贪吃蛇源代码,读者不仅可以学习到基本的游戏开发技巧,还能深入理解C语言的编程实践,锻炼逻辑思维和问题解决能力。对于初学者,这是一个很好的实践项目,可以帮助他们巩固理论知识,提高编程...
【贪吃蛇游戏详解】 贪吃蛇是一款广受欢迎的经典小游戏,其简单易上手的玩法深受玩家喜爱。在这个由MFC框架实现的版本中,我们可以深入理解如何利用C++编程语言构建一个完整的图形用户界面(GUI)应用。MFC...
javaweb毕业设计-JAVA贪吃蛇游戏毕业设计(源代码+lw)(可做课程设计).rarjavaweb毕业设计-JAVA贪吃蛇游戏毕业设计(源代码+lw)(可做课程设计).rarjavaweb毕业设计-JAVA贪吃蛇游戏毕业设计(源代码+lw)(可做课程设计)....
【贪吃蛇游戏开发详解】 贪吃蛇游戏是一款经典的计算机程序,它基于简单的规则和直观的用户交互,深受程序员和游戏爱好者的喜爱。本项目使用C语言编程,并结合了EasyX图形库,使得游戏在VC++6.0环境下运行流畅。...
《Unity贪吃蛇》是一款基于Unity引擎开发的2D游戏,它将经典的贪吃蛇玩法与现代游戏技术相结合,提供了丰富的用户体验。Unity引擎是全球广泛使用的跨平台游戏开发工具,支持2D和3D游戏开发,具有强大的图形渲染、...
rust-snake使用rust编写的贪吃蛇游戏 仅供学习参考。 rust-snake使用rust编写的贪吃蛇游戏 仅供学习参考。 rust-snake使用rust编写的贪吃蛇游戏 仅供学习参考。 rust-snake使用rust编写的贪吃蛇游戏 仅供学习参考。...
在本文中,我们将深入探讨如何使用Cocos2d-x框架实现一个简单的“贪吃蛇”游戏。Cocos2d-x是一个流行的开源游戏开发框架,它使用C++编写,支持跨平台开发,适用于iOS、Android、Windows等多个操作系统。下面,我们将...