原生js扫雷游戏
Posted !ment
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生js扫雷游戏相关的知识,希望对你有一定的参考价值。
图片效果如下:完整代码:https://pan.baidu.com/s/15WjcsmuXULciCZrlhiOMoQ 密码:g4my
1.功能:
实现的功能:
1.选择游戏难度
2.右击标记地雷(右击两次可以取消标记)
3.显示剩余雷数
4.自动连锁点开(点击到周围格子都为空时,自动将周围格子显示)
没有实现的功能:
1.没有时间限制
2.开始步入正题
第一步:生成一张地图,也就是td表格
第二步:生成表格里面的雷并且显示到页面(生成不重复的数字,然后将其顺序打乱,最后截取所需雷数)
第四步:点击雷,获取到雷附近的信息(获取以雷为中心,周围九宫格的坐标)
第五步:以雷为中心,将周围九宫格里面的数字实现累加
第六步:设置鼠标点击事件,当点击右键是标记小红旗,左键来判断是否为雷
第七步:点击button按钮,实现不同难度之间的切换
3.首先要生成一张地图,创建一个构造函数Mine,里面存储的是一些一会要用到的变量
function Mine(tr,td,mineNum){
this.tr=tr; //行
this.td=td; //列
this.mineNum=mineNum; //雷的数量
this.squares=[]; //存储所有方块的信息,它是一个二维数组,
this.tds=[]; //存储所有的单元格(二维数组)
this.surplusMine=mineNum; //剩余雷的数量
this.allRight=false; //右击标的小红旗是否全是雷,用来判断游戏是否成功
this.parent=document.querySelector(\'.gameBox\');
}
接下来要在构造函数Mine的原型链上创建一个方法,用来创建表格(生成地图)
Mine.prototype.createDom=function(){ var table=document.createElement(\'table\'); for(var i=0;i<this.tr;i++){ var domTr=document.createElement(\'tr\'); this.tds[i]=[]; for(var j=0;j<this.td;j++){ var domTd=document.createElement(\'td\');//创建td this.tds[i][j]=domTd; //将所有的td存储到tds里面,后面会用到 domTr.appendChild(domTd); //将td添加到tr里面 } table.appendChild(domTr); //将tr添加到表格里面 } this.parent.appendChild(table); //将表格显示在页面 }
4.生成不重复的数字,截取所需要的数字,就是雷
Mine.prototype.randomNum=function(){ var square=new Array(this.tr*this.td); //生成一个空数组,就是生成位置,长度为格子的总数 for(var i=0;i<square.length;i++){ square[i]=i; //生成81个数字,相当于81个索引 } // console.log(square); square.sort(function(){return 0.5 - Math.random()});//将生成的数字打乱 return square.slice(0,this.mineNum); //将生成的81个数字截取为9个数字 }
效果如下:
5.以雷为中心,获取周围九宫格的坐标,用来使雷周围的数字发生改变
Mine.prototype.getAround=function(square){ var x=square.x; var y=square.y; var result=[]; //存储九宫格坐标(二维数组) for(var i=x-1;i<=x+1;i++){ for(var j=y-1;j<=y+1;j++){ if( i<0|| j<0|| i>this.td-1|| j>this.tr-1|| (i==x&&j==y)|| this.squares[j][i].type==\'mine\' ){ continue; //满足上面条件跳出 } result.push([j,i]); //将九宫格里面符合条件的数组添加到result里面 } } return result; //将坐标返回 }
6.将雷周围的数字实现累加,方便玩家判断雷的位置
Mine.prototype.updateNum=function(){ for(var i=0;i<this.tr;i++){ for(var j=0;j<this.td;j++){ if(this.squares[i][j].type==\'number\'){ continue; } var num=this.getAround(this.squares[i][j]); for(var k=0;k<num.length;k++){ // console.log(num); this.squares[num[k][0]][num[k][1]].value+=1;//将每个格子的value值累加 } } }
7.设置鼠标左键右键,当点击左键时,判断点击的是否为雷,如果为0,继续判断周围是否为零,实现连锁效果,右击标小红旗。
Mine.prototype.play=function(ev,obj){
var This=this; //判断是左键还是右键 //obj==this==td if(ev.which==1&&obj.className!=\'flag\'){ //等于1时,为左键并且限制用户标完小红旗后不能左击 //console.log(obj); var curSquare=this.squares[obj.pos[0]][obj.pos[1]]; //获取当前格子的信息;this.pos[0]等于这个格子的pos0的值 var cl=[\'zero\',\'one\',\'two\',\'three\',\'four\',\'five\',\'six\',\'seven\',\'eigth\']; //console.log(cl[3]); //console.log(curSquare); if(curSquare.type==\'number\'){ //区分是雷还是数字 //当用户点击的是数字 obj.innerhtml=curSquare.value; //将数字显示出来 obj.className=cl[curSquare.value]; //改变不同的数字的显示颜色 //还要区分数字是0还是非零,当点到零时,要使周围都显示 if(curSquare.value==0){ //点击的格子是否为零 obj.innerHTML=\'\'; //将为零的显示为空 function getAllZero(square){ //递归函数 var around=This.getAround(square); //获取当前点击的周围格子数组 //console.log(around); for(var i=0;i<around.length;i++){ var x=around[i][0]; var y=around[i][1]; This.tds[x][y].className=cl[This.squares[x][y].value]; if(This.squares[x][y].value==0){ //以某个格子为中心,找到周围格子为零 if(!This.tds[x][y].check){ This.tds[x][y].check=true; getAllZero(This.squares[x][y]); } }else{ //以某个格子为中心,找的周围的格子不为零 This.tds[x][y].innerHTML=This.squares[x][y].value; } } } getAllZero(curSquare); } }else{ //用户点击的是雷 this.gameOver(obj); setTimeout(function(){ alert(\'失败\'); //alert会优先执行,使用定时器,使先显示雷,后弹框 },200); } } if(ev.which==3){ //如果右击的是一个数字,就不能右击 if(obj.className&&obj.className!=\'flag\'){ return; } obj.className=obj.className==\'flag\'?\'\':\'flag\'; //右击两次,使红旗变化 if(this.squares[obj.pos[0]][obj.pos[1]].type==\'mine\'){ this.allRight=true; //用户标的小红旗都是雷 }else{ this.allRight=false; //用户标的其中有一个雷 } if(obj.className==\'flag\'){ this.mineNumDom.innerHTML=--this.surplusMine; }else{ this.mineNumDom.innerHTML=++this.surplusMine; } if(this.surplusMine==0){ //剩余的雷的数量为0,表示用户自己已经标完小红旗,这时候要判断游戏是成功还是结束 if(this.allRight==true){ //表示标的小红旗都是雷 alert(\'恭喜你,游戏通过\'); }else{ alert(\'游戏失败\'); this.gameOver(); //游戏失败就会将所有的雷显示出来 } } } };
Mine.prototype.gameOver=function(clickTd){
for(var i=0;i<this.tr;i++){
for(var j=0;j<this.td;j++){
if(this.squares[i][j].type==\'mine\'){
this.tds[i][j].className=\'mine\'; //显示所有雷
}
this.tds[i][j].onmousedown=null; //取消所有格子的点击事件
}
}
if(clickTd){
clickTd.style.backgroundColor=\'red\'; //给点中的那个雷表上小红色
}
}
}
连锁效果:
8.实现button按钮的不同切换
var btns=document.querySelectorAll(\'.level button\'); var mine=null; //用来存储生成的实例 var ln=0; //用来处理当前显示的状态 var arr=[[9,9,10],[16,16,40],[28,28,99]]; //给button添加事件 for(let i=0;i<btns.length;i++){ if(i<=2){ btns[i].onclick=function(){ btns[ln].className=\'\'; this.className=\'active\'; mine=new Mine(arr[i][0],arr[i][1],arr[i][2]); //console.log(mine); mine.init(); ln=i; } }else{ btns[i].onclick=function(){ mine=new Mine(arr[ln][0],arr[ln][1],arr[ln][2]); mine.init(); } } } btns[0].onclick(); //默认显示9*9方格
以上是关于原生js扫雷游戏的主要内容,如果未能解决你的问题,请参考以下文章