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;i
3.绑事件函数:
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;i
8.show_zj函数:主要是中键按钮的作用中键点击后的函数,这里的show_zj1是鼠标键按下后的显示效果,
show_zj2函数就是
show_zj1:function(num){
this.store(this.tiles[num].index);
for(vari=0;i
9.结束判断:
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;i
11统计信息:还是比较全的和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
之前看书学习总觉得学了就忘,感觉懂了公式却不知道怎么用,写完扫雷小程序觉得收获了很多
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。