原生js —— 简易版贪吃蛇

几点注意事项:
① 当将页面中某个对象存入数组时,对数组进行操作相当于对DOM元素操作。
② 移除页面上的某一个元素的两种方法:1) 父对象.removeChild(移除对象) 2)对象.remove()
select对象.selectedIndx为当前选中元素的索引。select对象.selectedOptions为当前选中元素
④ 当移除select标签的被选中的元素时:select对象.remove(select对象.selectedIndex)
父元素对象.removeChild(移除对象):以 Node 对象返回被删除的节点,如果节点不存在则返回 null。
对象.remove():jQuery方法。返回一个指向已被删除的节点的引用,这个节点元素还可以使用;该方法也会移除被选元素的数据和事件。如需移除元素,但保留数据和事件,请使用 detach() 方法代替。如只需从被选元素移除内容,请使用 empty() 方法。

简易版贪吃蛇

功能:蛇可穿墙,只能撞自己死亡。蛇在吃一个食物后得分会加一。创建的食物必须要在蛇身外部出现,食物的位置不可和蛇身任何一个位置相同。

1. 创建map:使用动态原型模式,只有当instance=null时才创建map对象。最终将map加给body(document.body.appendChild(地图对象))

注意:将map设为绝对定位,无论是蛇还是食物都作为绝对定位在map中。

  var getMap = (function getMap(){
        var instance = null;
        function map(){
            var divele = document.createElement("div");
            divele.style.width="900px";
            divele.style.height="600px";
            divele.style.backgroundColor="black";
            divele.style.position="relative";
            divele.className="map";
            document.body.appendChild(divele);
        }
      return function () {
          if(instance==null){
              instance = new map();
          }
          return instance;
      }
    })();
2. 蛇对象
① 创建蛇身:createSnack方法
    this.createSnack = function(ele) {
            var spanEle = document.createElement("span");
            spanEle.style.width="30px";
            spanEle.style.height="30px";
            spanEle.style.backgroundColor=ele[2];
            spanEle.style.position="absolute";
            spanEle.style.left=ele[0]*30+"px";
            spanEle.style.top = ele[1]*30+"px";
            return spanEle;
        };
getSnack方法

init数组中存储所有蛇身对象。初始时init[i][3]都为null,且数组长度为3(默认有三个蛇身对象)。初始时调用该方法,创建初始三个蛇身,并将其将入map元素。之后在每次吃完食物后调用该方法,增加蛇身长度,并将其将入map元素。

 this.getSnack=function(){
            for(var i=0;i<init.length;i++){
                if(init[i][3]==null){
                    init[i][3] = this.createSnack(init[i]);
                    map.appendChild(init[i][3]);
                }
            }
        };
③ 蛇移动方法:move

① 在蛇移动过程中,每个蛇身对象都取前一个对象的定位位置(即x,y值),蛇头根据当前移动方向来决定位置。
② 在蛇移动过程中,要注意蛇穿墙的情况,当当前蛇头x>30时,设置x=0。当前蛇头x<0,设置x=29(注意:此处只是init中每个对象的x和y改变,还并未改变位置),纵轴同理。
③ 在蛇移动过程中,如果蛇头的位置和蛇身任何一个对象的位置相同,则清除移动计时器,并提示游戏失败。(注意:此处只是init中每个对象的x和y改变,并未改变位置)游戏失败后直接return。

this.move = function () {
            for(var i=init.length-1;i>0;i--){
                init[i][0] = init[i-1][0];
                init[i][1] = init[i-1][1];
            }
            //转换方向
            switch (direction) {
                case "left":
                    init[0][0]--;
                    break;
                case "right":
                    init[0][0]++;
                    break;
                case "up":
                    init[0][1]--;
                    break;
                case "down":
                    init[0][1]++;
                    break;
            }
            //蛇穿墙
            if(init[0][0]>=30){
                init[0][0]=0;
            }
            if(init[0][0]<0){
                init[0][0]=29;
            }
            if(init[0][1]>=20){
                init[0][1]=0;
            }
            if(init[0][1]<0){
                init[0][1]=19
            }
            for(var j=1;j<init.length;j++){
                if(init[j][0]==init[0][0] && init[j][1]==init[0][1]){
                    clearInterval(timer);
                    alert("Game over!!!你最后的得分为"+count);
                    return;
                }
            }
            this.setPostion();
            this.eat();
            complete[1] = true;

        }
④ 设置蛇的位置:setPosition方法

