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

这一节我们主要讲解扫雷时鼠标单击的事件。我们首先介绍左键单击的事件,分为两种情况——遇到地雷,游戏结束;不是地雷,自动点开相邻的非地雷区域,并且显示对应地雷区域周围地雷的数目。

我们首先需要为Form_Main添加MouseDown以及MouseUp事件,分别用来监测鼠标按下以及弹起的事件信息。再定义两个全局变量,用来标识鼠标左键以及右键是否被按下,代码如下:

7-1 鼠标变量

在MouseDown事件中输入下面的代码:

7-2 鼠标按下记录

在MouseUp事件中,我们需要获取鼠标弹起前按下的鼠标按键的状态信息,代码如下:

7-3 鼠标弹起

我们首先处理鼠标左键按下的情况,这里分为两种情况,在前文中已经介绍过。但是在处理之前,我们需要获取游戏者单击的是哪个雷区,因此我们需要加入一些用以判断当前鼠标所属区域的代码。但是回顾一下, 我们上一节中在MouseMove事件中已经获得了当前鼠标所属的区域,并且保存在了全局变量中,因此,我们直接调用即可:

7-4 左键单击事件

我们首先来处理非地雷的情况。也就是说我们需要寻找所有相邻的非地雷区域,这里我们才有深度优先搜索(Depth First Search),首先定义一个函数如下:

7-5 dfs

在MouseUp函数中调用,并且刷新绘图区域:

7-6 dfs调用

此时,我们运行程序,单击雷区,与上一节结束时的程序没有什么区别,因为我们还没有更新绘图函数,用下面的代码更新PaintGame函数主循环中的代码:

7-7 PaintGame

此时,我们再次运行程序,单击某个格子,如果不是地雷,那么就可以看到下面的情况:

7-8 阶段性结果

接下来,我们先不处理游戏失败的情况,先来考虑右击事件,它主要用于更改标记,我们在右击函数中加入下面的代码:

7-9 右键事件

同样,我们现在运行程序还是不会有什么效果。我们需要更新PaintGame函数。再次之前,我们需要将我们的图标信息代入到工程中来,在导入之前我们需要将它们大尺寸分别修改为24*24和20*20,以达到更好的显示效果。

在右侧解决方案资源管理器中找到Resources.resx文件,双击打开资源管理界面,将两张图片选中后拖动过去即可完成图片的导入。同时修改PaintGame函数的未点开功能部分如下:

7-10 PaintGame修改

 

此时,我们发现当我们的区域处于红旗或者问号的时候,左击的时候还是会打开该区域,修改左击代码如下:

7-11 左键事件修改

此时,我们以及完成了基本的游戏功能了。接下来我们还需要完成一个鼠标左右键同时按下的事件,代码如下:

7-12 左右键事件

这里,我们缺少一个OpenMine函数,定义如下:

7-13 打开周围雷区

 

此时,如果我们运行程序,很有可能出现下面的情况,有的地方是一个白色的区域,没有任何内容:

7-14 最终结果

出现这种结果,也就意味着出现了地雷,因为我们的PaintGame函数暂时还没有绘制地雷的功能。

细心的读者可能发现了一个问题,地图上有了一面红旗,底下的状态栏中却仍然显示地雷数目为10,我们通过修改右击事件来修复这个问题:

7-15 右击事件

最终,我们会看到这样的效果:

7-16 最终结果

 

我们将在下一节中介绍游戏结束的相关内容。

4 条评论扫雷游戏制作过程(C#描述):第七节、内部实现(续)

  1. 这节的深度优先算法中 private void dfs(int sx, int sy) { pState[sx, sy] = 1;//访问节点 for (int i = 0; i = 1 && x = 1 && y <= nHeight && pMine[x, y] != -1 && pMine[sx, sy] == 0 && (pState[x, y] == 0 || pState[x, y] == 3))//不是地雷,处于地雷区域,且未点开,或者标记为问号 { dfs(x, y); } } }

    px[] py[]在哪定义的

发表评论