前端游戏之初步扫雷

扫雷应该算是最基础的js入门游戏吧,所以刚学完js就来写写扫雷的代码,初步思路想了很久,得出一个不算正规的扫雷思路,先放下图看看:
在这里插入图片描述
注:上图中的字体颜色,是我为了查看每个小方块执行的是哪步的注释,可忽略。
具体思路:
·········先用ul>li,做一个由9*9的小方格组成一个大方块——>就是扫雷的界面,在li中写入每个格子的内容(空,数字,炸弹),再将字体颜色和小方块的背景颜色设置一致,使内容能够象征性的消失,然后再通过点击事件,改变所点击小方块的字体和背景颜色,使其又“出现”,以此实现扫雷的效果。
········以上的表面代码都比较好实现,但是有一点需要花些功夫,就是当我所点击的小方格为空时,需要连接触发周边的内容,使空方格周围的上下左右的内容都显示出来,且又遇到为空的邻近方格,需要再进行上下左右的显示,接下来以此类推,得到最终的点击空方格触发周围一片的显示效果。
下面介绍下具体代码,首先是扫雷界面的设定:
html代码:

<ul class="ul1">
        <br/>
        <li></li>
        <li></li>
        <li></li>
        <li>1</li>
        <li>*</li>
        <li>1</li>
        <li></li>
        <li></li>
        <li></li><br/>
        <li></li>
        <li></li>
        <li>2</li>
        <li>2</li>
        <li>2</li>
        <li></li>
        <li></li>
        <li></li>
        <li></li><br/>
        <li>1</li>
        <li>1</li>
        <li>2</li>
        <li>*</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li></li><br/>
        <li>1</li>
        <li>*</li>
        <li>3</li>
        <li>2</li>
        <li>2</li>
        <li>1</li>
        <li>*</li>
        <li>1</li>
        <li></li><br/>
        <li>1</li>
        <li>1</li>
        <li>2</li>
        <li>*</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li></li><br/>
        <li></li>
        <li>1</li>
        <li>2</li>
        <li>2</li>
        <li>1</li>
        <li></li>
        <li></li>
        <li>1</li>
        <li>1</li><br/>
        <li>1</li>
        <li>2</li>
        <li>*</li>
        <li>1</li>
        <li></li>
        <li>1</li>
        <li>1</li>
        <li>2</li>
        <li>*</li><br/>
        <li>2</li>
        <li>*</li>
        <li>3</li>
        <li>1</li>
        <li></li>
        <li>1</li>
        <li>*</li>
        <li>2</li>
        <li>1</li><br/>
        <li>2</li>
        <li>*</li>
        <li>2</li>
        <li></li>
        <li></li>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li></li><br/>
    </ul>
    

注:上述html是模仿电脑自带扫雷游戏的内容设置的,有想换内容的可以参考电脑自带的扫雷游戏,或者自己想也可以。
设置完html,还没将大方格做出来,因此需要css的帮忙,
css代码:

           ul{
            list-style: none;         /*取消ul原有的格式*/
            position: absolute;          /*设置在页面中的绝对定位*/
            left: 40px;
            top: 40px;
        }
    .ul1 li{
        float: left;	               /*使li能够横着排成9个小方格*/
        width: 20px;              /*小格子的宽*/
        height: 20px;            /*小格子的高*/
        border: 1px solid rgb(158, 157, 157);                       /*格子的边框*/
        background-color: rgb(209, 207, 207);                       /*格子的初始背景颜色*/
        line-height: 20px;                            /*使内容居中对齐*/
        text-align: center;                         /*使内容居中对齐*/
        color: rgb(209, 207, 207);                      /*内容字体颜色*/
        cursor: pointer;                            /*当鼠标移入方格时,箭头变成指示类型的小手*/
    }

有了上述的css,使我们的扫雷界面基本完成,接下来就是内部逻辑的处理了,就需要用到js的内容。
以下是js的代码:

function retSibling(e,n){              //这是提取e元素的前n个或后n个的元素的封装函数
         while(e && n){
            if(n > 0){
               if(e.nextElementSibling){
                e = e.nextElementSibling;
               }
               else{
                for(e = e.nextSibling;e && e.nodeType != 1;e = e.nextSibling)
                ;
               }
                n --;
            }
            else
            {
                if(e.previousElementSibling){
                    e = e.previousElementSibling;
                }
               else{
                   for( e = e.previousSiling;e && e.nodeType != 1;e = e.previousSiling);
               }
                n ++;
            }
         }
         return e;
     }



function k1(target){    //由下面调用一个所触发的target元素,查看它前一个兄弟元素节点,查看的内容有:1.是否为边界节点(br/);2.内容是否为空;3.内容是否为*;4.内容是否为数字

    if(target.previousElementSibling == "<br/>"){
    }else{
        if(target.previousElementSibling.innerText == ""){  //当为空时,首先改变该元素的字体和背景颜色,再将它的前一个节点元素重新赋给target,利用递归的方法重复调用k1检查下一个节点元素的内容
            target.previousElementSibling.style.color = "black";
            target.previousElementSibling.style.backgroundColor = "#fff";
            target = target.previousElementSibling;
            k1(target);
            k3(target);         //将target提供给k3,k3是向上判断的封装函数
            k4(target);        //将target提供给k4,k4是向下判断的封装函数
        }else if(target.previousElementSibling.innerText == "*"){    //为*时,表示炸弹,因此不会触发任何内容

        }else{       //去掉空和*,剩下的自然是数字,因此当是数字时,只需要显示该数字就可以了
            target.previousElementSibling.style.color = "black";
            target.previousElementSibling.style.backgroundColor = "#fff";
        }
    }
}