init数组变化时,DOM元素并未发生变化,故需要重新设置每一个对象的位置。将所有的位置提取成一个函数设置是因为:当蛇撞到自身时,要先判断init[0]是否与蛇身对象位置相同,而不能在位置变化后再判断(会出现在撞到自身后继续向前移动的情况)

   this.setPostion = function () {
            for(var i=0;i<init.length;i++){//将所有位置提成一个函数写蛇头不会被盖住。(若先设置尾部,再设置头部,最后撞死时头部后面的元素已经取得了头部的位置,尽管头部未移动,但是头部后面的元素和头部叠加到了一起)
                init[i][3].style.left=init[i][0]*30+"px";
                init[i][3].style.top=init[i][1]*30+"px";
            }
        }
3. 创建食物:createFood方法

① 在创建食物时,要先移除已被吃掉的食物map.removeChild(food[0])(food数组中只有当前食物,故其长度最大为1)
② 在创建前应该先生成除蛇身位置以外的随机食物位置。此处应用一个while循环来判断。
③ 创建食物相关信息,并将食物加入map对象中

function createFood(){
        if(food.length==1){
            map.removeChild(food[0]);
        }
        var randomX = this.getRandomX();
        var randomY = this.getRandomY();
        for(var i=0;i<init.length;i++)
            while(randomX==init[i][0] && randomY==init[i][1]){
            //判断是否食物位置与蛇的位置相同
                randomX = this.getRandomX();
                randomY = this.getRandomY();
                i=-1;
                break;
            }
        }
        var spanEle = document.createElement("div");
        foodPosition[0]=(randomX);//用foodPosition存储当前食物的位置,用来和蛇头位置作比较。若相同,则蛇吃食物
        foodPosition[1]=(randomY);
        spanEle.style.backgroundColor="green";
        spanEle.style.width="30px";
        spanEle.style.height="30px";
        spanEle.style.position="absolute";
        spanEle.className="food";
        spanEle.style.left=randomX*30+"px";
        spanEle.style.top=randomY*30+"px";
        map.appendChild(spanEle);

    }
4. 切换方向:body的onkeyup事件

① 根据key来做限制,且存储当前方向direction。若当前方向和即将变化的方向相反,则方向不改变,蛇依旧以当前的方向运动。若不相反,才可改变。
② 用complete属性来判断上次移动是否完成,若complete[1]为false,则上次移动未完成,不能进行下次移动(若当前蛇向上移动,当以很快的速度按下右下键时,会撞自己死亡:按下右键还未move便方向又变为向下。由于按了右键后方向向右,故是可以将方向改为向下的)
③ 当转变方向时,将complete[1]值设为false。在当前方向下完成一次移动后,则将compelet[1]变为true。这样至少保证了蛇在该方向完成了一次移动。只有当compelet[1]true时,蛇才可转变方向。

document.body.onkeyup = function (ev) {
            var key = ev.key;
            if(complete[0]!=key && complete[1]){
                if(key=="ArrowUp"){
                    if(direction!="down"){
                        direction = "up";
                    }
                }
                else if(key=="ArrowDown"){
                    if(direction!="up" ){
                        direction="down";
                    }
                }else if(key=="ArrowLeft"){
                    if(direction!="right" ){
                        direction="left";
                    }
                }else{
                    if(direction!="left"){
                        direction="right";
                    }
                }
                complete = [key,false];
            }

        }
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<style>
    *{
        margin:0;
        padding:0;
    }
    .grade{
        font-style: normal;
        font-weight: bold;
        color: red;
    }
</style>
<body>
<span >
    当前你的得分为:<i class="grade"></i>
