js实现扫雷小程序的示例代码
初学javascript,写了一个扫雷程序练练手!
扫雷规则及功能
扫雷想必大家都不陌生,就是windows上点击排雷的小游戏,它的主要规则有
1.左键点击显示当前格子是否为雷,如果为雷的话,GameOver啦,如果不是雷的话,这个格子会显示周围八个格子内的雷数量。
2.鼠标右键标记,标记可能的雷,标记了之后取消需要再次右键点击该格子,左键无效果。
3.鼠标中键(滚轮)按下后,快捷扫雷(如果周围雷数和未被标记且未被翻开的格子相等,会将这些格子一并翻开)
主要功能基本完全复刻了windows7扫雷的功能
扫雷github地址:扫雷github地址
扫雷算法
1.首先我定义了一个构造函数,里面是一系列的属性:
varmineCraft=function(num1,num2,mine_num,obj,type){ this.num1=num1;//整个扫雷的行数 this.num2=num2;//整个扫雷的列数 this.mine_num=mine_num;//雷的个数 this.tiles=[];//数组里面存放的是每个小格子 this.obj=obj;//扫雷放置的对象 this.flag=true; this.arr=[]; this.arr_2=[]; this.time_dsq=null; this.time_dc=''; this.time_arr=[[],[],[]];//时间统计信息 this.details=[[],[],[]];//游戏统计详情 this.type=type;//游戏类型:初级/中级/高级/自定义 this.buildTiles();//创建游戏函数 };
2.在页面上创建扫雷的界面函数buildTiles
buildTiles:function(){ this.obj.style.width=51*this.num1+'px';//在传进来的对象上画整体格子,每个小格子51px大小,总大小就为个数*单个大小 this.obj.style.height=51*this.num2+'px'; varindexOfdiv=0; for(vari=0;i3.绑事件函数:
event:function(){ var_this=this; this.obj.onmouseover=function(e){//鼠标悬停事件--- if(e.target.className=='tile'){ e.target.className='tilecurrent'; } } this.obj.onmouseout=function(e){//鼠标移出事件-- if(e.target.className=='tilecurrent'){ e.target.className='tile'; } } this.obj.onmousedown=function(e){//鼠标按下事件 varindex=e.target.index; if(e.button==1){//e.button属性左键0/中键1/右键2 event.preventDefault();//取消默认 } _this.changeStyle(e.button,e.target,index); } this.obj.onmouseup=function(e){//鼠标弹起事件 if(e.button==1){ _this.changeStyle(3,e.target); } } },4.点击调用的函数:
changeStyle:function(num1,obj,num_index){ if(num1==0){//是左键的话 if(this.flag){//this.flag是之前定义的用于判断是否为第一次点击 this.store(num_index);//store函数,存放被点击的格子周围的8个格子 this.setMineCraft(this.mine_num,this.arr,num_index);//如果是第一次点击即调用布雷函数更改flag状态 this.flag=false; this.detail_statistics(0,false);//开始信息统计函数 } if(obj.className!='tile'&&obj.className!='tilecurrent'){//如果不是第一次点击,被点击的格子不是未点击状态,无效 returnfalse; } if(obj.getAttribute('val')==0){//如果不是雷。改为翻开状态 obj.className="showed"; obj.innerHTML=obj.getAttribute('value')==0?'':obj.getAttribute('value');//显示周围雷数 this.showAll(obj.index);//递归函数判断周围格子的情况,就是扫雷游戏上一点开会出现一片的那种 } if(this.over(obj)){//判断游戏是否结束 this.last(); } } if(num1==2){//右键标记事件 if(obj.className=='biaoji'){ obj.className='tile'; }elseif(obj.className!='biaoji'&&obj.className!='showed'){ obj.className='biaoji'; } } if(num1==1){//中键事件 if(obj.className=="showed"){ this.show_zj1(obj.index); } } if(num1==3){//鼠标弹起事件 if(obj.className=="showed"){ varflag1=this.show_zj2(obj.index,0); }else{ this.show_zj2(obj.index,1) returnfalse; } if(flag1&&this.over()){//弹起判断是否结束 this.last(); } } },5.布雷:我之前的布雷是在页面加载在buildTiles()的时候布雷的,但是这样会导致有可能你电机的第一个格子就是雷(游戏性不强),后来修改到第一次点击完成之后布雷(确保第一下点的不是雷),避开直接炸死的现象.所以把调用放在后面的event后触发的changeStyle函数中
setMineCraft:function(num,arr_first,num_first){//雷的个数、最开始被点击的格子周围的八个、被点击的那个格子 vararr_index=[]; for(vari=0;i-1){//如果是属于第一次点击的周围的直接跳过在该位置布雷 num++; continue; } if(this.tiles[index_Mine].getAttribute("val")==0){ this.tiles[index_Mine].setAttribute("val",1); }else{ num++; } } this.showValue(); this.event() }, 6.存储周围格子的函数:
store:function(num){//传入格子的index. vartiles_2d=[]; varindexs=0; for(vari=0;i=0&&j-1>=0){ this.arr.push(tiles_2d[i-1][j-1]); } //正上 if(i-1>=0){ this.arr.push(tiles_2d[i-1][j]); } //右上 if(i-1>=0&&j+1<=this.num1-1){ this.arr.push(tiles_2d[i-1][j+1]); } //左边 if(j-1>=0){ this.arr.push(tiles_2d[i][j-1]); } //右边 if(j+1<=this.num1-1){ this.arr.push(tiles_2d[i][j+1]); } //左下 if(i+1<=this.num2-1&&j-1>=0){ this.arr.push(tiles_2d[i+1][j-1]); } //正下 if(i+1<=this.num2-1){ this.arr.push(tiles_2d[i+1][j]); } //右下 if(i+1<=this.num2-1&&j+1<=this.num1-1){ this.arr.push(tiles_2d[i+1][j+1]); } }, 7.showAll函数:作用是如果该格子周围没有雷,自动翻开周围8个格子,然后再判断周围八个格子的周围8隔格子是否有雷,利用了递归的方法
showAll:function(num){ if(this.tiles[num].className=="showed"&&this.tiles[num].getAttribute("value")==0){ this.store(this.tiles[num].index); vararr2=newArray(); arr2=this.arr; for(vari=0;i8.show_zj函数:主要是中键按钮的作用中键点击后的函数,这里的show_zj1是鼠标键按下后的显示效果,
show_zj2函数就是
show_zj1:function(num){ this.store(this.tiles[num].index); for(vari=0;i9.结束判断:
over:function(obj){ varflag=false; varshowed=document.getElementsByClassName('showed'); varnum=this.tiles.length-this.mine_num; if(showed.length==num){//如果被排出来的格子数等于总格子数-雷数,这游戏成功结束 this.detail_statistics(1,true);//游戏统计,true代表胜,false,代表失败 alert('恭喜你获得成功'); flag=true; }elseif(obj&&obj.getAttribute('val')==1){//如果被点击的是雷,则炸死 this.detail_statistics(1,false); alert('被炸死!'); flag=true; } returnflag; },10.结束后的显示函数:
last:function(){ varlen=this.tiles.length; for(vari=0;i11统计信息:还是比较全的和windows7扫雷版的判断项目是一样的,使用的是每次结束游戏后将数据存入localStorage中,
//已玩游戏,已胜游戏,胜率,最多连胜,最多连败,当前连局; detail_statistics:function(num,zt){ vartime_pay=1; var_this=this; if(num==0){ this.time_dsq=setInterval(function(){ $('#time_need').text(time_pay); _this.time_dc=time_pay; time_pay++; },1000); } elseif(num==1){ clearInterval(this.time_dsq); if(this.type==4){returnfalse;} if(localStorage.details==undefined){ localStorage.details=JSON.stringify([[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]]);//这里存放的就是上面注释中的六项数据 } if(JSON.parse(localStorage.details)instanceofArray){ this.details=JSON.parse(localStorage.details); } this.details[this.type][0]+=1; if(zt==false){ if(this.details[this.type][5]>=0){ this.details[this.type][5]=-1; }else{ this.details[this.type][5]-=1; } if(this.details[this.type][5]=0){ this.details[this.type][5]+=1; }else{ this.details[this.type][5]=1; } if(this.details[this.type][5]>this.details[this.type][3]){ this.details[this.type][3]=this.details[this.type][5]; } this.details[this.type][3]+=1; this.details[this.type][2]=this.toPercent(this.details[this.type][4]/this.details[this.type][0]); localStorage.details=JSON.stringify(this.details); vartime1=newDate(); vartime_str=time1.getFullYear()+'/'+time1.getMonth()+'/'+time1.getDate()+''+time1.getHours()+':'+time1.getMinutes(); if(localStorage.time==undefined){ localStorage.time=JSON.stringify([[],[],[]]); } if(JSON.parse(localStorage.time)instanceofArray){ this.time_arr=JSON.parse(localStorage.time); } this.time_arr[this.type].push([this.time_dc,time_str]); this.time_arr[this.type].sort(function(a,b){ returna[0]-b[0]; }); if(this.time_arr[this.type].length>5){ this.time_arr[this.type].pop(); } localStorage.time=JSON.stringify(this.time_arr); } }, 扫雷的主要部分就是这些了,还有一些小功能包括没写来,要看完整的可以看gitHub
之前看书学习总觉得学了就忘,感觉懂了公式却不知道怎么用,写完扫雷小程序觉得收获了很多
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。