先放一张成品图

javascript简单贪吃蛇 js做贪吃蛇_贪吃蛇

首先在写贪吃蛇之前,理一下思路。

  1. 选择什么结构存储贪吃蛇
  2. 如何进行移动
  3. 如何吃到食物
  4. 吃到食物怎么增加身体
  5. 怎么才能结束游戏

好了,理清这几点之后,我们就可以着手进行游戏结构的编写啦
٩(๑> ₃ <)۶з。

首先我们采用二维数组来存储贪吃蛇,用坐标来初始化蛇头以及蛇身。
(蛇的每一节都是20*20)

var snake = function(){
    this.bodyArr = [
		{x: 0,y: 0},
		{x: 0,y: 20},
		{x: 0,y: 40},
		{x: 0,y: 60},
		{x: 0,y: 80},
		{x: 0,y: 100}, //这是蛇头
	];
	this.dir = 'DOWN'; //默认方向向下运动
}

其实完成蛇的初始化就已经相当于完成了一半啦,剩下的就是慢慢添加方法函数了。
我们将所有的方法都选择添加在原型链上。

首先将蛇渲染到页面上,这个就不多赘述了。然后就是怎么让蛇跑起来的问题了,这里我们只需要控制蛇头的移动就行了,蛇身就依次往前挪动一格,然后删除以前的蛇再重绘即可。
然后添加键盘事件,选择上下左右进行移动,这里移动有一个简单的小逻辑。
比如我们按 ‘左’ 时,蛇正在向右或者向左移动时,都不能进行操作。其余方向同理。

那怎么吃到食物呢,首先设置随机数让食物随机刷新,蛇头吃到食物,删除当前食物再重绘。
在判断如何吃到食物时,很简单,只需要判断蛇头和食物的横纵距离是否相等即可。那么该如何添加蛇身进去呢,这是个问题,不是简单的添加一个元素在蛇的尾部,因为蛇有四个运动的方向,需要判断当前运动的方向,再添加对应的坐标。

if (arr[0].x === arr[1].x) {      //纵向移动
    x = arr[0].x;
    if (arr[0].y > arr[1].y) {      //向上移动
        y = arr[0].y + 20;
    } else if (arr[0].y < arr[1].y) {  // 向下移动
        y = arr[0].y - 20;
    }
} else if (arr[0].y === arr[1].y) {    // 横向移动
    y = arr[0].y;
    if (arr[0].x > arr[1].x) {     //向左移动
        x = arr[0].x + 20;
    } else if (arr[0].x < arr[0].x) {   //向右移动
        x = arr[0].x - 20;
    }
}
	arr.unshift({ x, y })

完成至此,已经把贪吃蛇的基本功能都实现了,现在只是稍微丰富下边边角角即可畅玩游戏啦(๑¯ิε ¯ิ๑)

我在设置蛇头移动时,没有设置触碰边界就死亡,而是从哪个方向出去,就从相反的方向进来,只有触碰到自己的身体时,才会死亡。实现方式多种多样,看个人喜好。

剩下的得分就很简单了,只需要在吃到食物时,分数累加即可。

是不是感觉贪吃蛇也并没有那么难呢。

原生js实现代码略多,可以用canvas重写下。不过逻辑都是一样的哦…

以下附上完整代码:
index.html

<div class="wrap">
        <div class="score">
            <span>得分:</span>
            <span class="result"></span>
        </div>
</div>

index.css

<style>
    .wrap {
        width: 500px;
        height: 500px;
        margin: 100px auto;
        background-color: #000;
        position: relative;
        overflow: hidden;
    }

    .round {
        display: block;
        position: absolute;
        width: 20px;
        height: 20px;
        background-color: green;
        border-radius: 50%;
    }

    .round.head {
        background-color: red;
    }

    .food {
        display: block;
        position: absolute;
        width: 20px;
        height: 20px;
        background-color: purple;
        border-radius: 50%;
    }

    .wrap .score {
        color: yellow;
        position: absolute;
        top: 30px;
        left: 40%;
        z-index: 999;
    }
    </style>

index.js

