概述
基于Android平台的扫雷游戏
Download MinesweeperForAndroid_Source – 1.16 MB
扫雷-开始的截图
扫雷-新游戏的截图
扫雷-胜利的截图
扫雷-失败的截图
简介
扫雷是一个简单的单人游戏。游戏的目的是在没有触碰任何一个地雷的情形下清空一个雷区。扫雷不仅有Windows版本,也有其他平台的版本(包括大多数Linux的变体)。扫雷在Windows的用户中十分流行,自从Windows 3.1以来一直绑定在里面。
在这篇文章中我们创建一个Android版本的扫雷。我们将尝试Windows扫雷的大多数功能。这篇文章面向中高级别的开发者,并且需要熟悉Java 和Android开发。
关于游戏
在扫雷游戏中,游戏者要面对一片砖块组成的格栅,有些砖块包含随机设置的地雷。我们将实现一个典型的初学者级别扫雷游戏:行和列的数量都是9,一共有10颗地雷。扩展成中级和高级游戏很容易(只需要改编代码中的上述三个值)。
好吧,在这篇文章中我不会教你怎么玩游戏,但我们需要在实现前了解这个游戏的一些特点(Windows版本):
- 点击左键打开一个砖块
- 点击右键对砖块进行标记:插旗帜(表示下面有雷),标问号(不确定是否有雷),取消标记
- 第一个砖块下面永远没有雷;避免了一开始就要猜测的烦恼。
- 如果打开的砖块是空的,周围的砖块都会依次打开直到遇到数字砖块;类似涟漪的原理。
- 在一个砖块上同时点击左右键或者中键,如果周围的地雷都被标出来了,则会打开周围所有未打开的砖块。
- 点击第一个砖块时开始计时,在选择一个新游戏后不会开始计时。
已经啰嗦够多了,我们现在开始编写这个游戏
一步一步实现
解释和实现任何复杂系统的最好方法是一次一步进行。首先,我们探讨GUI,布局和应用的视觉。我们也会探讨创建布局时用到的一些技术。然后,我们讨论鼠标、点击和触摸事件的区别,以及应用的反应。最后一步关于实现整个游戏以及上面介绍过的功能。
视觉和触碰的感知体验
我们先讨论设计GUI的不同方面,包括总体的应用布局和一些创建游戏时需要用到的技术。
应用的布局
我们使用TableLayout进行扫雷的布局,在TableLayout上加入三行:
- 第一行包括用于计时的三列数字,新游戏按钮和剩余地雷数。我们使用TextView显示计时和地雷数。新游戏按钮使用ImageButton
- 第二行是50像素高的空的TextView,将第一行和雷区隔离开
- 第三行是另一个TableLayout,用来显示雷区。我们将动态的向这个区域添加按钮。
布局的代码如下(删去了一些额外的属性来节省空间):
使用外部字体
我们使用外部字体LCD mono(见源代码部分)来显示时间和地雷数。在Android中使用外部字体很容易,分为两步:
- 在工程的assets文件夹下创建字体文件夹,复制TTF(True Type Font)文件至字体文件夹。
- 通过调用createFromAsset 和传递TTF文件名创建一个Typeface对象。在这个对象中设置TextView的Typeface。代码如下:
使用风格
在我们的扫雷游戏里,点击新游戏的笑脸按钮会让这个笑脸变成紧张的表情。当按钮处于按压状态时(紧张的笑脸),我们需要一个不同的图像。当它处于正常状态时需要另一张图像。为了实现此功能,我们使用风格,效果如下:
使用风格也需要两步:
- 创建一个XML文件(风格定义文件),指定相应的按钮状态使用的图片。比如在按压状态下,我们需要惊讶(紧张)的图片,正常状态下需要微笑的图片。当然,这两幅图片已经复制到 res/drawable文件夹中了。风格文件的代码如下:
- 为新游戏按钮更新/添加背景的属性值,将它的值设定为上面创建的风格文件。更新后的ImageButton代码如下:
TableLayout中的动态行
动态添加砖块的原理相同(砖块是从按钮类继承的类,包含支持实现的额外功能)。我们希望它们像预想的那样工作,分为如下的几步:
- 创建一个TableRow对象,设置布局的参数值。
- 将砖块添加到上面创建的行对象中。
- 使用 findViewById 函数获得TableLayout(雷区)的样本。
- 将上边创建的行添加到TableLayout中
代码如下:
设置扫雷图标
改变应用的图标(图标在主页和启动窗口中显示)非常简单,因为这个工程有默认的图标,在 res/drawable 文件夹中名为 icon.png,改变/更新/替换工程中的icon.png,则新图标将在启动窗口中显示出来。了解关于Android图标设计的更多细节,请阅读图标设计指南。
用于多个像素版本的图像
正如我们都知道的,Android支持并能够在不同尺寸的设备上运行。这些设备可能有不同的屏幕尺寸,不同的高宽比,不同的分辨率,不同的密度和不同的像素支持。为了支持各种设备,我们必须定制不同设备所用的图像。而现在这是不可能的。Google推荐使用为三种普遍的屏幕密度设置不同图像的方法,这三种屏幕分别是 Low DPI,Medium DPI和High DPI。图像按照各自的密度分别复制到文件夹 res/drawable-hdpi,res/drawable-mdpi和res/drawable-ldpi中。如果希望Android自动调整图像(这种方法一点都不给力),那么仅需要设置一个图像(扫雷就使用这种方法),并将其复制到 res/drawable-nodpi文件夹。更多信息请阅读支持多种屏幕。
计算时间
开发游戏的最重要的事情就是跟踪时间。Java世界里的标准方法是使用java.util.Timer或者java.util.TimerTask 保持时间。这里麻烦的地方在于我们需要创建一个新的线程,一些情况下我们并不想这样。Android有更好的解决方案。我们可以使用类 android.os.Handler实现目标。
用Handler取代Timer
可以用两种方法使用Handler,一种是给Handler传递消息并在消息收到时执行特定的操作,另一种是在Handler中调度一个Runable对象。我们在扫雷中使用第二种方法,使用Handler的好处在于它和creator线程中的thread/message队列相联系。了解更多关于Handler的信息,请阅读Handler官方文档,实现handler的代码如下:
处理用户操作
在扫雷中,我们接受点击和长点击事件。点击事件表示点击鼠标左键,长点击事件表示点击鼠标右键。我们没有对触碰事件进行同样的设定,虽然我们也可以这样做,但是这样做的话应用就只能限制于触摸设备。而在可触摸设备上,可以用触摸来表示点击和长点击事件,而在不可触摸设备上,可以用滚轮和按键来表示点击事件和长点击事件。
理解鼠标的点击和电话的点击事件
Java提供实现鼠标按钮的功能,支持鼠标的点击/长按/释放,鼠标的移动/拖拽,鼠标的进入/退出,以及滚轮事件。对Android来说,在进入/退出事件和滚轮事件之上没有鼠标的概念。Android仅提供点击和触摸功能。点击包括普通的点击和长点击,点击事件不支持拖拽功能,触摸事件支持拖拽功能。
理解电话的点击和触摸事件
触碰事件将在以下状况中击发:用户在触碰模式下触碰一个项目,或者用导航键/跟踪球指向一个项目并按下进入键,或者用跟踪球指向一个项目并按下跟踪球。当用户完成符合触碰事件的操作时,触碰事件将被调用,包括按压、释放、或者屏幕上的任何移动操作(在该项目的范围内)。
理解电话的点击和长点击事件
点击事件将在以下状况中击发:用户在触碰模式下触碰一个项目,或者用导航键或跟踪球指向一个项目并按下进入键,或者用跟踪球指向一个项目并按下跟踪球。长点击事件将在下列状况下击发:用户在触碰模式下一直触摸一个项目,或者用导航键/跟踪球指向一个项目并一直按下进入键,或者用跟踪球指向一个项目并一直按下跟踪球(至少一秒)。
模拟左右键
Android不支持中间键的点击事件,我们使用长点击事件来模拟此功能。如果长点击事件在一个有数字的打开的砖块上发生,我们就能击发相应的功能。这部分的代码如下:
不可用按钮的事件
当一个按钮不可用时,我们不能在上面击发任何事件。为了克服这个缺陷,我们将这个键标为不可用并改变它的背景。事实上,一个键不可能真正丧失功能,它一直是可用的。在这种情况下,这个键仍然可用但假装不能用,而且可以接受事件。
决定策略
让我们回到游戏最重要的方面,来实现这个游戏。我们在这个部分讨论关于游戏部分中介过的功能。我们按照顺序一个一个实现(其中之一已经在模拟左右键中介绍过了)
完成流程图
扫雷游戏最重要的部分是处理用户操作。首先等待并接受用户输入,然后恰当的处理。我相信与其我用文字来解释,不如我用图表来解释的效果更好,图表的说服力更强。整个循环用下面的流程图表示:
从第一次点击开始
之前我们说过,计时器从第一次点击开始(打开第一个砖块),在按下新游戏按钮时不会开始计时。这一点对于控制时间来说非常重要,为了实现这个功能,我们只需创建一个布尔变量,只要接受到点击事件就检查此变量,开始调用Handler,然后改变此变量的值。这部分代码如下:
第一次点击没有地雷
用户的第一次点击不应该触发地雷,否则一开始就要猜测。因此我们在第一次点击后设置地雷。我们在用户刚刚打开的砖块之外的部分随机设置地雷(通过随机设置行和列的数字)。之后为所有砖块计算邻近的地雷数目生成数字砖块。这部分代码如下:
打开砖块的涟漪效果
用户在打开一个砖块后得到有关下一步的提示,如果打开的砖块是空的,用户就无法猜测地雷的情况并决定下一步操作。为了避免这种情况,我们打开空白砖块邻近的砖块,一直递归的打开直到遇见有数字的砖块。类似于涟漪的效果。递归打开空白砖块(涟漪效果)的代码如下:
在砖块上做标记
我们进一步讨论将砖块标记为旗子、问号和取消标记的方法。实现的方法直接明了,当我们收到非左右键点击的长点击事件时,我们检查砖块现在的状态。如果砖块上没有标记,就在上面插旗子(表示内有地雷),如果砖块上插着旗子,就在上面标问号(怀疑但不确定有地雷),而如果砖块上面有问号标记,就清除标记。我们只需要一些条件判断句就能实现:
在每一步检查游戏的输/赢
对滴,这一步非常重要。每次点击后都要检查游戏的状态,确保我们不会错过任何点击和任何砖块。当点击的砖块下边有地雷时,我们就输了。当所有包含地雷的砖块上插了旗子时,我们就赢了。代码如下:
测试/玩儿法
玩游戏的方法和Windows版是一样的。请留意以下关键点:
- 点击微笑按钮,开始一个新游戏
- 点击或者触摸一个砖块来打开它,这和Windows中的鼠标左键功能相同。
- 点击或者保持触摸一个砖块达到一秒,则对其进行标记,包括旗帜、问号或者清除标记。这和Windows中的鼠标右键功能相同。
- 点击或者保持触摸一个打开的数字砖块,则将周围的砖块都打开(周围的所有地雷已经插了旗子),这和Windows中的中间键功能相同。
- 没有插旗砖块的图标,用F字母表示旗帜。
- 亲自实现并试玩,反馈你的体验。
总结
用一篇文章解释一个完整的动画游戏不是非常容易。我已经尽力解释了扫雷的工作原理以及如何操作游戏中重要的部分。下边附有游戏的源代码,虽然我们一直使用初级程度的扫雷,但是实现中级和高级的扫雷非常容易,只需要在代码中做少数修改。请提供你使用的反馈和建议。
资源
创建扫雷GUI的图像属于各个作者,图像的资源为:
背景图像:Fractal Blue Abstract Mobile wallpaper
笑脸图像:GNOME Desktop Icon Pack by GNOME icon artists
地雷图像:Farm-Fresh Web Icon Pack by FatCow Web Hosting
LCD字体格式:LCD Mono by Samuel Reynolds
历史
初稿:2010年9月28日
授权
这篇文章及相关的源代码和文件,经过The Code Project Open License(CPOL)协议的授权。
关于作者
The Manoj Kumar
原文链接:http://www.codeproject.com/KB/android/MinesweeperForAndroid.aspx
原作者:The Manoj Kumar
最后
以上就是负责龙猫为你收集整理的Android 扫雷游戏的全部内容,希望文章能够帮你解决Android 扫雷游戏所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复