Let’s Rock! 第一季-用ASP.NET扫雷!(3)
Hello,我是Snake,欢迎阅读我的文章--Let’s Rock! 第一季-用ASP.NET扫雷!(3)
上回讲述了Rule这个最重要类的一部分关于游戏初始化的方法.而之前给出的Click方法中可以看出在鼠标左键或右键双击时会执行2个方法,分别为dig(挖)和flag(标记).那么我们开来看看这两个方法里有什么乾坤.
Dig(Block b)
我们获取到我们鼠标单击时的坐标,我们可以判断出我们点击了哪一个块.经过Click方法的分析呢,将这个获取到的块传递到Dig方法中.这时我们就得开始考虑b的一切可能性.如果b.IsMine==true的话,意味着我们的游戏就结束了.所以我们在判断完b.IsMine是否为true之后将执行一个GameOver方法.如果b.IsFlag的属性为true的话,我们将不做任何事情,直接return.余下就是判断它的b.IsDig的属性是否为true,如果为true,执行一段最容易出错的代码,如果为false,将它的IsDig属性设置为true,就代表这个块被挖开了,并且没被雷给炸到.
那么上面所说的那段最容易出错的代码是什么呢?
我们接下来思考一下我们点开一个已经翻开的块时,游戏要怎么做才让我们满意?—显然是展开它周围8个块中尚未翻开的的那一部分.
通常懂得玩扫雷游戏的玩家都知道当我们确定这个已翻开的块的周围没有雷的情况下我们才会点击它,并且命令它展开,那么此时有2种情况:
- 当前块标记的是周围有X个雷,但玩家并未给它标记慢X个旗--此时游戏应该丢弃玩家这次点击的请求,以示警告.
- 玩家给当前块标记满了X个或X个以上的旗子—此时游戏将会听话地将其周围的块都展开,无论玩家是否标记错误.如果标记错误,不好意思,Game Over.至于多标记的块,我们就当作一个隐患埋在游戏当中,并不挖开(也不能挖开,Dig方法碰到已经被标记的块会跳出方法块,什么事也不干的)谁叫玩家自己不小心的.
好了.现在我们健壮的Block类终于有用武之地啦!具体就不再多说,相信您已经被我给绕晕了.
没关系,代码来啦.
private static void Dig(Block b)
{
if (b.IsFlag)
{
return;
}
if (b.IsDig)
{
if (b.MineSurround == 0)
{
foreach (var ob in b.Surrounds)
{
if (!ob.IsDig) Dig(ob);
}
}
else
{
if (b.FlagSurround >= b.MineSurround)
{
foreach (var ob in b.Surrounds)
{
if (!ob.IsDig) Dig(ob);
}
}
}
}
else if (!b.IsDig && b.IsMine)
{
Runtime.GameOver(false);
}
else
{
b.IsDig = true;
if (b.MineSurround == 0)
Dig(b, true);
}
CheckAfterDig();
}
大家可以看到当判断b.IsDig的时候,我们的代码先判断了b周围的雷的个数,如果周围雷的个数为0,游戏将自动帮我们展开它周围的所有未展开项.而展开的方法还是Dig,也就是说游戏将进入一个Dig方法的循环当中.所以我们应当避免Dig方法永远的挖下去,再挖就内存溢出了(显然控制这段代码不进入死循环有点困难,我尝试了好多次,最终以最完美的姿态展示给大家.)!如果b周围雷的个数超过0个,那么游戏将不展开所有的项,那么方法执行到这里也就停了,也就控制了它进入死循环.
Flag(Block b)
标记的语法就没什么好说的代码也非常简单,不具备什么逻辑性.
private static void Flag(Block b)
{
if (!b.IsDig && !b.IsFlag)
{
b.IsFlag = true;
Runtime.GameInfo.Flags++;
}
else if (!b.IsDig && b.IsFlag)
{
b.IsFlag = false;
Runtime.GameInfo.Flags--;
}
}
好了,最近的时间不多,所以每一章节放的内容也不多,4月份就会更加的忙,希望我能忙中偷闲,写下一篇新的博文
