使用JavaScript制作贪吃蛇

index.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">
    <title>贪吃蛇</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="map">

</div>


<script src="js/tool.js"></script>
<script src="js/food.js"></script>
<script src="js/snake.js"></script>
<script src="js/game.js"></script>
<script src="js/main.js"></script>
</body>
</html>

index.css代码如下

#map {
    width: 600px;
    height: 400px;
    background-color: #ccc;
    position: relative;
}

food.js代码如下

//自调函数 开启一个新的作用域,避免命名冲突
(function () {
    //局部作用域

//记录上一次创建的食物,为删除做准备
    var elements=[];
    var position = 'absolute';
//构造函数Food
    function Food(options) {
        options = options || {};
        this.color = options.color || 'green';

        this.width = options.width || 20;
        this.height = options.height || 20;
        //食物的位置
        this.x = options.x || 0;
        this.y = options.y || 0;
    }

//把食物渲染到map上
// prototype,每个函数都具有一个子对象prototype,prototype表示了该函数的原型
// prototype表示一个类属性的集合。通过new来生成一个类的对象时,prototype对象的属性就会变成实例化对象的属性
    Food.prototype.render = function (map) {
        //删除之前创建的食物
        remove();

        //动态创建div,显示页面上的食物
        var div = document.createElement('div');
        map.appendChild(div);

        elements.push(div);
        //随机生成食物
        this.x = Tool.getRandom(0,map.offsetWidth/this.width - 1)*this.width;
        this.y = Tool.getRandom(0,map.offsetHeight/this.height - 1)*this.height;

        //设置div样式
        div.style.position = position; //脱离文档流
        div.style.background = this.color;
        div.style.width = this.width + 'px';
        div.style.height = this.height + 'px';
        div.style.left = this.x + 'px';
        div.style.top = this.y + 'px';
    };

    function remove() {
        for (var i = elements.length-1;i >= 0;i-- ){
            //删除div
            elements[i].parentNode.removeChild(elements[i]);
            //删除数组元素
            elements.splice(i,1); //第一个参数,从哪个元素开始  第二个参数,删除几个元素
        }
    }
    //把Food构造函数 让外部可以访问
    window.Food = Food;
})()
//测试
// var map = document.getElementById('map');
// var food = new Food();  //这里的Food就是window.Food
// food.render(map);

snake.js代码如下

(function () {
    var position = 'absolute';
    //记录之前创建的蛇
    var elements = [];
    function Snake(options) {
        options = options || {};
        //蛇节的大小
        this.width = options.width || 20;
        this.height = options.height || 20;
        //蛇移动的方向
        this.direction = options.direction || 'right';
        //蛇身体(蛇节) 第一个元素是蛇头
        this.body = [
            {x: 5, y: 2, color: 'red'},
            {x: 4, y: 2, color: 'blue'},
            {x: 3, y: 2, color: 'blue'},
            {x: 2, y: 2, color: 'blue'},
            {x: 1, y: 2, color: 'blue'}
        ];
    }
    Snake.prototype.render = function (map) {
        //删除之前创建的蛇
        remove();
        //把每一蛇节渲染到地图上
        for (var i = 0,len = this.body.length; i<len; i++){
            //蛇节
            var object = this.body[i];
            var div = document.createElement('div');
            map.appendChild(div);

            //记录当前蛇
            elements.push(div);
            //设置样式
            div.style.position = position;
            div.style.width = this.width + 'px';
            div.style.height = this.height + 'px';
            div.style.left = object.x * this.width + 'px';
            div.style.top = object.y * this.height + 'px';
            div.style.backgroundColor = object.color;
        }
    }
    //控制蛇移动的方法
    Snake.prototype.move = function (food,map) {
        //控制蛇的身体移动 (当前蛇节 到 上一蛇节的位置)
        for (var i = this.body.length - 1;i > 0;i--){
            this.body[i].x = this.body[i - 1].x;
            this.body[i].y = this.body[i - 1].y;
        }
        //控制蛇头的移动
        //判断蛇移动的方向
        var head = this.body[0];
        switch (this.direction){
            case 'right':
                head.x += 1;
                break;
            case 'left':
                head.x -=1;
                break;
            case 'top':
                head.y -=1;
                break;
            case 'bottom':
                head.y +=1;
        }


        //2.4判断蛇头是否和食物重合
        var headX = head.x * this.width;
        var headY = head.y * this.height;
        if (headX === food.x && headY === food.y){
            //让蛇增加一节
            //获取蛇的最后一节
            var last = this.body[this.body.length - 1];
            this.body.push({
                x:last.x,
                y:last.y,
                color:last.color
            })
            //随机在地图上重新生成食物
            food.render(map);
        }
    }

    function remove() {
        for (var i = elements.length -1;i>= 0;i--){
            //删除div
            elements[i].parentNode.removeChild(elements[i]);
            //删除数组中的元素
            elements.splice(i,1);
        }
    }
    //暴露构造函数给外部
    window.Snake = Snake;
})()

