“俄罗斯方块”游戏设计开发.doc_第1页
“俄罗斯方块”游戏设计开发.doc_第2页
“俄罗斯方块”游戏设计开发.doc_第3页
“俄罗斯方块”游戏设计开发.doc_第4页
“俄罗斯方块”游戏设计开发.doc_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

I 摘要摘要 俄罗斯方块是一款非常经典游戏 风靡全球 经久不衰 是学习面向对象的 编程思想的理想实例 现在面向对象的计算机编程语言很多 都可以编程来实现 本毕业设计论文介绍用 Java 语言设计一个 俄罗斯方块 游戏的过程 整个 游戏系统是一个应用程序 Java Application 不再是嵌入到网页里的那种小应 用程序 Applet 并使用了最新的 Java 2 标准 Swing 组件 使得界面更具有专 业效果 游戏设计过程中涉及到游戏框架 游戏界面的编写 菜单处理 变量的 定义 算法设计以及预览功能的实现 同时 还为游戏添加了其他功能 如设计 About 对话框 实现游戏分数的存档 为游戏添加状态栏 通过本次毕业设计可以学到如何定义类和类成员及其方法 如何使用 JBuilder 来创建工程 如何创建一个对话框 并将对话框和主应用程序联系起来 关键词 俄罗斯方块 应用程序 Swing 组件 Java II ABSTRACT Tetris is a classic and durable game and it has been popular all over the world And it s an ideal sample for leaning object oriented programming It can be implemented by different object oriented programming languages that exist nowadays This thesis describes the implementing process of this game in java language which is implemented in application form instead of applet that embedded in the web pages The use of swing component makes the interface look more professional The game designs in the process to involve to the game frame the compilation of game contact surface menu processing the definition of variable the design of algorithm as well as the realization of the function of preview are involved in the process of designing this game Meanwhile some other functions are also added to the game such as designing About dialog achieving the archive of the game scores adding status bar to the game Through this thesis we can learn how to define classes class members and the methods how to use JBuilder to create works how to create a dialog and how to link the dialog box and the main application Keywords The Russian Block the application procedure the Swing module Java III 目录 摘要 I ABSTRACT II 第 1 章 绪论 1 1 1 研究背景 1 1 1 1 游戏的历史 1 1 1 2 游戏的意思与涵义 2 1 2 研究内容 3 第 2 章 开发工具的选择 4 第 3 章 可行性研究 6 3 1 设计目的 6 3 2 可行性研究前提 6 3 3 可行性分析 6 3 3 1 管理可行性 6 3 3 2 经济可行性 7 3 3 3 技术可行性 7 3 3 4 社会可行性 7 3 4 本章小结 7 第 4 章 需求分析 8 4 1 引言 8 4 2 游戏的需求 8 4 3 方案论证 9 4 3 1 C 的优点 9 4 3 2 Java 的优点 9 4 3 3 方案的选择 10 4 4 本章小结 11 第 5 章 概要设计 12 5 1 游戏设计分析 12 5 1 1 方块类型数据 12 5 1 2 程序运算逻辑 12 IV 5 1 3 绘图 12 5 1 4 显示平台 12 5 2 注意事项 13 5 3 游戏流程图 13 5 4 本章小结 14 第 6 章 系统详细设计 15 6 1 设计游戏框架 15 6 1 1 编写游戏框架 15 6 1 2 为游戏编写菜单项 15 6 1 3 为菜单增加事件处理 16 6 2 设计游戏界面 17 6 2 1 在 Panel 中加入几个必要的常量和变量 17 6 2 2 在 Panel 上面画出游戏界面 18 6 2 3 将 Panel 加到框架中去 19 6 3 游戏内容的设计 20 6 3 1 描述方块 20 6 3 2 描述游戏状态 21 6 3 3 初始化游戏状态 21 6 3 4 编写新的方块组的算法 21 6 3 5 编写方块组移动的算法 23 6 3 6 编写消去一行的算法 24 6 3 7 游戏里实现一个线程 26 6 3 8 控制游戏开始 26 6 3 9 让游戏暂停 28 6 3 10 让游戏结束 29 6 3 11 判断游戏是否结束 30 6 3 12 让玩家控制游戏 30 6 3 13 重新编写画图的功能代码 32 6 3 14 类的同步方法 33 6 3 15 计算游戏得分和当前游戏级别 34 6 4 添加游戏的其他功能 34 V 6 4 1 设计 关于 对话框 34 6 4 2 设计设定游戏等级的对话框 35 6 4 3 添加状态栏 36 6 5 封装得分情况 37 6 5 1 定义 Score 类和类成员 38 6 5 2 定义方法 writeToFile 38 6 5 3 定义方法 readFromFile 38 6 5 4 定义方法 sortScore 38 6 5 5 定义方法 isScoreTop int nScore 39 6 5 6 定义方法 insertNameScore String sName int nScore 39 6 5 7 定义方法 getScore 和 getName 39 6 6 让玩家输入名字 39 6 6 1 输入玩家名字的对话框 39 6 6 2 查看排行榜的对话框 40 6 7 系统完成后的主要界面效果 41 6 8 本章小结 41 第 7 章 系统测试 42 7 1 发现问题 42 7 2 解决问题 42 7 3 本章小结 44 第 8 章 游戏打包发布 45 8 1 打包的好处 45 8 2 如何打包 45 8 3 本章小结 46 第 9 章 结论 47 致谢 48 参考文献 49 1 第第 1 章章 绪论绪论 1 1 研究背景研究背景 游戏开发至今已经有 30 多年 在这个短暂的时期里 随着硬件平的提高 游戏开发新技术层出不穷 经典游戏比比皆是 1 1 1 游戏的历史游戏的历史 1 电子游戏的起源 真正的电子游戏机产生于 20 世纪 70 年代 1971 年 麻省理工学院的学生 Nolan Bushnell 设计了世界上的第一个业务用游戏机 俗名街机 叫做 电脑空 间 这台游戏机用一台黑白电视机作为显示屏 用一个控制柄作为操纵器 不 过由于市场因素这款游戏以失败告终 但是最后他在电子游戏的发展上取得了非 凡的成就 上面介绍的是专用机游戏的历史 而最早的电脑游戏可以追溯到 1972 年 一个叫 Crowther 的工程师用当时最流行的主机 DEC 公司的 PDP 10 编 写一段简单的 FORTRAN 程序 在这个程序里 Crowther 设计了一张地图 地图 上不规则的分布着陷阱 游戏者必须寻找路径避开陷阱 这个程序被公认为是最 早的电脑游戏程序 1989 年 BroderBund 公司的设计师乔丹 麦克纳根据阿拉伯 民族的古老传说 一千零一夜 在 Apple 平台上制作了一部动作冒险相结合的电 脑游戏 波斯王子 这个游戏获得了第一作 它代表了当时电脑技术的最高水 平 1986 年 任天堂公司发售了一款真正的游戏巨作 超级马里奥 20 世纪 80 年代 IBM PC 兼容机的出现打破了 Apple 公司的垄断地位 到了 20 世纪 90 年 代 游戏业才真正成熟起来 成为了一种产业 由于 PC 机价格非常低而且硬件 速度越来越快 游戏逐渐成为人们生活中不可缺少的一部分 游戏产业也逐渐发 展成熟 2 图形硬件的发展 图形硬件的飞速发展是近些年来的事情 部分原因是来自工业方面的压力 例如在军事和医疗方面对于实时图形的需求很强烈 而交互娱乐产业也极大的推 动了图形硬件的发展 技术上的因素同样也推动着图形硬件的发展 许多图形算 法可以很容易地表达为并行方式 这样硬件执行的效率变得很高 摩乐定律也起 了作用 越来越多的晶体管可以集成到一块单独的芯片上 在所谓的 GPU 图形 2 处理器 概念出现以前 特殊的图形硬件只出现在诸如 SGI 和 E TetricsFrame start actionAdapter TetricsFrame adaptee this adaptee adaptee public void actionPerformed ActionEvent e 17 adaptee start actionPerformed e 下面是相应监听器的代码 private void jbInit throws Exception start setText 开始游戏 start addActionListener new TetricsFrame start actionAdapter this 6 2 设计游戏界面设计游戏界面 接下来开始写游戏的界面 将游戏写在一个 Panel 上面 我们再新建一个类 让它从 java awt panel 里继承 将它命名为 Tetrics 游戏 的主要功能都要在这个类里实现 代码如下 public class Tetrics extends JPanel implements Runnable KeyListener public Tetrics 6 2 1 在在 Panel 中加入几个必要的常量和变量中加入几个必要的常量和变量 1 定义颜色常量 定义两个常量 一个定义 Panel 的背景颜色 BAKCOLOR 另一个定义 Panel 的前景颜色 FORCOLOR final Color BAKCOLOR new Color 80 123 166 final Color FORCOLOR Color black 2 定义坐标常量 定义左边用来显示预览分数 走的步数的区域的宽度 final int XOFFSET 200 3 定义必要的常量 定义每个小方块的宽度 int m nSqLength 18 定义行数和列数 static int m nCols static m nRows 6 2 2 在在 Panel 上面画出游戏界面上面画出游戏界面 1 初始化变量 在 Panel 的构造方法里将 Panel 的背景颜色设为背景色常量 并且为必要的 变量赋上一个初始值 关键代码如下 public Tetrics super try jbInit catch Exception ex ex printStackTrace 重载构造方法 拥有 TetricsFrame 变量 方便传递函数 public Tetrics TetricsFrame tFrame super m tFrame tFrame try jbInit catch Exception ex ex printStackTrace void jbInit throws Exception this addKeyListener this 设置初始参数 m nSqLength 20 19 m nCols 10 m nRows 20 2 画出界面来 这里使用到 Panel 的 paint 方法 加一些功能代码 让整个 Panel 能够画出一 个初始的界面来 关键代码如下 public synchronized void paint Graphics g g setFont new Font 宋体 0 18 int gx m nSqLength int gy m nSqLength m nRows 4 打印 Score 和 LEVEL 的位置 g drawString 分数 m nTheScore gx gy gy 30 g drawString 级别 5 gx gy 画浏览的方块 int middle m nCols 2 int top m nRows gy 30 g setColor Color darkGray 清除预览的方块组 g fillRect gx gy m nSqLength 4 m nSqLength 4 画游戏区 for int i 0 i m nCols i for int j 0 j 0 6 3 2 描述游戏状态描述游戏状态 接下来定义一些描述游戏状态的变量 这些变量都定义在 Tetrics 类中 例如 判断当前游戏是不是正在玩 m bGameInPlay 判断当前是不是需要一个新的方块 组 m bNeedNewPiece 游戏的级别 m nPlayLevel 方块组的分值 m nPieceValue 游戏的分数 m nTheScore 等等 这里不再一一详述 6 3 3 初始化游戏状态初始化游戏状态 在 jbInit 方法里 要在游戏开始之前需要初始化的量都初始化 例如定义游 戏运行界面的行列 m nCols 10 m nRows 20 等等 22 6 3 4 编写新的方块组的算法编写新的方块组的算法 游戏中用到 7 种不同的方块组 预先定义 7 种不同的方块组 1 定义 7 种不同的方块组 每个方块组都是由 4 个小方块组成的 每种有不同的组合方式 用随机数来 决定哪种类型的方块组 每种组合方式有自己相应的分数 例如红色长条形方块 组 分数为 100 产生代码如下 private void newPrePiece int middle m nCols 2 int top m nRows switch int Math random 7 红色长条形方块组 case 0 m nPieceValue 100 m prePiece 0 new Square middle 1 top 1 1 m prePiece 1 new Square middle 2 top 1 1 m prePiece 2 new Square middle top 1 1 m prePiece 3 new Square middle 1 top 1 1 break case 1 case 2 不再一一累述 这里将新产生的方块组放在 m prePiece 数组中 即预览的方块组 2 预览当前正在运行的方块组 当游戏需要一个新的方块组时 应该从预览的那个方块组里取得 然后重新 产生一个新的预览方块组 定义一个方法 将预览的方块组转变成当前正在移动 的那个方块组 代码如下 private void transferPreToCur 23 Square old new Square 4 old 0 old 1 old 2 old 3 new Square 1 1 0 for int i 0 i 4 i m curPiece i m prePiece i 效果如图 6 3 所示 图图 6 3 预览方块组预览方块组 6 3 5 编写方块组移动的算法编写方块组移动的算法 一个方块组应该是不断移动的 定义一个方法 来判断是否可以移动 如果 可以移动 返回真 反之 返回假 代码如下 boolean moveSquares Square from Square to outerlable for int i 0 i to length i if to i InBounds false return false if m nField to i m nColumn to i m nRow 0 for int j 0 j from length j if to i IsEqual from j continue outerlable return false 24 for int i 0 i from length i if from i InBounds m nField from i m nColumn from i m nRow 0 for int i 0 i to length i m nField to i m nColumn to i m nRow to i m nColor return true from 定义了没有移动之前的那个方块组 to 为要移到的方块组 下面编写一 个方法来移动当前玩的那个方块组 代码如下 private synchronized boolean moveCurPiece int nDx int nDy boolean bRotate Square newpos new Square 4 for int i 0 i 4 i if bRotate int dx m curPiece i m nColumn m curPiece 0 m nColumn int dy m curPiece i m nRow m curPiece 0 m nRow newpos i new Square m curPiece 0 m nColumn dy m curPiece 0 m nRow dx m curPiece i m nColor else newpos i new Square m curPiece i m nColumn nDx m curPiece i m nRow n Dy m curPiece i m nColor if moveSquares m curPiece newpos false return false m curPiece newpos return true 6 3 6 编写消去一行的算法编写消去一行的算法 当方块组摆放的位置刚好使得一行的方块都填满时 应该将这一行消去 编 25 写一个方法 遍历每一行 对每一行都进行检查是不是已经填满 如果填满了方 块 则上面的方块都整体的往下移动一格 关键代码如下 private void removelines outerlabel for int j 0 j m nRows j for int i 0 i m nCols i if m nField i j 0 continue outerlabel for int k j k m nRows 1 k for int i 0 i m nCols i m nField i k m nField i k 1 j 1 效果如图 6 4 6 5 和 6 6 所示 图图 6 4 消去满行前的效果图消去满行前的效果图 26 图图 6 5 满行时的效果图满行时的效果图 图图 6 6 消去满行后的效果图消去满行后的效果图 6 3 7 游戏里实现一个线程游戏里实现一个线程 在游戏里 方块组可以自己不停地往下走 碰到下面的方块后就会在顶部产 生一个新的方块组 继续往下走 一直到整个方块组刚一产生就没有路可走的时 候 游戏就结束了 鉴于游戏特点 用线程来控制这个游戏 首先声明要实现 Runnable 接口 代码如下 public class Tetrics extends JPanel implements Runnable 然后增加一个线程的成员 代码如下 Thread m theThread null 27 定义一个 run 方法 在方法中加入要让游戏做的事情 不停的移动方块 移 动到底部的时候 就检查游戏是不是有可以消去的行 如果有 就消去 然后再 新建一个方块组 中间还要判断游戏是不是已经结束了 6 3 8 控制游戏开始控制游戏开始 在方法里定义一个线程 然后让这个线程开始运行 还要注意一点 就是要 重新给一些变量赋值 如 游戏的分数等 还要考虑这么一种情况 就是当点击 暂停 按钮之后的开始 不是用来重新开始的 而是接着刚才的状态往下玩 那么就应该在 start 方法的一开始来判断游戏是否是暂停 如果是暂停的 就不 将游戏的状态重新刷新一次 关键代码如下 if m theThread null 游戏是被暂停 而不是重新开始 m theThread resume m bPaused false this repaint return 重新开始赋上游戏的状态 for int i 0 i m nCols i for int j 0 j m nRows 4 j m nField i j 0 m nOldField i j 1 m nTheScore 0 m nTotalPieces 0 m bNeedNewPiece true 28 m bGameInPlay true m theThread new Thread this newPrePiece m theThread start this repaint this update this getGraphics 效果图如图 6 7 所示 图图 6 7 开始游戏开始游戏 6 3 9 让游戏暂停让游戏暂停 这个功能可以通过将线程简单地挂起来实现 首先我们应该判断游戏的线程 是否为空 也就是用来判断游戏是否正在玩 如果是 则将这个线程挂起 并将 m bPaused 标志为 true 否则退出 不进行任何操作 29 关键代码如下 if m theThread null try m theThread suspend m bPaused true catch Exception e e printStackTrace 游戏暂停效果如图 6 8 所示 30 图图 6 8 暂停游戏暂停游戏 6 3 10 让游戏结束让游戏结束 先要判断当前游戏是不是正在进行 如果是 则结束当前游戏的线程 否则 就不进行任何操作 游戏结束如图 6 9 所示 31 图图 6 9 游戏结束游戏结束 6 3 11 判断游戏是否结束判断游戏是否结束 到这里 游戏可以运行了 但是游戏始终不会结束 即使在方块组一出现就 无法可走时 游戏仍然没有结束 这是因为没有加入任何判断游戏是不是已经结 束的代码 编写一个方法来实现这个功能 在 transferPreToCur 中定义了一个当 前运动的方块组 如果在这里先定义一个 old 方块组 这个方块组里的方块全是 由 new Square 1 1 0 来定义的 这是执行 moveSquares old m curPiece 方法就会 发现 当游戏结束时 moveSquares 方法返回假 而当游戏还没有结束的时候 moveSquares 方法返回真 这样就可以简单地通过修改 transferPreToCur 方法来 达到判断游戏是否结束的目的 在游戏结束的时候 将 m bGameInPlay 标志为假 效果图如图 6 9 所示 6 3 12 让玩家控制游戏让玩家控制游戏 1 添加键盘事件处理 32 采用重载 Panel 的 keyDown Event evt int nKey 方法来实现键盘事件的处理 在老式的消息处理机制中为每个组件都定义了 keyDown keyPress 等方法 分别 为键盘进行某种动作的时候要调用的方法 现在我们在 keyDown 中加入一些功能 代码 那么当键盘按下的时候 就会执行这些功能代码 这个方法的返回类型为 boolean 若返回真 则其他任何组件都不会对键盘事 件再次处理 如果为 false 键盘消息将发送到上一级组件继续处理 要做的处理是这样的 首先要判断游戏是否正在玩 如果不是 则返回 然后还应该判断游戏是否 已经暂停 如果不是 也返回 此后 应该判断按下的是哪个键 是 A W S D 键 中的任意一个 就可以调用移动方法相应地往某个方向移动 流程图如图 6 10 所示 图图 6 10 按键流程图按键流程图 2 让 Panel 获得焦点 焦点就是当前接受事件的组件 整个游戏是放在 Panel 里的 应该将键盘事 件处理的代码也放到 Panel 中 所以接受键盘事件的组件也是 Panel 假如是 按键 判断按键 W 键 moveCurPiece 0 0 true S键 moveCurPiece 0 1 false A 键 moveCurPiece 0 1 false D 键 moveCurPiece 1 0 false 不需要新的方块组 执行 this update this getGraphics 刷新界面 33 Frame 的话 就无法在按下键盘的时候让 Panel 里的游戏获得这个键盘的消息 所以 要做的第一件事就是应该将当前接受事件的组件定位为我们正在编写的 Panel 这个功能实现起来很简单 每个组件里都有一个 requestFocus 方法 用来请 求获得焦点 可以直接在游戏开始时调用这个方法 将下面这行代码加到 start 方法里即可 requestFocus 6 3 13 重新编写画图的功能代码重新编写画图的功能代码 1 重载 update 以减少画面的闪烁 默认的 update 是先使用默认的背景颜色填充窗口 再调用 paint 方法 这 样窗口在重画时 常常会感觉到闪烁 避免闪烁的比较好的方法就是重载 update 使它完成所有必要的显示功能 然后在 update 中直接调用 paint 首先应该定义类成员变量 m bJustupdating 用来表示是否刚刚调用过 update 方 法 如果是调用过 update 方法然后再调用 paint 方法 就应该将所有的方块组 都重画一遍 以保证当编写的游戏被另一个程序遮住之后 再显示出来的时候能 够全部重画 2 在 paint 方法中加入功能代码 前面已经把界面简单画出来了 但是 对于游戏的方块组以及下面堆砌的方 块它却没有画 游戏得分和级别关键代码如下 g drawString 分数 m nTheScore gx gy g drawString 级别 m nPlayLevel gx gy 画预览的方块组 预览的方块组为 m prePiece 关键代码如下 if m bGameInPlay for int i 0 i 4 i g setColor m colors m prePiece i m nColor g fill3DRect m prePiece i m nColumn middle 2 m nSqLength gx gy m prePiece i m nRow top m nSqLength m nSqLength m nSqLength true for int i 0 i m nCols i 34 or int j 0 j m nRows j 1 代表没有刚刚开始 if m bJustupdating m nOldField i m nRows 1 j 1 m nOldField i m nRows 1 j m nField i m nRows 1 j g setColor m colors m nField i m nRows 1 j g fill3DRect XOFFSET m nSqLength i m nSqLength m nSqLength j m nSqLength m nSqLength true m nOldField i m nRows 1 j m nField i m nRows 1 j m bJustupdating false 此时界面效果图如图 6 11 所示 图图 6 11 最终界面图最终界面图 35 6 3 14 类的同步方法类的同步方法 对一个类的方法声明同步就相当于对这个方法加上了一把锁 一个类里所有 声明同步的方法都保持同步 也就是说当我们调用了这个类中的任何一个同步方 法时 其他所有声明同步的方法 限于这个类里 或资源都会被锁定 不让其他 类的任何方法去访问 一直到那个同步方法被释放 用到同步方法 是为了避免 同一个资源或方法被其他方法同时使用或调用 造成资源的崩溃 这种情况只出 现在多线程的程序里 在游戏中 也需要这么一把锁 以避免有些资源被同时访问 比如应该将 movePiece 和 paint 方法同步 因为这两个方法之中 一个对当前游戏状态的数 组进行了修改 一个使用了这个状态数组 如果不设置同步 会出现游戏状态修 改了一半就被画出来的现象 在移动方块组的时候 有时方块组会多出部分方块 或少了部分方块 6 3 15 计算游戏得分和当前游戏级别计算游戏得分和当前游戏级别 计算游戏得分 是通过赋给每一个方块组一个分值的办法来实现的 当摆好 一个方块组后 游戏如果没有结束 则这个方块组的分值就会累加到你的分数之 上 对于游戏等级的划分 是通过当你每玩过 30 个方块组的时候 游戏等级就 会自动累加 1 这样 可以给玩家增加一点挑战性 这部分代码是在 run 里实现 的 6 4 添加游戏的其他功能添加游戏的其他功能 6 4 1 设计设计 关于关于 对话框对话框 一个完整的应用程序都是应该有 关于 对话框的 在这个对话框里 一般 要放上一张标志性的图片 然后再有一段说明 最后再有一个 确定 按钮 用 JFrame 类来产生这个对话框 1 设计装载图片的面板 定义一个类 PicPanel 来装载图片 用 Class 接口来定位这个 URL forName String s 取得 S 类的 Class 接口对象 是 Class 的静态方法 getResource String name 取得一个名为 name 的资源 返回值为这个资源的 URL 36 要是在应用程序里取得资源 a txt 的 URL 这个资源和 TFrame 类同在一个目录里 就可以这样写 URL url Class forName TFrame getResource a txt 不过 由于 Class forName 方法在出错时会抛出异常 所以要捕获这个异常 这 里有必要使用到 Toolkit 提供了很多有用的方法 取得一个图片资源的 URL 并将它装入 主要方法为 initImage 在构造方法中调用这个方法以装载图片 然后在 paint 方法中将它画到 Panel 上面 2 编写 关于 对话框 这里可以用 JBuilder 的 Designer 来设计这个对话框 3 在菜单里打开 关于 对话框 相关代码都设计完后 还应该在游戏菜单中选择 关于 时 能够弹出对话 框 可以在 MenuListener 类中的 actionPerformed 方法里添加相关代码 效果如图 6 12 所示 图图 6 12 关于关于 对话框对话框 6 4 2 设计设定游戏等级的对话框设计设定游戏等级的对话框 1 Dialog 类 Dialog 类是一种特殊的 Frame 它只能放到应用程序的最高层 它一般是用 来给用户提供某种信息或者获得某种信息而创建的 Frame 即对话框 对话框的 方法几乎和 Frame 的方法一样 它也有 setSize setLocation 等方法 可以使用 这些方法创建 Dialog 37 现在是个空的 Dialog 新建一个 JPanel 命名为 levelDialog 然后在它的上 面放置一个对话框必须有的东西 然后将这个 Panel 加到对话框里 新建这么一 个 JPanel 类 在 levelDialog 中定义一个成员对象 用来保存 levelDialog 所属于 的 Dialog 对象 修改 levelDialog 的构造方法 在创建对话框的时候 可以同时创 建一个 levelDialog 对象 并将它加入对话框里 2 用 JBuilder 的 Designer 来设计对话框 新建一个类 levelDialog 使用滚动条来设定游戏的级别 3 使设定游戏级别对话框生效 要使这个对话框能够控制游戏 必须能够获得游戏的主体 Tetrics 对象 在构 造对话框中的 Panel 时传入这个对象 然后就可以编写代码处理对话框的各个事 件 点击 Button 能够关闭窗口 增加滚动条的 changeListener 使得滚动条的值改变时 能够同时改变游戏的 级别 在对话框刚刚打开的时候 使得对话框显示的就是游戏当前的级别 效果如 图 6 13 所示 图图 6 13 设置级别设置级别 对话框对话框 6 4 3 添加状态栏添加状态栏 1 border 布局 对于 Java 的界面管理 要保证在各个运行平台上都能保持一致 这里要用到 BorderLayou 这是一个简单的 Layout 它有 5 个位置 South North West East Center 2 用 JPanel 来实现 StatusBar 38 为 TFrame 安装Border 布局 然后在 Center 处装入游戏 在 South 处装入游 戏状态栏 StatusBar 通过在 JPanel 中加入一个 JLabel 来实现 在 TFrame 中定义 两个类成员 一个是表示 StatusBar 的那个 JPanel 对象 另一个是 JLabel 对象 接下来在 myInit 方法 在构造方法里调用 中加入状态代码 然后在改变状态 信息的地方直接调用 m lStatus setText String s 就可以了 例如在开始游戏时 在游戏界面的下方显示 开始游戏 暂停游戏时显示 暂停游戏 结束游戏时显示 结束游戏 刚运行时显示 游戏装载完毕 游戏装载完毕的状态图如图 6 14 所示 图图 6 14 游戏装载完毕游戏装载完毕 开始游戏的状态图如图 6 7 所示 暂停游戏的状态图如图 6 8 所示 游戏结 束的状态图不再画出 39 6 5 封装得分情况封装得分情况 下面要编写一个类 用来从文件 档案 中取得原来玩家的得分 也提供方 法将现在的玩家的分数写入到文件 档案 中 6 5 1 定义定义 Score 类和类成员类和类成员 这个类提供 3 个方面的服务 取得存档文件里的玩家的名字和分数 定义方 法名为 getScore 和 getName 判断一个分数是不是进入了前十名 定义方法名为 isScoreTop int nScore 将一个玩家的名字和分数插入到存档中 定义方法名为 insertNameScore String sName int nScore 这 3 个服务是这个类的公有方法 对于这些方法所要实现的底层细节以应该 给予保护 比如我们需要从文件里取得玩家的名字和得分 以及往文件里写等等 细节 都要封装起来 不让类外的对象调用 对于类的成员 我们要定义一个 String 数组来保存存档文件里的玩家名字 一个整型数组来保存玩家的分数 在 类的构造方法里 还应该给这些信息初始化 6 5 2 定义方法定义方法 writeToFile 首先定义存档文件里信息的组织方式 准备在文件中存储十个玩家和相应的 十个分数 定义信息的组织方式 每个用户的信息用 分开 每个用户的名字 和分数用 分开 所有这些信息都连续地放到文件之中 在文件里存有如下 内容 张三 1500 李四 990 王五 900 周六 800 韩七 700 赵八 600 顾红 500 邱一 400 李位 300 张图 200 先根据 m nScore 和 m sName 的情况来生成这个字段 然后将这个字段写入 文件就好了 算法是这样的 先遍历玩家的名字数组和分数数组 按规定的方式 来生成一个字符串 最后将字符串写入 6 5 3 定义方法定义方法 readFromFile 从文件读出存档的方法 利用 FileReader 类来实现 读完文件把内容放在 String 里 还要进行处理 以便能够将存档的信息提取出来 StringTokenizer 是 一个字符串的分析器 能够将字符串分隔开来 算法是这样的 不断地从文件里 取字符数组 并将字符数组添加到一个 String 的后面 一直到文件被读完 这样 这个文件的所有内容都被放到了这个 String 里 然后按保存存档的格式来分析这 个字符串 将分析的结果放到玩家名字的数组和玩家分数的数组里 40 6 5 4 定义方法定义方法 sortScore 对分数进行排序的算法 要将显示出来的分数从高到低排序 也就是 第一 个看到的分数应该是第一名 这是游戏排行榜的要求 这里采用冒泡法来排序 先遍历所有的分数 将最高的分数放到第一个 然后再遍历其他分数 再将最高 的放到第二个 一直到最后一个 6 5 5 定义方法定义方法 isScoreTop int nScore 该方法是这个类提供给外部类的一个服务 要将这个方法声明为 public 该方法要判断这个分数是否比记录的分数要高 如果比记录里的所有分数都 低 那么这个分数不会被记入档案 6 5 6 定义方法定义方法 insertNameScore String sName int nScore 提供给外部类的一个服务 声明为 public 这部分的算法如下 首先判断这个分数是否已经到前十名 我们的存档只存 前十名 如果不是 则直接返回 然后对分数进行排序 然后替换掉最后一个 再排一下序 存入文件 6 5 7 定义方法定义方法 getScore 和和 getName 提供给外部类的一个服务 声明为 public getScore 方法是返回 Score 类中存储所有分数记录的数组 getName 方法是 返回存储所有玩家名字的数组 6 6 让玩家输入名字让玩家输入名字 封装完后 如果需要对玩家的分数进行什么操作的话 直接调用 Score 里的 方法就行了 下面编写两个对话框 一个是在玩家玩完游戏之后 若玩家的分数 很高 比档案里的某一人的分数要高 才弹出的 这个对话框提示玩家已经进入 了前十名 让玩家输入他的名字 另一个对话框是提供给用户的 让用户能够查 看当前的排行榜 6 6 1 输入玩家名字的对话框输入玩家名字的对话框 这里也是用 JBuilder 提供的 Designer 来设计对话框的 Panel 命名为 InsertPanel 定义 dialog 包里 在这个 Panel 里加入三个 Panel 和两个 TextFiled 41 首先定义几个类成员 m dialog 来保存必要的对象 在构造方法里将这个类 需要的对象传入 增加 确定 取消 按钮的功能 在 TFrame 类里增加弹出 这个对话框的方法 定义为 insertScoreReport 在这个方法里 先判断这个分数 是不是应该往存档文件里写 如果是 就新建一个对话框 并将它上面做的这个 Panel 加入进去并显示出来 在游戏结束时调用 TFrame 类的 insertScoreReport 方 法 可以在 Tetrics 里加入部分代码来实现这个功能 效果如图 6 15 所示 图图 6 15 输入玩家名字输入玩家名字 6 6 2 查看排行榜的对话框查看排行榜的对话框 定义这个对话框为 ScoreReportP 从 Panel 派生 也放在 dialong 对话框里 这个对话框上面包含一个 Panel 然后还有一个 button 可用 desinger 设计 然后 加入功能代码 将玩家的记录显示出来 myInit 在这个方法里用 Score 里的 getName 和 getScore 将文件里的记录取出来 然后创建新的 TextFiled 和 Label 将记录里的值赋给这些组件 让它们能够显示文件里的记录 然后顺序的 加入 jPanel 我们在 ScoreReportP 里添加的小 Panel 在 TFrame 的菜单里加入 查看记录的菜单 在 TFrame 的 addMenu 方法里加入这个菜单 然后在 MenuListener 的 actionPerformed 方法里加入相应的处理代码 运行结果如图 6 16 所示 42 图图 6 16 分数报告分数报告 6 7 系统完成后的主要界面效果系统完成后的主要界面效果 到这里 游戏的主题及相关功能已经设计完毕 主要运行界面如图 6 17 所示 43 图图 6 17 主要界面效果主要界面效果 6 8 本章小结本章小结 这一章是整个设计的主题部分 从游戏的框架 游戏界面 游戏内容 封装 得分 输入玩家名字等各个模块进行了分析与设计 每个模块的设计又包含各个 功能的实现 其中最重要的是游戏内容的设计 游戏的核心算法即在此设计 比 如 判断满行 消去满行 移动方块组等算法 还讲到了如何用键盘来控制游戏 加入状态栏 设计 关于 对话框等模块的设计 最后实现整个游戏功能 第第 7 章章 系统测试系统测试 到这里 游戏的基本功能及相关功能已实现 但是经过对各个方法及模块的 反复测试 如消去满行的方法 移动方块组的方法 将预览的方块转变成游戏区 内的方块的方法 设置级别的模块 关于 对话框的模块 查看分数的模块等 还有些地方不够完善 有些问题 7 1 发现问题发现问题 其中一个问题是 在游戏开始前或者游戏中时 当设置完游戏级别后 然后 结束游戏 再重新开始游戏 这时发现游戏的级别不是 0 而是当初设置的那个 级别 另一个问题就是 在游戏过程中 有时需要直接重新开始游戏 而不是结束 游戏后 再点 开始游戏 按钮来重新开始游戏 相对比较麻烦 这里加入一个 重新开始 按钮来直接重新开始游戏 界面如图 7 1 所示 44 图图 7 1 修改前的游戏菜单界面修改前的游戏菜单界面 7 2 解决问题解决问题 设置完游戏级别后 级别已经确定 为了使游戏结束后 再开始时的级别是 0 只要在控制游戏结束的代码里 加入使游戏级别为 0 的相关代码即可 代码 如下 控制游戏开始 public synchronized void stop m nPlayLevel 0 接着来解决 重新开始 按钮的问题 首先在 游戏 菜单选项里加入 重新开始 按钮 关键代码如下 JMenuItem restart new JMenuItem jMenu1 add restart 效果如图 7 2 所示 图图 7 2 修改后的游戏菜单界面修改后的游戏菜单界面 接着为按钮添加事件处理 采用 ActionListener 接口来做菜单的事件响应 代码如下 void restart actionPerformed ActionEvent e m tetrics stop m tetrics start jLabel1 setText 开始游戏 45 this repaint 下面添加控

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论