网页版扫雷游戏
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
摘要
在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活不可或缺的一部分,越来越多的人使用计算机办公、娱乐、购物等等。
游戏行业发展一日千里,该行业极大的影响和改变了人们的生活和娱乐方式,游戏为消费者提供丰富多彩的虚拟空间,使消费者可以自由自在的享受虚拟世界的乐趣,实现自己在现实生活着那个可能永远不能实现的梦想,满足了消费者的心理和精神需求。
扫雷游戏是Windows操作系统自带的一款小游戏,在过去的几年里,Windows 操作系统历经数次换代更新,变得越来越庞大、复杂,功能也越来越强大,但是这款小游戏依然保持原来的容貌,可见这款小游戏受到越来越多人的喜爱。
扫雷游戏是比较经典的一款小游戏,实现它的方法很多,可以用很多不同算法设计和语言实现,如C++, JAVA等。
我这里用的是javascript编写了与它功能相似的扫雷游戏,寓学于乐。
程序的功能是随机生成地雷数,通过鼠标操作玩游戏,不接受键盘,按任意键结束程序。
单击屏幕上的笑脸可以重新开始游戏。
当鼠标左键单击到地雷时提示游戏失败。
其功能类似于Windows操作系统自带的扫雷游戏。
报告首先介绍了进行该游戏课程设计的目的,然后是任务描述和设计的相关要求,最后是最重要的需求分析和设计方案。
重点介绍了在游戏过程中各事件的处理,其中又以鼠标事件和清除未靠近地雷区方块这两方面最为最要,鼠标事件是利用鼠标所发出的信息了解用户的意图,进而做出相对应的动作。
清除未靠近地雷区的方块较为复杂。
关键词:扫雷游戏;算法设计;事件;javascript
目录
摘要 (1)
第一章课程设计目的 (3)
第二章课程设计描述和要求 (4)
2.1 任务描述 (4)
2.2 设计要求 (5)
第二章需求分析 (5)
3.1功能描述 (6)
3.2功能需求 (6)
3.3 功能模块 (7)
3.4系统需求分析总结........................................................ 错误!未定义书签。
第四章设计方案.. (7)
4.1 总体设计 (7)
4.2 详细设计 (9)
第五章心得体会 (18)
参考资料 (19)
第一章课程设计目的
本课程设计是计算机科学与技术专业重要的实践性环节之一,是对本课程学习后进行的一次全面而综合的练习。
本次课程设计的目的主要有:(1)让学生掌握较为简单的算法分析能力;
(2)更深入地理解和掌握该课程中的有关基本概念,程序设计思想和方法。
(3)对掌握知识的深度、运用理论去处理问题的能力、实验能力、课程设计能力进行考核。
(4)培养综合运用所学知识独立完成课题的能力。
(5)掌握程序设计说明文档的能力与技巧;
第二章课程设计描述和要求
2.1 任务描述
随着人们工作压力变得越来越大,现如今更多的人开始通过玩游戏来排解内心的压力,而各种各样的游戏也排入市场,一些大型网络游戏更是一些年轻用户的最爱,所有扫雷游戏面对市场的竞争压力还是非常大的。
分析Windows系统自带的扫雷游戏,查找规则并对主要功能进行模仿程序实现,对于实现过程中出现的bug进行调试解决。
经过对游戏的初步分析,扫雷游戏含有如下规则:
根据输入的信息,执行相应的挖雷,插旗,自动蔓延开挖等。
挖雷过程由计时器计时,由一个计数器统计插旗后雷的剩余个数。
如果选择了标记功能,那么单击右键会依次对未知点进行插旗,标记,取消插旗与标记。
如果点击到了未插旗子的雷区,如果是雷,则判定游戏失败,之后对雷区的点击进行屏蔽,不予响应。
如果是疑问标记则像正常区域对待。
如何判断胜利,如果所有的雷都被插旗或者点击后剩余的雷区。
具体任务如下:
(1)需要为Windows操作系统的用户设计完成一款扫雷游戏,这是一个根据某种算法自动布雷,有用户扫雷的简单网页游戏;
(2)本游戏在难度设置上,分为低、中、高三个难度等级,三个等级的雷数不同;
(3)本游戏由每个学生单独完成,完成时间大概7周时间,开发成本低,易于完成;
(4)设计过程中,前两周,对整个游戏所实现的功能进行详细的设计以及对存在的问题及解决办法进行最终确定;3-5周完成游戏的程序编写,并优化;最后两周,写出设计本游戏的详细文档说明,并作课程设计汇报。
整个扫雷游戏课程设计实现流程图如图2-1所示:
图2-1 课程实现流程图
图2-1清晰明了的描述了整个课程设计的实现流程。
前期工作是制定规则和设计算法,这一阶段主要任务是搜集相关资料,然后根据搜集到的资料结合自己所学知识制定系统实现算法;中期工作是算法实现和调试系统,这一阶段主要任务是完成算法的实现,然后进行调试和优化系统;后期工作是对数据结果进行分析,然后完成课程设计报告。
2.2 设计要求
(1)系统需求分析,对系统的各种功能需要进行总结;
(2)理解扫雷玩法的特点,并分析玩法的实现功能
(3)设计雷区和非雷区的判断算法。
(4)进行概念设计和逻辑结构设计,以便使系统实现进展顺利;
(5)模块化程序设计;
(6)进行详细的设计方案,包括总体设计和详细设计,这包括程序设计代码的分析和系统运行界面截图的分析;
(7)要求人机交互性较强;
第二章需求分析
需求分析的主要任务即详细的找出程序所需要的各种功能实现,是对系统功
能进一步分析和抽象,以确定系统应当做什么的问题,从而完成系统的逻辑设计。
本程序为扫雷游戏的实现,首先是要实现扫雷游戏的基本功能,根据扫雷游戏的玩法,设计程序,实现程序功能。
本系统需求分析分为四个部分:功能描述、功能需求、功能模块和系统需求分析报告。
3.1功能描述
按功能将游戏区域分成两个区域:雷区和提示区。
提示区包括计雷器、计时器和一个笑脸的按键操作。
游戏过程中,当用户用鼠标点击相应的方块,程序就会作出相应的鼠标事件,而鼠标事件的处理都是由扫雷程序实现的。
游戏开始时,系统会在雷区的某些小方块中随机布下若干个地雷。
安放地雷的方块称为雷方块,其他的称为非雷方块。
布完雷后,系统会在其他非雷方块中填充一些数字。
某一个具体数字表示与其紧邻的8个方块中有多少个雷。
用户可以根据这些数字判断是否可以打开某些方块,并把认为有地雷的方块标识地图。
如果某个数字方块周围的地雷全都标记完,可以单击鼠标左键,将其周围剩下的方块挖开。
如果数字周围地雷没有全部标记,在同时单击鼠标左右键时,其他隐藏或未标记的方块将被按下一次。
当用户将所有地雷挖出后,其余的非雷方块区域都已打开,此时游戏胜利。
在游戏过程中,一旦错误地打开了雷方块则游戏失败,游戏结束;当用户标识的地雷数超过程序设定,虽然打开了全部其余方块,游戏仍然不会结束。
3.2功能需求
(1)提示区右侧显示总雷数,并减去被标明有雷区域的数目;
(2)提示区中间位置显示笑脸按钮用于开局和显示鼠标动作的结果;
(3)提示区左侧则显示扫雷所用的时间;
(4)单击鼠标左键于未知区域,如果未知区域有雷,游戏结束,显示所有的地雷;如果没有雷,则显示周围雷数,如果周围没雷,则再查看周围八个区域是否有雷直到有雷为止,并显示周围雷的数目;
(5)单击鼠标右键于未知区域,则显示小红旗,将其标识有雷。
在该位置再次单击右键则取消设置,旗帜消失;
(6)如果该数字方块周围地雷已经完全标识出,双击该数字所在方块,将快速翻开所有周围不是地雷的方块,并显示,直到有雷为止;
(7)将雷全部扫完后,会出现一个提示框,显示游戏胜利。
3.3 功能模块
(1)游戏界面
(2)布雷
(3)鼠标事件
(4)游戏胜利(结束)
(5)游戏失败(结束)
(6)游戏设置(难度)
扫雷游戏系统基本功能如图3-1所示
图3-1是整个扫雷游戏的系统基本功能图,从图中可以看出系统分为四大功能模块,即游戏开始、游戏选关、游戏计雷、游戏计时。
第四章设计方案
4.1 总体设计
4.1.1 界面设计
界面采用网页技术实现,通过div+css来呈现,分为控制区(上)和游戏区(下)。
控制区左边是游戏时间,从点开第一个按钮开始计时;中间是复位按钮;右边是旗帜的个数,它和雷的个数是相等的,但旗帜的个数会随着玩家的使用而变化。
游戏区就是对应等级的规格按钮。
效果图看详细设计。
4.1.2 功能设计
实现功能包括:布局格子,布雷,判断游戏完成或失败,鼠标事件(左键单击、右键单击、左右键同时按下、左键按下拖动、左右键同时按下拖动),游戏难度转换,重新开始。
另外,本游戏还包含了一些细微的处理,比如屏蔽了右键菜单,屏蔽了鼠标选择,玩家第一步不会踩雷等设计。
在这些功能中,鼠标的事件为本游戏的实现关键,所以这段算法也是整个程序的核心,其中鼠标的左右键同时按下和松开以及按下拖动的事件是实现的难点。
4.1.3 游戏流程设计
打开网页后,游戏进入初始化阶段,默认为游戏等级为初级,初始化阶段首先是根据游戏等级初始化雷个数,游戏范围,然后初始化数组,接着初始化计时器、游戏状态、旗帜数,再接着清空面板,重新生成格子,初始化格子样式,给每个按钮绑定鼠标单击事件。
当鼠标第一次用左键点击游戏区域中的按钮时,获取该按钮坐标出入布雷方法中,随机生成雷时回避该坐标(避免第一次点到雷),并且生成提示数值存于借助的二维数组中。
以后每次点击都会和二维数组里面的值来匹配。
游戏详细运行流程如图4-1所示
图4-1 运行流程图
图4-1是游戏详细的运行流程图,图中清晰地描述了系统的执行过程,即根据不同的事件,游戏状态的转换。
过程为:游戏开始,等待事件,发出鼠标事件,根据用户发出的命令,判断是左键命令还是右键命令,若是右键命令则是标出地图,若是左键命令则是调用扫雷的相关逻辑算法,进行下一部操作;如果点到雷,则游戏结束,调用菜单事件,重新开局;如果没有点到雷,则继续判断,直到点完数字,则游戏胜利,调用菜单事件,重新开局。
4.2 详细设计
4.2.1 界面设计
初始界面如图4-2所示
游戏中界面如图4-3所示
游戏失败界面如图4-4所示
游戏成功界面如图4-5所示
图4-5 游戏成功界面
4.2.2 功能实现
布局格子
游戏分为三个等级,分别为初级、中级、高级。
初级规格为:9*9, 10个雷;中级规格为:16*16, 40个雷;高级规格为:16*30, 70个雷;在放置格子的同时为该格子绑定鼠标单击事件以及样式。
游戏根据玩家选择不同的游戏等级会自动生成对应格子以及雷。
先创建一个表格,再创建行,创建单元格,再创建按钮,然后反序一级一级加入。
使用表格的目的是为了方便布局以及调整样式。
核心代码如下:
var tr, td, btn;
var table = document.createElement( "TABLE" );
table.id = "table";
var tbody = document.createElement( "TBODY" );
for( var i=0;i<currentX;i++ ){
tr = document.createElement( "TR" );
for( var j=0;j<currentY;j++ ){
td = document.createElement( "TD" );
btn = document.createElement( "BUTTON" );
btn.innerText = " ";
btn.className = "initBtn";
btn.onmousedown = mouseDwon;
btn.onmouseup = mouseUp;
btn.onmouseover = mouseMoveIn;
btn.onmouseout = mouseMoveOut;
td.appendChild( btn );
tr.appendChild( td );
}
//添加到表格
tbody.appendChild( tr );
}
table.appendChild( tbody );
gamePanel.appendChild( table );
布雷
随机生成雷的位置,以前的做法是将是雷的按钮的value属性值赋为9,后来发现不同的浏览器执行效果不一样,有些浏览器一打开不操作会直接显示其值,这样就没得玩了,我编写的时候用的是ie8不会直接显示出来。
现在的做法做法是借助一个二维数组来设计,随机生成对应的9,记录在数组里,玩的时候单击格子获得该格子对应的坐标,然后再到数组里判断其对应的值是不是9,这样只有在操作之后才会显示该值。
根据不同游戏等级随机放置对应的雷数。
关于第一次点击不会中雷的设计:用一个变量记录是否是第一次点击,每次初始化的时候该变量都会设置为true,第一次点击之后设置为false并获取到该格子的坐标传入布雷方法,在布雷的方法里布雷时避开这一坐标。
核心代码如下:var x, y, i=0;
while( i<mineCount ){
x = Math.round(Math.random() * currentX );
y = Math.round(Math.random() * currentY );
if( x==h && y==k ){} //回避第一次点击
else if( judgeCoord(x,y) && temp[x][y] != 9 ){
temp[x][y] = 9;
i++;
}
}
设置提示数字
根据当前格子周围八个方向雷的个数来设置当前格子对应二维数组的的数值,如果周围的8个格子有3个雷,则该格子对应的二维数组坐标的值为3;如果当前格子为雷,则该坐标的值为9。
核心代码如下:
for( var i=0; i<currentX; i++ )
for( var j=0; j<currentY; j++ ){
n = 0;
if( temp[i][j] != 9 ){
//周围8个格子
for( var p = i>=1?i-1:0; p<(i+2<currentX?i+2:currentX); p++ ) for( var q= j>=1?j-1:0; q<(j+2<currentY?j+2:currentY); q++ )
{
if( judgeCoord( p,q ) &&(temp[p][q] ==9) ) n++;
}
temp[i][j] = n;
}
}
游戏成功
判断游戏是否成功是在没猜到地雷的情况下判断剩余未打开格子的个数,如果与当前游戏等级所持有的雷数想同,则说明游戏完成,游戏会给出成功提示,并自动进入下一局,每次左键点击以及左右键同时按下避雷触发鼠标对应事件后都会进行判断。
游戏失败
踩到雷就表明游戏失败,也就说你当前打开的格子对应的二维数组中的值是9,游戏失败,根据二维数组中9的坐标转换成一维下标,在游戏面板中根据该下标显示所有雷。
游戏会给出相应提示,并自动进入新的一局。
鼠标事件
使用event.button可以判断出玩家在按钮上点击了哪个鼠标键,从而进行对应的行为,0表示未按下任何键;1表示左键;2表示右键;3表示左右键同时按下。
这里主要利用后三种指标进行鼠标的各种判断。
鼠标事件之左键单击
左键单击的功能是打开格子,如果打开的是雷则游戏失败;如果是数值格子则显示该格子;如果是空白格子则显示该格子并判断周围八个方向的的格子,如果周围的格子还有空白格子则继续递归判断,如果是数值格子,则打开,是雷的和插上旗帜的都不会打开。
核心代码如下:
if( temp[x][y] == 9 ){ //踩到雷
mineClick();
return;
}else if( btn.className == "initBtn"||btn.className == "tempBtn" ){ //
if( temp[x][y] == 0 ){ //空白键
btn.innerText = " ";
spaceBtn( x, y );
}else{
openBtn( x,y );
}
鼠标事件之右键单击
右键单击的功能是插旗和取消插旗,该功能只作用在未打开的格子上,如果格子未插旗则插上旗帜,反之取消。
旗帜的数量与雷的数量一样,每插一个旗帜,旗帜的数量就会减1,当旗帜的数量等于0时,要先取消之前的插的旗才能进行插旗操作。
主要代码如下:
if( cName == "remindBtn" ){
flag++;
btn.className = "initBtn";
}else{
if( flag>0 ){
if( cName!="openBtn" ){
btn.className = "remindBtn";
flag--;
}
}else{
alert( "标志已用完" );
}}
鼠标事件之左右键同时单击
左右键同时单击的功能是显示所点击格子周围的8个格子,在进行显示之前先判断一下周围是否有旗帜,如果格子的坐标对应的二维数组中的值为1并且周围插了1个以上的旗帜,会直接打开,不论该旗帜是否插在了地雷上,如果打开的格子中有一个雷,那么游戏结束;如果格子的坐标对应的二维数组中的值不为1,则会判断周围的雷是否都被插上了旗帜,如果是则打开其他格子,如果有1个或者1个以上的雷未插上旗帜,则不显示。
核心代码如下:
//下标符合规范,未插上旗帜,为未翻开状态
if (!judgeClass(i, j))
{
for( var p = i>=1?i-1:0; p<(i+2<currentX?i+2:currentX); p++ ) for( var q= j>=1?j-1:0; q<(j+2<currentY?j+2:currentY); q++ )
{
if (!(p==i&&q==j) && judgeRemind(p, q) && judgeClass(p, q) ) pressBc(p, q);
}
}
鼠标事件之左键按住拖动以及左右键同时按住拖动
该功能其实就是记录下用户最后是在哪个按钮上面松开的鼠标的,从而把这个按钮作为事件的触发源进行操作。
但这里有一个漏洞,如果按住鼠标离开了游戏区,并且在外面松开了鼠标,那么再次进入的时候尽管鼠标没按住,游戏也
会把鼠标移动当成是按住鼠标移动的操作,针对这一问题目前我想到了两种解决办法,第一种是划定游戏区域从而界定鼠标按住拖动的效果区域,第二种是给窗体添加鼠标的松开和按下事件,不管鼠标在哪按下,只要松开,两个记录变量就会被初始化,再次进入游戏区域时鼠标是初始化状态。
这里采用的是第二种。
4.2.3 关于本游戏的不足
A、在鼠标移动的处理上,功能虽然实现了,但是双键按下拖动的时候不能拖动太快,否则有些格子不能复原,我想应该是这个程序的性能设计问题,暂时没了解到其他原因,至于程序的性能,还在慢慢的修善中。
B、相对于Windows做的扫雷还有些功能没实现,比如英雄榜,问号等。
最近我发现微软一个很人性化的设计,就是窗口最小化时,游戏不会计时,窗口在打开的时候又会继续计时,等等一些人性化的设计我还在进一步改进中。
C、关于坐标的问题。
点击一个格子后,会获得该格子的坐标,初级的没问题,但是中级和高级的时候会出现一个问题,虽然现在解决了,但我没明白是什么原因造成的现象。
得出的下标缺了12和26,到了12就会从11直接跳到13, 26也是。
注:目前只发现了这些,如老师或同学发现其他不足还望批评指正。
第五章心得体会
刚开始老师说课程设计要写扫雷的时候,说实话那时候我还没玩过扫雷,windows自带的这些游戏我就玩过几次蜘蛛纸牌和弹珠。
回宿舍后赶紧把扫雷玩了下,向同学了解了下扫雷游戏的基本规则,以及这些操作所要使用哪些算法来实现。
因为大家都是用MFC或C#来做的,所以我想做个网页版的,刚好可以复习巩固一下之前学习的网页知识。
页面和布局用的是css+div,功能是用javascript实现的。
实现扫雷的难点在于鼠标事件的实现,包括左键单击,右键单击,左右键同时按下与弹起,左键按住拖动,左右键按住拖动,其中后面的四个事件相对来说难度高一些,在编写的过程中,遇到问题和老师以及同学探讨,百度也是一个非常好的帮手。
虽然大家实现这个游戏的语言不同,但是实现的核心算法都差不多,所以交流起来也没啥隔阂。
其他的一些功能比如判放格子、布雷、计算提示数、断游戏失败或成功、计时、插旗、游戏等级设置等,这些功能都还好,实现不怎么难,大部分时间都花在了鼠标的事件上,尤其是左右键同时控制那块。
现在,虽然扫雷的基本功能我都实现了,但是写的算法还不是那么精简,代码也不是那么高质量,不过我在慢慢的改进,实现代码的高质量化。
通过这次课程设计,我更加熟练了对javascript以及css的操作。
最后说一些比较官方的话:感谢老师的指导,感谢同学的帮助,感谢自己的努力,哈哈。
参考资料
1、王晓东. 《计算机算法设计与分析》(第3版). 北京. 电子工业出版社
2、杨树林胡洁萍. 《java语言最新实用案例》第二版. 北京. 清华大学出版社
3、马士兵. 《尚学堂javaweb系列教程》. 北京. 尚学堂
4、谭浩强《c程序设计》(第三版). 北京. 清华大学出版社。