js实现扫雷

扫码查看

学习扫雷笔记,学习资料:渡一教育实现扫雷视频,基本上所有都是原生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是用于取消鼠标右键的点击事件,为一会给右键点击添加旗子
12-29 09:18
查看更多