function k2(target){      //查看所给的target的后一个元素,与上述的向前(k1)的判断类似,下面不再仔细描述
    if(target.nextElementSibling == "<br/>"){

    }else{
        if(target.nextElementSibling.innerText == ""){
            target.nextElementSibling.style.color = "green";
            target.nextElementSibling.style.backgroundColor = "#fff";
            target = target.nextElementSibling;
            k2(target);
            k3(target);
            k4(target);
        }else if(target.nextElementSibling.innerText == "*"){

        }else{
            target.nextElementSibling.style.color = "green";
            target.nextElementSibling.style.backgroundColor = "#fff";
        }
    }
}


function k3(target){    //查看target的上方元素,利用9*9的特性,该节点元素的上方元素应该是该节点的前9个,不过由于在html中采用<br/>来做为转折方法,所以该元素的上方元素节点应该是前10个所在的位置。
    try{              //这里会用到try,是因为实在想不出什么好的方法可以限制当没有前10个元素节点时不操作的方法,所以用try投机取巧的方法,综合了下错误,当然错误仍然还在,只是不影响接下来的操作。
        var key = true;
        if(key == true){
        target = retSibling(target,-10);      //调用retSibling函数,将target和-10(-10表示前10个元素)提供给retSibling函数,使其返回该元素的第前10个的元素节点给target,替换原有的target所表示的元素节点
        if(target.innerText == ""){
            target.style.color = "red";
            target.style.backgroundColor = "#fff";
            k3(target);
            k5(target);      //注意:这里的k5与k1的内容基本相似,却不能改成k1,否则代码会蹦
            k6(target);      //注意:这里的k6与k2的内容基本相似,却不能改成k1,否则代码会蹦
             
        }else if(target.innerText == "*"){

        }else{
            target.style.color = "red";
            target.style.backgroundColor = "#fff";
            k1(target);
            k2(target);
        }
        }
    }catch{
        key = false;
    }
}


function k4(target){         //与上述的k3内容基本一致,所不同的是他表示的是下方的元素节点
    try{
        var key = true;
        if(key == true){
        target = retSibling(target,10);
        if(target.innerText == ""){
            target.style.color = "blue";
            target.style.backgroundColor = "#fff";
           
            k4(target); 
            k5(target);       //注意:这里的k5与k1的内容基本相似,却不能改成k1,否则代码会蹦
            k6(target);      //注意:这里的k6与k2的内容基本相似,却不能改成k1,否则代码会蹦
          
        }else if(target.innerText == "*"){

        }else{
            target.style.color = "blue";
            target.style.backgroundColor = "#fff";
            k1(target);
            k2(target);
        }
        }
    }catch{
        key = false;
    }
}


function k5(target){           //额外多出来表示一行的左边元素节点判断,但很关键,与k1基本一致,只是缺少递归。
    if(target.previousElementSibling == "<br/>"){
    }else{
        if(target.previousElementSibling.innerText == ""){
            target.previousElementSibling.style.color = "black";
            target.previousElementSibling.style.backgroundColor = "#fff";
            target = target.previousElementSibling;
            k5(target); 
        }else if(target.previousElementSibling.innerText == "*"){

        }else{
            target.previousElementSibling.style.color = "black";
            target.previousElementSibling.style.backgroundColor = "#fff";
        }
    }
}

function k6(target){          //额外多出来表示一行的右边元素节点判断,但很关键与k2基本一致,只是缺少递归。
    if(target.nextElementSibling == "<br/>"){

    }else{
        if(target.nextElementSibling.innerText == ""){
            target.nextElementSibling.style.color = "green";
            target.nextElementSibling.style.backgroundColor = "#fff";
            target = target.nextElementSibling;
            k6(target);
        }else if(target.nextElementSibling.innerText == "*"){

        }else{
            target.nextElementSibling.style.color = "green";
            target.nextElementSibling.style.backgroundColor = "#fff";
        }
    }
}

 var ul = document.getElementsByTagName('ul')[0];    //将ul选择出来
    ul.onclick = function(e){                    //对ul进行点击事件
    var event = e||window.event;
    var target = event.target||event.srcElement;
    target.style.color = "black";
    target.style.backgroundColor = "#fff";
    
    if(target.innerText == "*"){    //为*(炸弹)时,表示游戏结束
        alert("Boom!!!");
    }else if(target.innerText == ""){
       // 以下k1,k2,k3,k4表示调用上述的封装函数,具体作用上述已解释
        k1(target);
        k2(target);
        k3(target);
        k4(target);

    }
    }

到此,基本的扫雷功能已经完全实现,该代码中的最大缺陷在于,用了递归的方法,使得当触发联动性比较大的空方格时,较容易发生代码崩溃的现象,所以对于刚开始在li中所写内容需要注意,尽量使方格空空的连性少些。
**求助:**不知有哪位大佬能够帮助解决上述的缺陷或者指出代码中有哪些不合理性,欢迎留下您留下宝贵的建议,谢谢!

猜你喜欢

转载自blog.csdn.net/weixin_42800902/article/details/83545048
今日推荐