扫雷游戏制作过程(C#描述):第六节、内部实现

在进行内部实现之前,我们先来考虑一下扫雷的内部逻辑。首先,我们需要保存每个点上是否有地雷,如果没有地雷,那么要显示与它紧邻的八个格子中一共有多少的地雷。还需保存每个雷区的状态(点开,未点开,红旗,问号)。我们考虑定义两个常量,表示地雷的最大范围:

6-1 常量定义

接下来定义两个数组,用来保存上述两种数据。对于第一类数据,我们使用-1表示该区域有地雷,使用数字表示与它紧邻的八个格子中一共有多少地雷;对于第二类数据,我们使用0表示未点开,1表示点开,2表示红旗,3表示问号。如下图所示:

6-2 数组定义

接下来我们需要初始化游戏数据,双击New Game菜单,输入游戏的初始化代码:

6-3 初始化游戏

其中涉及到了dx以及dy这两个偏移量常量数组的定义,如下图所示:

6-4 偏移量数组

接下来我我们来实现一些特效,例如高亮当前鼠标悬浮位置的雷区,打开设计窗口,添加MouseMove事件:

6-5 MouseMove

为此,我们还需要定义一个变量MouseFocus来记录当前的高亮点,代码分别如下:

6-6 Point

同时,我们需要在初始化的时候对它进行清零操作,将下面的清零代码加入到刚才的初始化函数中:

6-7 重置高亮点

接下来我们需要修改PaintGame函数,添加对高亮点的绘制:

6-8 PaintGame此时,我们可以尝试运行,然而却发现界面会一直在闪,使得游戏体验急剧下降,为了修复这个问题,我们只需要在构造函数中添加一句代码,开启双缓冲即可,代码如下:

6-9 开启双缓冲

然而我们发现效果并没有很大的提升,这是由于我们之前定义的PaintGame函数所导致的,它不断的定义新的Graphics实例,使得这个过程变得很慢,我们可以直接使用Paint事件中的Graphics实例。首先修改PaintGame函数的定义以及部分实现,如下图所示:

6-10 PaintGame定义

同时修改Paint事件中的调用函数:

6-11 Paint事件

对于其它非Paint函数调用的PaintGame函数,一律修改为this.Refresh();即可,如下图所示:

6-12 PaintGame修改

6-13 PaintGame修改

再次运行的时候,我们发现已经没有了之前的闪屏问题了。然而我们却发现了新的问题,对于当前移动到的位置坐标获取不准确,我们进行下面的调整:

6-14 MouseMove修改

 

此时,我们运行程序的时候,就会发现界面基本已经完成了。

接下来我们需要为Setting菜单添加一个单击确定按钮以后就自动开始游戏的功能,为此我们只需要修改UpdateSize函数,代码如下:

6-15 UpdateSize修改

接下来我们需要修改一下显示地雷数目以及计时的标签,在新建游戏的函数中修改如下:

6-16 标签显示

运行后,我们发现计时器并没有显示出来,因为我们还没有为计时器摄制事件。在设计窗口页面中双击计时器,程序自动创建计时器事件,输入下面的代码:

6-17 Timer事件同时记得在设计页面中将记时器的Interval属性设置为1000,表示每秒执行一次计时器事件代码。

最后,我们运行程序,效果如下:

6-18 最终结果

下一讲将会涉及具体的鼠标单击以及右击雷区时的逻辑事件的判定。

 

发表评论