JS實現貪喫蛇

JS實現貪喫蛇

1.結構

創建一個盒子box作爲蛇的身體,當前盒子中只有一個子元素,代表此時蛇的長度爲1.
在創建一個盒子food作爲貪喫蛇的食物。

 <div id="box">
        <div></div>
 </div>
 <div id="food"></div>

2.CSS

設置蛇和食物的樣式,這裏注意蛇和食物都是絕對定位。

<style>
    *{
        padding: 0px;
        margin: 0px;
    }
    #box div{
        width: 30px;
        height: 30px;
        box-sizing: border-box;
        background: green;
        border: 1px solid black;
        position: absolute;
    }
    #food{
        width: 30px;
        height: 30px;
        background: brown;
        position: absolute;
    }
    </style>

3.腳本

獲取蛇的身體和每一個子元素
var box = document.getElementById("box");
var boxs = document.getElementById("box").children;
定義蛇頭的位置
 var snackX = 0;
 var snackY = 0;
獲取屏幕寬度和高度,以此來設定牆的邊界,以限制蛇的移動範圍。
 var cw = document.documentElement.clientWidth;
 var ch = document.documentElement.clientHeight;
 var minsnackX = 0;
 var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
 var minsnackY = 0;
 var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
定義初始的移動方向。
  var turn = "right";
獲取食物元素,並設置食物的位置座標。
 var foodele = document.getElementById("food");
    var foodX,foodY;
蛇的初始化
  for(var i = 0; i <6 ; i++){
        box.appendChild(boxs[0].cloneNode(true));
    }
刷新食物
 function food(){
 	//此處的座標要先獲取頁面最大支持的蛇身體的塊數,然後在塊數中隨機,然後乘以塊數的大小,
 	//因爲蛇的移動每一步都是固定的,想要判定食物和蛇頭重合就必須座標是整塊的倍數。
   	 foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
     foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
        //判定當食物的產生位置和蛇的任何一個位置重合時就重新生成食物。
        for(var i = 0;i<boxs.length;i++){
            if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
                food();
            }
        }
        foodele.style.left = foodX + "px";
        foodele.style.top = foodY + "px";
 }
調用food()方法 生成第一個食物
   food();
設置定時器 每次執行一次蛇的運行方法
   var timer = setInterval(function(){
        snackMOve();
    },150)
封裝一個蛇的運動方法
  //移動和判定邊界
    function snackMOve(){
    //此處爲判定方向 根據判定的方向,向改方向前進一個方塊
        switch(turn){
            case "right":snackX +=30;break;
            case "left":snackX -=30;break;
            case "bottom":snackY +=30;break;
            case "top":snackY -=30;break;
        }
        //如果蛇越過了牆就從另一端出現
        if(snackX > maxsnackX){
            snackX = 0;
        }
        if(snackX < minsnackX){
            snackX = maxsnackX;
        }
        if(snackY > maxsnackY){
            snackY = 0;
        } 
        if(snackY < minsnackY){
            snackY = maxsnackY;
        }
        //從最後一個開始,每個元素跟隨上一個元素的位置
        for(var i = boxs.length-1; i >0 ; i--){
            boxs[i].style.left = boxs[i-1].style.left;
            boxs[i].style.top =  boxs[i-1].style.top ;
        }
        //第一個也就是蛇頭的位置,永遠是根據方向獲取的位置
        boxs[0].style.left = snackX + "px";
        boxs[0].style.top =  snackY + "px" ;


        //判定喫到食物 就長大和刷新
        //當蛇頭位置移動之後與食物重合 那麼刷新食物,並且在蛇的身體中插入一個克隆的元素,相當於長度+1
        if(snackX  === foodX && snackY  === foodY){
            food();
            box.appendChild(boxs[0].cloneNode(true));
        }else{
        //判定撞死 
        //當蛇頭與身體中的任何一個元素重合,那麼判定結束遊戲,停止定時器
            for(var i = 1;i<boxs.length;i++){
                if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
                    clearInterval(timer);
                    alert("失敗");
                }
            }
        }
    }

蛇的運動方向

document.onkeydown = function(eve){
    var e = eve||event;
    var keyCode = e.keyCode||e.which;
    switch(keyCode){
        case 37:if(turn === "right"){break;}turn = "left";break;
        case 38:if(turn === "bottom"){break;}turn = "top";break;
        case 39:if(turn === "left"){break;}turn = "right";break;
        case 40:if(turn === "top"){break;}turn = "bottom";break;
    }        
}

