学习扫雷笔记,学习资料:渡一教育实现扫雷视频,基本上所有都是原生js的,部分bug不知为何就是用js就实现不了,然后无奈之下尝试了jQuery结果可以,如果解决了bug再改,用了jq的地方会标注即写上js写法,大致实现效果如下
先说不足,由于自己本身也没有解决,在实现点击雷后会将全部雷显示出来,并且alert一个lose,但是只有alert先确定结束后全部雷才会显示出来,之后会继续尝试改进。
HTML部分,因为是学习+练习就只写了基础功能,界面样式什么的后期会有所修改
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="css/index.css"> <script src="js/jquery.js"></script> <title>Document</title> </head> <body> <div id="content"> <!-- 顶端按钮 --> <div id="level"> <button class="active">初级</button> <button>中级</button> <button>高级</button> <button class="big">重新开始</button> </div> <!-- 棋盘 --> <div id="gameBox"> <!-- js动态添加的 --> </div> <!-- 底部文本 --> <div id="bottomText"> <div class="text">剩余雷数:<span class="mineNum"></sapn></div> </div> </div> <script src="js/index.js"></script> </body> </html>
三个部分,上部按钮,中部扫雷界面(‘棋盘’),下部剩余雷数text,中部‘棋盘’是用添加上去的
CSS部分,前面部分是对基础界面的样式修改,后面td.one-td.eight部分是给实现扫雷点击后出现的数字改颜色用的
注意 td的border-color,是用来实现‘棋盘’上宛如砖块一样的立体效果,设置上方和左侧为白色,其他地方为想要的颜色即可,
#content{ height: 900px; margin: 0 auto; width: 800px; } #level{ height: 25px; width: 280px; margin: 0 auto; } #level button{ height: 25px; line-height: 25px; width: 60px; text-align: center; background: rgb(73, 139, 141);; color: white; padding: 0px; margin: 0px; border: 0px; border-radius: 5px; outline: none; cursor: pointer; } #level button.active{ background: #0bb9b6; } #level button.big{ width: 80px; } #gameBox{ padding-top: 20px; } #bottomText{ height: 20px; width: 200px; margin: 0 auto; line-height: 20px; } /* .mineNum{ height: 20px; width: 50px; } */ table{ border-spacing: 1px; background-color: #929196; margin: 0 auto; } td{ height: 20px; width: 20px; background-color: #ccc; padding: 0; border: 1px solid; border-color: #fff #a1a1a1 #a1a1a1 #fff; text-align: center; line-height: 20px; font-weight: bold; } .mine{ background:#c9c9c9 url(../images/mine.png) no-repeat center; background-size: cover; } .flag{ background:#ccc url(../images/flag.png) no-repeat center; background-size: cover; } td.zero{ background-color: #d9d9d9; border-color: #d9d9d9; } td.one{ color: red; background-color: #d9d9d9; border-color: #d9d9d9; } td.two{ color: green; background-color: #d9d9d9; border-color: #d9d9d9; } td.three{ color: yellow; background-color: #d9d9d9; border-color: #d9d9d9; } td.four{ color: blue; background-color: #d9d9d9; border-color: #d9d9d9; } td.five{ color: blueviolet; background-color: #d9d9d9; border-color: #d9d9d9; } td.six{ color: brown; background-color: #d9d9d9; border-color: #d9d9d9; } td.seven{ color: cadetblue; background-color: #d9d9d9; border-color: #d9d9d9; } td.eight{ color: coral; background-color: #d9d9d9; border-color: #d9d9d9; }
JS部分!
首先使用的是面向对象思想,在部分地方会对写好的函数进行调用,函数是写在原型上的。
第一步先写了构造函数,写上了后期所需要用到的各种变量,用在后期生成‘棋盘’的时候。
//面向对象思想 function Mine(tr,td,mineNum){ this.tr=tr;//行数 this.td=td;//列数 this.mineNum=mineNum;//雷的总数 this.squares=[];//存储所有方块的信息,二维数组,以行列的信息存储 this.tds=[];//存储所有单元格的DOM对象(二维数组) this.surplusMine=mineNum;//剩余雷的数量 this.allRight=false;//玩家标注的小红旗是否全是雷,判断是否游戏成功 this.parent=document.getElementById('gameBox'); }
然后是createDom(),生成‘棋盘’,用的是table,td,tr,但是ul和li也是能够实现的
生成基础‘棋盘’后,写格子的点击事件调用了play函数,后面会讲到这个函数
Mine.prototype.createDom=function(){ var This=this; var table=document.createElement('table'); for(var i=0;i<this.tr;i++){ var domTr=document.createElement('tr');//通过构造函数传入的行数来生成tr this.tds[i]=[]; for(var j=0;j<this.td;j++){//列 var domTd=document.createElement('td');//同上 domTd.pos=[i,j];//存储对应的位置,行与列(后面会用到坐标,坐标和行与列的关系是x y恰好相反) domTd.onmousedown=function(){//当对应的格子被点击时 This.play(event,this);//This 实例对象 this 被点击的Td } this.tds[i][j]=domTd; domTr.appendChild(domTd); } table.appendChild(domTr); } this.parent.innerHTML=""; this.parent.appendChild(table); }
然后init函数
其中使用了一个random函数,用于随机生成雷的位置,用td*tr得到大于需要雷的数量的有序数,用排序+random得到随机数,通过mineNum的大小来确定随机数的数量,最后返回一个数组。
Mine.prototype.randomNum=function(){ var square=new Array(this.td*this.tr); for(var i=0;i<square.length;i++){ square[i]=i; } square.sort(function(){return 0.5-Math.random()}); return square.slice(0,this.mineNum); }
Mine.prototype.init=function(){ var rn=this.randomNum();//雷的位置 var n=0;//作为访问随机数字的位置的索引,即rn的索引 for(var i=0;i<this.tr;i++){ this.squares[i]=[]; for(var j=0;j<this.td;j++){ n++;//取方块在数组里的数组用行与列的方式去取,取方块周围对应的数字用坐标 if(rn.indexOf(n)!=-1){ this.squares[i][j]={type:'mine',x:j,y:i}; }else{ this.squares[i][j]={type:'number',x:j,y:i,value:0}; } } } this.update(); this.createDom(); this.parent.oncontextmenu=function(){ return false; } // this.mineNumDom=document.getElementsByClassName('mineNum'); // this.mineNumDom.innerHTML=this.surplusMine; $('.mineNum').html(this.surplusMine);//出bug,用原生无法显示,未解决,原生实现应该就是上面两行,但是也不知道哪里出的问题 }
上方init函数
定义一个n用于一会比较用,两个for循环用rn.indexOf(n)来判断rn即随机数有哪些,若存在随机数数组中,则未squares里对应的坐标位赋值type:'mine',否则则为number。
update()晚点再说,大致就是刷新。
this.parent.oncontextmenu是用于取消鼠标右键的点击事件,为一会给右键点击添加旗子