</span>
<script>
    var map;
    var snackList;
    var  init = [[2,0,"red",null],[1,0,"yellow",null],[0,0,"yellow",null]];
    var timer;
    var food;
    var count=0;
    var foodPosition=[];
    var direction="right";
    var grade = document.getElementsByClassName("grade")[0];
    grade.innerHTML = count;
    var complete = ["ArrowRight",true];
    var getMap = (function getMap(){
        var instance = null;
        function map(){
            var divele = document.createElement("div");
            divele.style.width="900px";
            divele.style.height="600px";
            divele.style.backgroundColor="black";
            divele.style.position="relative";
            divele.className="map";
            document.body.appendChild(divele);
        }
      return function () {
          if(instance==null){
              instance = new map();
          }
          return instance;
      }
    })();
    function snack(){
        this.getSnack=function(){
            for(var i=0;i<init.length;i++){
                if(init[i][3]==null){
                    init[i][3] = this.createSnack(init[i]);
                    map.appendChild(init[i][3]);
                }
            }

        };
        this.createSnack = function(ele) {
            var spanEle = document.createElement("span");
            spanEle.style.width="30px";
            spanEle.style.height="30px";
            spanEle.style.backgroundColor=ele[2];
            spanEle.style.position="absolute";
            spanEle.style.left=ele[0]*30+"px";
            spanEle.style.top = ele[1]*30+"px";
            return spanEle;
        };
        this.eat = function () {
            if(init[0][0]==foodPosition[0] && init[0][1] == foodPosition[1]){
                foodPosition = [];
                init[init.length]=[init[init.length-1][0],init[init.length-1][1],"yellow",null];
                this.getSnack();
                count++;
                grade.innerHTML = count;
                createFood();

            }
        };
        this.setPostion = function () {
            for(var i=0;i<init.length;i++){//将所有位置提成一个函数写蛇头不会被盖住。(若先设置尾部,再设置头部,最后撞死时头部后面的元素已经取得了头部的位置,尽管头部未移动,但是头部后面的元素和头部叠加到了一起)
                init[i][3].style.left=init[i][0]*30+"px";
                init[i][3].style.top=init[i][1]*30+"px";
            }
        }
        this.move = function () {
            for(var i=init.length-1;i>0;i--){
                init[i][0] = init[i-1][0];
                init[i][1] = init[i-1][1];
            }
            //转换方向
            switch (direction) {
                case "left":
                    init[0][0]--;
                    break;
                case "right":
                    init[0][0]++;
                    break;
                case "up":
                    init[0][1]--;
                    break;
                case "down":
                    init[0][1]++;
                    break;
            }
            //蛇穿墙
            if(init[0][0]>=30){
                init[0][0]=0;
            }
            if(init[0][0]<0){
                init[0][0]=29;
            }
            if(init[0][1]>=20){
                init[0][1]=0;
            }
            if(init[0][1]<0){
                init[0][1]=19
            }
            for(var j=1;j<init.length;j++){
                if(init[j][0]==init[0][0] && init[j][1]==init[0][1]){
                    clearInterval(timer);
                    alert("Game over!!!你最后的得分为"+count);
                    return;
                }
            }
            this.setPostion();
            this.eat();
            complete[1] = true;

        }
    }
    //创造食物
    function getRandomX() {
        return Math.floor(Math.random()*30);
    }
    function getRandomY() {
        return Math.floor(Math.random()*20);
    }
    function createFood(){
        if(food.length==1){
            map.removeChild(food[0]);
        }
        var randomX = this.getRandomX();
        var randomY = this.getRandomY();
        for(var i=0;i<init.length;i++){
            while(randomX==init[i][0] && randomY==init[i][1]){
                randomX = this.getRandomX();
                randomY = this.getRandomY();
                i=-1;
                break;
            }
        }
        var spanEle = document.createElement("div");
        foodPosition[0]=(randomX);
        foodPosition[1]=(randomY);
        spanEle.style.backgroundColor="green";
        spanEle.style.width="30px";
        spanEle.style.height="30px";
        spanEle.style.position="absolute";
        spanEle.className="food";
        spanEle.style.left=randomX*30+"px";
        spanEle.style.top=randomY*30+"px";
        map.appendChild(spanEle);

    }
    window.onload = function (ev) {
        getMap();
        map = document.getElementsByClassName("map")[0];
        food = document.getElementsByClassName("food");
        snackList = new snack();
        snackList.getSnack();
        timer = setInterval(function () {
                snackList.move()
        },250);
        createFood();
        document.body.onkeyup = function (ev) {
            var key = ev.key;
            if(complete[0]!=key && complete[1]){
                if(key=="ArrowUp"){
                    if(direction!="down"){
                        direction = "up";
                    }
                }
                else if(key=="ArrowDown"){
                    if(direction!="up" ){
                        direction="down";
                    }
                }else if(key=="ArrowLeft"){
                    if(direction!="right" ){
                        direction="left";
                    }
                }else{
                    if(direction!="left"){
                        direction="right";
                    }
                }
                complete = [key,false];
            }

        }
    }
</script>
</body>
</html>
                                                                                                      
                                                                                       
发布了72 篇原创文章 · 获赞 72 · 访问量 6338

猜你喜欢

转载自blog.csdn.net/weixin_43314846/article/details/100701600