- 浏览: 6807 次
- 性别:
- 来自: 北京
最新评论
-
yanhuadesan:
写的相当不错,正好今天我也在写这个来着,学习了
代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager
题外话:
今天中午做到电脑前没事干,就写个贪吃蛇游戏,写着写着就发现变量太多了,函数调用太乱了,逻辑越来越混乱,于是就想重构一下。但是有想一想,干脆把重构的过程记录下来,大家也分享分享,还能提高一下知名度,何乐而不为呢?
所以……所以……我硬着头皮在不重构的情况下写完了一个简单的贪吃蛇(WTF!)
/*--------------------------------------------无耻的分隔栏----------------------------------------------------- */
介绍下功能:
Swing组件完成的贪吃蛇游戏,通过键盘的方向键改变方向,吃到虫子增长长度,每吃掉一个虫子,移动速度会增长,撞到四周或者自己提示游戏结束。记录分数(但是没显示,因为不重构写不下去了),没有重新游戏(留到重构以后再写)。
界面:
(恐怖的)代码:
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.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; public class Game extends JPanel implements KeyListener { /** * 贪吃蛇行走的方向 */ enum Direction { UP { @Override public Point getNextPoint(Point p) { return new Point(p.x, p.y - 1); } @Override public Point getPreviousPoint(Point p) { return new Point(p.x, p.y + 1); } @Override public boolean isAvailable(Direction d) { if (d == Direction.UP || d == Direction.DOWM) { return false; } return true; } }, DOWM { @Override public Point getNextPoint(Point p) { return new Point(p.x, p.y + 1); } @Override public Point getPreviousPoint(Point p) { return new Point(p.x, p.y - 1); } @Override public boolean isAvailable(Direction d) { if (d == Direction.UP || d == Direction.DOWM) { return false; } return true; } }, LEFT { @Override public Point getNextPoint(Point p) { return new Point(p.x - 1, p.y); } @Override public Point getPreviousPoint(Point p) { return new Point(p.x + 1, p.y); } @Override public boolean isAvailable(Direction d) { if (d == LEFT || d == RIGHT) { return false; } return true; } }, RIGHT { @Override public Point getNextPoint(Point p) { return new Point(p.x + 1, p.y); } @Override public Point getPreviousPoint(Point p) { return new Point(p.x - 1, p.y); } @Override public boolean isAvailable(Direction d) { if (d == LEFT || d == RIGHT) { return false; } return true; } }; /** * 沿此方向的下一个点 * @param p * @return */ public abstract Point getNextPoint(Point p); /** * 沿此方向的上一个点 * @param p * @return */ public abstract Point getPreviousPoint(Point p); /** * 可以转动的方向 * @param d * @return */ public abstract boolean isAvailable(Direction d); } private static final long serialVersionUID = -7269846451378790762L; private static final Random random = new Random(); public static void main(String[] args) { JFrame j = new JFrame("贪吃蛇"); Game contentPane = new Game(); j.setContentPane(contentPane); j.addKeyListener(contentPane); j.setBounds(20, 20, 700, 500); j.setVisible(true); j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * 分数 */ 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 = da[random.nextInt(4)]; /** * 虫子的位置 */ 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 Game() { 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); 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); } /** * 游戏主循环线程 */ new Thread() { @Override public void run() { while (true) { if (System.currentTimeMillis() - crrTime > 500 / speed) { synchronized (Game.class) { moveSnake(); if (!checkSnack()) { JOptionPane.showMessageDialog(null, "Game Over!"); return; } } repaint(); crrTime = System.currentTimeMillis(); } } }; }.start(); } /** * 判断贪吃蛇是否撞墙或撞到自己 * @return */ protected boolean checkSnack() { Point p = snake.getFirst(); int x = p.x, y = p.y; if (x < 0 || x >= tableWidth || y < 0 || y >= tableHeight) { return false; } Iterator<Point> it = snake.iterator(); it.next(); while (it.hasNext()) { Point pBody = it.next(); if (p.equals(pBody)) { return false; } } return true; } @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 (Game.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.setColor(new Color(0x555555)); g.clearRect(0, 0, tableWidth * sellSize, tableHeight * sellSize); for (int i = 0; i < tableWidth; i++) { for (int j = 0; j < tableHeight; ++j) { g.drawRect(i * sellSize, j * sellSize, sellSize, sellSize); } } g.setColor(new Color(0x3399cc)); for (Point p : snake) { g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); } g.setColor(new Color(0x115599)); Point p = snake.peek(); g.fillRect(p.x * sellSize, p.y * sellSize, sellSize, sellSize); g.setColor(new Color(0xdd7744)); g.fillRect(target.x * sellSize, target.y * sellSize, sellSize, sellSize); } }
下节预告:拆分文件
发表评论
-
代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager
2012-10-21 22:50 1070继续题外话: 上一篇忘记发布到博客频道了,都没有人看到,这次 ... -
代码重构-以贪吃蛇为示例(四)-继续封装
2012-10-19 10:55 781题外话:本人第一次写技术文章,希望寻求鼓励啊,发了四篇了一个评 ... -
代码重构-以贪吃蛇为示例(三)-封装Snake
2012-10-17 15:44 1712通过上一节的分离我们可以使程序的流程更清楚,但是这些功能还是冗 ... -
代码重构-以贪吃蛇为示例(二)-分离入口、内部类,抽离函数
2012-10-16 22:19 1245面对这么乱的代码,第一步就是把想关性不太大的部分抽离出去。具 ... -
代码重构-以贪吃蛇为示例(序)
2012-10-16 15:22 973在正文之前,先说点题外话。 首先,作为一名学习了2年Ja ...
相关推荐
在本篇博客“代码重构-以贪吃蛇为示例(四)-继续封装”中,作者通过实现贪吃蛇游戏来阐述代码重构的重要性和具体实践。贪吃蛇游戏是许多程序员学习编程时的入门项目,它包含了基本的逻辑控制、用户输入处理以及游戏...
在本篇博客“代码重构-以贪吃蛇为示例(五)-封装Scoring和SpeedManager”中,作者通过重构一个贪吃蛇游戏的代码,深入探讨了软件开发中的两个重要概念:分数管理(Scoring)和速度管理(SpeedManager)。...
在本篇博文中,我们将深入探讨“代码重构”的概念,并以经典的贪吃蛇游戏为例,进行实际的重构实践,特别是如何对游戏中的主角——Snake(贪吃蛇)进行封装。这个过程将涉及到软件工程中的模块化、面向对象设计原则...
最近在csdn上看到一位大神用20行代码就写出了一个贪吃蛇的小游戏,感觉被惊艳到了,就试着读了一下这段代码,阅读过程中不断为作者写法的巧妙而叫绝,其中我发现自己对运算符优先级和一些js的技巧不是很清楚,所以看...
总的来说,【贪吃蛇安卓源码】是一个基础的Android游戏开发示例,涵盖了Android应用开发的基本框架和功能实现。通过研究这个项目,初学者可以了解Android应用的结构,掌握Java编程和Android SDK的使用,同时也能学习...
这个"Flash 3.0 贪吃蛇"小游戏是一个典型的AS 3.0编程示例,它展示了如何利用Flash来实现一款经典游戏的重构。 1. **ActionScript 3.0基础** - AS 3.0是Flash Player 9及更高版本中的主要脚本语言,与AS 2.0相比,...
【标题】"java+GUI做的一个贪吃蛇小...通过分析和重构代码,可以学习到如何将业务逻辑与用户界面相结合,以及如何用Java实现动态的图形效果。同时,它也是一个良好的示例,展示了如何将编程理论知识应用到实际项目中。
6. **IT技术分享**:这可能包含了技术文档、教程、示例代码等,可以帮助学习者了解最新的IT技术和最佳实践。 在【压缩包子文件的文件名称列表】中提到的"ahao3"可能是某个文件或子目录的名字,但由于信息不全,无法...
- **代码重构**:分析已有的游戏代码,优化结构,提升代码质量。 - **参与开源项目**:加入开源游戏项目,与其他开发者合作,共同完成更复杂的任务。 总之,"C语言经典小游戏 c 小游戏"不仅是一个学习C语言编程的...
- **经典游戏重构**:可能包括贪吃蛇、俄罗斯方块等简单游戏,通过源码了解游戏循环、碰撞检测、分数系统等基本机制。 - **物理引擎**:某些示例可能涉及到Box2D,这是一个物理模拟库,常用于实现物体的碰撞和运动...
总的来说,这个JavaGame游戏开发入门源码合集是一个宝贵的学习资源,通过实践和调试这些代码,你可以逐步掌握游戏开发的关键技能,并为创建自己的Java游戏打下坚实的基础。记得在学习过程中,不仅要理解代码的功能,...
"games-master"项目是学习和实践Python游戏开发的好资源,通过研究和重构其中的代码,不仅可以掌握Python编程基础,还能深入了解游戏设计和实现的细节。无论你是游戏开发的新手还是经验丰富的开发者,这个项目都为你...
这款游戏不仅为玩家提供了经典的“贪吃蛇”体验,更是一个生动的教学示例,它展示了如何在C++环境下通过Qt库来实现蛇的运动和伸长机制。 首先,我们来看C++作为编程语言的角色。C++是一种通用、面向对象的编程语言...
{2.10.3}静态代码块}{62}{subsection.2.10.3} {2.11}\ttfamily final}{63}{section.2.11} {2.12}\ttfamily abstract}{63}{section.2.12} {2.13}\ttfamily interface}{64}{section.2.13} {2.14}JavaBean规范}{66...