window.onload = function() {
        init();
    }

    function init() {
        initGame();
    }

    var initGame = (function() {
        var wrap = document.getElementsByClassName('wrap')[0],
            result = document.getElementsByClassName('result')[0];
        wrapW = wrap.offsetWidth,
            wrapH = wrap.offsetHeight,
            count = 0;
        t = null;
        var snake = function() {
            this.bodyArr = [
                { x: 0, y: 0 },
                { x: 0, y: 20 },
                { x: 0, y: 40 },
                { x: 0, y: 60 },
                { x: 0, y: 80 },
                { x: 0, y: 100 },
            ];
            this.dir = 'DOWN';
        }

        snake.prototype = {
            init: function() {
                this.initsnake();
                this.run();
                this.bindEvent();
                this.food();
            },
            bindEvent: function() {
                var _self = this;
                document.addEventListener('keydown', function() {
                    _self.changeDir();
                }, false);
            },
            initsnake: function() {
                var arr = this.bodyArr,
                    len = arr.length,
                    frag = document.createDocumentFragment(),
                    item;

                for (var i = 0; i < len; i++) {
                    item = arr[i];
                    var round = document.createElement('i');
                    round.className = i === len - 1 ? "round head" : "round";
                    round.style.left = item.x + "px";
                    round.style.top = item.y + 'px';
                    frag.appendChild(round);
                }
                wrap.appendChild(frag);
            },

            run: function() {
                var _self = this;

                t = setInterval(function() {
                    _self.move();
                }, 500);
            },

            move: function() {
                var arr = this.bodyArr,
                    len = arr.length;

                for (var i = 0; i < len; i++) {
                    if (i === len - 1) {
                        this.setHeadXY(arr);
                    } else {
                        arr[i].x = arr[i + 1].x;
                        arr[i].y = arr[i + 1].y;
                    }
                }
                this.removeSnake();
                this.initsnake();
                this.dead(arr);
                this.eatFood(arr);
            },
            dead: function(arr) {
                var headX = arr[arr.length - 1].x,
                    headY = arr[arr.length - 1].y,
                    item;
                for (var i = 0; i < arr.length - 2; i++) {
                    item = arr[i];

                    if (headX === item.x && headY === item.y) {
                        var _self = this;
                        setTimeout(function() {
                            alert('over');
                            clearInterval(t);
                            _self.removeSnake();
                        }, 200)
                    }
                }
            },

            setHeadXY: function(arr) {
                var head = arr[arr.length - 1];
                switch (this.dir) {
                    case 'LEFT':
                        if (head.x <= 0) {
                            head.x = wrapW - 20;
                        } else {
                            head.x -= 20;
                        }
                        break;
                    case 'RIGHT':
                        if (head.x >= wrapW - 20) {
                            head.x = 0;
                        } else {
                            head.x += 20;
                        }
                        break;
                    case 'UP':
                        if (head.y <= 0) {
                            head.y = wrapH - 20;
                        } else {
                            head.y -= 20;
                        }
                        break;
                    case 'DOWN':
                        if (head.y >= wrapH - 20) {
                            head.y = 0;
                        } else {
                            head.y += 20;
                        }
                        break;
                    default:
                        break;
                }
            },

            removeSnake: function() {
                var bodys = document.getElementsByClassName('round');
                while (bodys.length > 0) {
                    bodys[0].remove();
                }
            },
            changeDir: function(e) {
                var e = e || window.event,
                    code = e.keyCode;
                this.setDir(code);
            },
            setDir: function(code) {
                switch (code) {
                    case 37:
                        if (this.dir !== 'RIGHT' && this.dir !== 'LEFT') {
                            this.dir = "LEFT";
                        }
                        break;
                    case 38:
                        if (this.dir !== 'UP' && this.dir !== 'DOWN') {
                            this.dir = "UP";
                        }
                        break;
                    case 39:
                        if (this.dir !== 'RIGHT' && this.dir !== 'LEFT') {
                            this.dir = "RIGHT";
                        }
                        break;
                    case 40:
                        if (this.dir !== 'UP' && this.dir !== 'DOWN') {
                            this.dir = "DOWN";
                        }
                        break;
                    default:
                        break;
                }

            },
            food: function() {
                var food = document.createElement('i');
                food.className = 'food';
                food.style.left = this.foodPos(wrapW) * 20 + 'px';
                food.style.top = this.foodPos(wrapH) * 20 + 'px';
                wrap.appendChild(food);
            },

            foodPos: function(WorH) {
                return Math.floor(Math.random() * (WorH / 20));
            },

            eatFood: function(arr) {
                var food = document.getElementsByClassName('food')[0],
                    foodX = food.offsetLeft,
                    foodY = food.offsetTop,
                    headX = arr[arr.length - 1].x,
                    headY = arr[arr.length - 1].y,
                    x,
                    y;

                if (headX === foodX && headY === foodY) {
                    this.removeFood();
                    this.score();
                    this.food();

                    if (arr[0].x === arr[1].x) {
                        x = arr[0].x;
                        if (arr[0].y > arr[1].y) {
                            y = arr[0].y + 20;
                        } else if (arr[0].y < arr[1].y) {
                            y = arr[0].y - 20;
                        }
                    } else if (arr[0].y === arr[1].y) {
                        y = arr[0].y;
                        if (arr[0].x > arr[1].x) {
                            x = arr[0].x + 20;
                        } else if (arr[0].x < arr[0].x) {
                            x = arr[0].x - 20;
                        }
                    }
                    arr.unshift({ x, y })
                }
            },

            removeFood: function() {
                var food = document.getElementsByClassName('food')[0];
                food.remove();
            },
            score: function() {
                result.innerText = ++count;
            }
        }
        return new snake().init();
    });