全部代碼

<!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">
    <title>Document</title>
    <style>
    *{
        padding: 0px;
        margin: 0px;
    }
    #box div{
        width: 30px;
        height: 30px;
        box-sizing: border-box;
        background: green;
        border: 1px solid black;
        position: absolute;
    }
    #food{
        width: 30px;
        height: 30px;
        background: brown;
        position: absolute;
    }
    </style>
</head>
<body>
    <div id="box">
        <div></div>
    </div>
    <div id="food"></div>
    <script>
        var box = document.getElementById("box");
        var boxs = document.getElementById("box").children;
        var snackX = 0;
        var snackY = 0;
        var cw = document.documentElement.clientWidth;
        var ch = document.documentElement.clientHeight;
        var minsnackX = 0;
        var maxsnackX = Math.floor(cw / boxs[0].offsetWidth)*boxs[0].offsetWidth;
        var minsnackY = 0;
        var maxsnackY = Math.floor(ch / boxs[0].offsetHeight)*boxs[0].offsetHeight;
        var turn = "right";
        var foodele = document.getElementById("food");
        var foodX,foodY;

        for(var i = 0; i <6 ; i++){
            box.appendChild(boxs[0].cloneNode(true));
        }


        //隨機食物
        function food(){
            foodX = parseInt( Math.random()*Math.floor(cw / boxs[0].offsetWidth))*boxs[0].offsetWidth;
            foodY = parseInt( Math.random()*Math.floor(ch / boxs[0].offsetHeight))*boxs[0].offsetHeight;
            for(var i = 0;i<boxs.length;i++){
                if(foodX + "px" === boxs[i].style.left && foodY + "px" === boxs[i].style.top){
                    food();
                }
            }
            foodele.style.left = foodX + "px";
            foodele.style.top = foodY + "px";
        }
        food();

        //設置定時器 移動
        var timer = setInterval(function(){
            snackMOve();
        },150)


        //移動和判定邊界
        function snackMOve(){
            switch(turn){
                case "right":snackX +=30;break;
                case "left":snackX -=30;break;
                case "bottom":snackY +=30;break;
                case "top":snackY -=30;break;
            }
            //根據邊界歸零
            if(snackX > maxsnackX){
                snackX = 0;
            }
            if(snackX < minsnackX){
                snackX = maxsnackX;
            }
            if(snackY > maxsnackY){
                snackY = 0;
            } 
            if(snackY < minsnackY){
                snackY = maxsnackY;
            }
            for(var i = boxs.length-1; i >0 ; i--){
                boxs[i].style.left = boxs[i-1].style.left;
                boxs[i].style.top =  boxs[i-1].style.top ;
            }
            boxs[0].style.left = snackX + "px";
            boxs[0].style.top =  snackY + "px" ;


            //判定喫到食物 就長大和刷新
            if(snackX  === foodX && snackY  === foodY){
                food();
                box.appendChild(boxs[0].cloneNode(true));
            }else{
            //判定撞死 暫停計時器 刷新
                for(var i = 1;i<boxs.length;i++){
                    // console.log(boxs[i].style.left);
                    if(snackX + "px" === boxs[i].style.left && snackY + "px" === boxs[i].style.top){
                        clearInterval(timer);
                        alert("失敗");
                        // console.log(1)
                    }
                }
            }
        }



        //方向
        document.onkeydown = function(eve){
            var e = eve||event;
            var keyCode = e.keyCode||e.which;
            switch(keyCode){
                case 37:if(turn === "right"){break;}turn = "left";break;
                case 38:if(turn === "bottom"){break;}turn = "top";break;
                case 39:if(turn === "left"){break;}turn = "right";break;
                case 40:if(turn === "top"){break;}turn = "bottom";break;
            }        
        }
    </script>
</body>
</html>

總結

貪喫蛇的思路主要是有以下幾個部分
1.食物的隨機出現(不能隨機在蛇身上)
2.定時器控制蛇的移動
3.牆的判定
4.蛇的運動邏輯
5.運動方向的判定
6.喫到食物的判定
7.蛇頭與身體的判定(即遊戲結束的判定)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章