//测试
// var map =document.getElementById('map');
// var sanke = new Snake();
// sanke.render(map);

game.js代码如下

//使用自调函数,创建一个新的局部作用域,防止命名冲突
(function () {
    function Game(map) {
        this.food = new Food();
        this.snake = new Snake();
        this.map = map;
        that=this;
    }
    Game.prototype.start = function () {
        //1.把蛇和食物对象渲染到地图上
        this.food.render(this.map);
        this.snake.render(this.map);
        //2.开始游戏逻辑
        //2.1 让蛇移动起来
        //2.2当蛇遇到边界游戏结束
        runSnake();
        //2.3通过键盘控制蛇移动的方向
        bindKey();
        //2.4当蛇遇到食物 做相应的处理
    }

    function bindKey() {
        document.onkeydown = function (e) {
            switch (e.keyCode){
                case 37:
                    if (that.snake.direction === 'right') return;
                    that.snake.direction = 'left';
                    break;
                case 38:
                    if (that.snake.direction === 'bottom') return;
                    that.snake.direction = 'top';
                    break;
                case 39:
                    if (that.snake.direction === 'left') return;
                    that.snake.direction = 'right';
                    break;
                case 40:
                    if (that.snake.direction === 'top') return;
                    that.snake.direction = 'bottom';
                    break;
            }
        }
    }

    //
    function runSnake() {
        var timerId = setInterval(function () {
            //让蛇走一格
            //在定时器中的function中this是指向window对象的
            that.snake.move(that.food,that.map);
            that.snake.render(that.map);

            //2.2当蛇遇到边界游戏结束

            var maxX = that.map.offsetWidth / that.snake.width;
            var maxY = that.map.offsetHeight / that.snake.height;
            //获取蛇头的坐标
            var headX = that.snake.body[0].x;
            var headY = that.snake.body[0].y;

            if (headX <0 || headX>=maxX){
                alert('Game Over');
                clearInterval(timerId);
            }
            if (headY <0 || headY >= maxY){
                alert('Game Over');
                clearInterval(timerId);
            }
            for (var i = that.snake.body.length - 1;i > 0;i--){
                if (headX == that.snake.body[i].x && headY == that.snake.body[i].y){
                    alert('Game Over');
                    clearInterval(timerId);
                    break;
                }
            }
        },300)
    }


    //暴露构造函数给外部
    window.Game = Game;
})()

// //测试
// var map =document.getElementById('map');
// var game = new Game(map);
// game.start();

main.js代码如下

(function () {
    var map =document.getElementById('map');
    var game = new Game(map);
    game.start();
})()

Tool.js代码如下

// 工具对象

(function () {
    var Tool = {
        getRandom: function (min, max) {
            min = Math.ceil(min);
            max = Math.floor(max);
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
    }
    window.Tool = Tool;
})()
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值