小型贪吃蛇游戏(有小bug)

本文详细介绍了使用HTML、CSS和JavaScript实现贪吃蛇游戏的过程,包括游戏构造函数、蛇和食物的构造函数,以及如何控制蛇的移动、食物的生成和游戏的运行机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<body>
    <button class="start">开始游戏</button>
    <button class="stop">暂停游戏</button>
    <button class="reset">重置游戏</button>
    <div class="map"></div>
    <script>
        /*实现贪吃蛇效果
        *1.先将贪吃蛇游戏整体看成是一个构造函数(类)
        *   贪吃蛇游戏所具备的属性以及方法有:
        *       属性:?和蛇的食物
        *       
        *2.蛇可以看成是一个对象,构造函数(类)
        *   蛇所具备的属性以及方法有:
        *       属性:  a.如果蛇想要移动,则得有可以移动的属性也就是身体
        *               b.如果蛇想要去吃东西,那么就得有属性头:使蛇头能够与食物所在的坐标重合,就可以实现吃东西的效果了
        *               c.还有蛇头以及蛇的身体的图片属性
        *       方法:  a.蛇的移动方法:为了能够让蛇在规定的范围内可以移动
        *               b.蛇的转向方法:为了让蛇能够在用户点击上下左右键的时候,蛇头能够直接改变其所在的转向
        *               
        *3.食物可以看成是一个构造函数(类)
        *   食物所具备的属性以及方法有:
        *       属性:只有一个:食物的图片属性;没有方法:因为在此游戏中食物只有一个而且还是在规定范围内的随机的位置,所以此方法应该是游戏的方法
        */
        // 先定义游戏的构造函数
        // 只有获取到了map元素,才能让图片上树,否则看不到情况:由于是让蛇的图片进行上树,那么就得给蛇添加属性

        // 获取元素
        var start = document.querySelector(".start");
        var stop = document.querySelector(".stop");
        var reset = document.querySelector(".reset");
        // 给其分别添加点击事件
        start.onclick = function(){
            // 开始游戏需要判定信号量
            if(game.flex){
                return;
            }
            game.start();
        }
        stop.onclick = function(){
            game.stop();
        }
        reset.onclick = function(){
            game.reset();
        }

        function Game(snake,food,map){
            this.snake = snake;
            this.food = food;
            this.map = map;
            this.timer = null;
            // 设置行列
            this.row = 30;
            this.column = 40;
            // 设置游戏的开关
            this.flex = true;
            // 设置食物的坐标,随机坐标
            this.foodX = parseInt(Math.random() * this.column);
            this.foodY = parseInt(Math.random() * this.row);
            // 给整个游戏设置一个初始化函数,调用该函数
            this.init();
        }
        // 在蛇将该创建的元素都已经创建好了之后就要将这些元素进行上树
        // 定义Game的构造函数的原型方法
        // 运用的是第二种方法:直接重定义Game的原型对象
        Game.prototype = {
            constructor:Game,
            // 使创建的元素进行上树操作,定义渲染方法
            renderSnake:function(){
                // console.log(this);
                for(let i = 0;i < this.snake.bodyArr.length;i++){
                    this.map.appendChild(this.snake.bodyEleArr[i]);
                }
            },
             // 设置一个定时器,因为后面结束游戏需要关闭定时器,所以需要一个变量来保存计数器
            //  因为设置定时器是为了能够让游戏开始,蛇进行移动,所以给整个game来设置方法
            start:function(){
                // console.log(this);
                // 游戏开始
                this.flex = true;
                // 定时器的this指向永远指向window
                this.timer = setInterval(function(){
                // 此时,要想用定时器rang蛇进行移动,那么就必须是将newHead的位置传入数组中的同时,渲染其样式
                this.snake.forword();
                // 每当蛇移动一次就要检测边界一次
                this.check();
                // 同时进行判断,来判断游戏是否开始,防止游戏已经结束了还在渲染
                if(this.flex){
                    this.snake.render();
                }
                }.bind(this),500);
            },
            // 再给游戏添加一个游戏结束的方法
            stop:function(){
                // 关闭开关
                this.flex = false;
                // 关闭定时器
                clearInterval(this.timer);
            },
            // 边界判定以及判断蛇头与食物是否重合
            check: function(){
                // 要想判定蛇头是否出边界,先要获取到蛇头的位置
                 var headX = this.snake.bodyArr[this.snake.bodyArr.length - 1].x;
                 var headY = this.snake.bodyArr[this.snake.bodyArr.length - 1].y;
                    // 进行边界判定,由于是x是从0开始,所以最后一个是39和29
                if(headX < 0 || headX > this.column - 1 || headY < 0 || headY > this.row - 1){
                    this.stop();
                }
                // 判断蛇头与食物是否重合,只要重合就让蛇的身体长长一个,食物的位置重置
                if(headX === this.foodX && headY === this.foodY){
                    //食物和蛇头重合的话,就蛇的身体生长,食物的位置重置以及各自的渲染
                    this.snake.growUp();
                    this.renderSnake();
                    this.foodReset();
                    this.renderFood();
                }
            },
            // 给整个游戏设置一个初始化游戏的方法
            init:function(){
                // 渲染蛇,渲染食物
                this.renderSnake();
                this.renderFood();
                // 条用事件函数
                this.bindEvent();
            },
            // 在设置一个方法,用于让用户输入键盘上的上下左右键来控制蛇的移动方向
            // 绑定事件
            bindEvent:function(){
                var _this = this;
                // 设置键盘输入事件:键盘按下事件
                document.onkeydown = function(e){
                    // 兼容性
                    var e = window.e || e;
                    var code = e.keyCode;
                    console.log(code);
                    // 利用keycode:获取字符的acsii码值进行判断
                    if(code === 37){
                        // 由于此时的this指向的是document,所以要有一个变量来保存前面的this
                        // 此时通过判断来改变蛇头的方向
                        _this.snake.changeDirection("left");
                    }else if(code === 38){
                        _this.snake.changeDirection("up");
                    }else if(code === 39){
                        _this.snake.changeDirection("right");
                    }else if(code === 40){
                        _this.snake.changeDirection("down");
                    }

                }
            },
            // 要想让食物渲染在整个游戏的空间里的任何一个地方,那么就要让食物在整个游戏中任意出现
            renderFood:function(){
                // 渲染完样式之后,在让其上树
                this.map.appendChild(this.food.ele);
                // 在整个游戏中设置其位置,随机
                this.food.ele.style.left =this.foodX * 20 + "px";
                this.food.ele.style.top =this.foodY * 20 + "px";
            } ,
            
            // 食物重置
            foodReset:function(){
                // 更新食物的坐标,先要创建食物的坐标
                this.foodX = parseInt(Math.random() * this.column);
                this.foodY = parseInt(Math.random() * this.row);
            },
            // 事件重置,蛇重置,食物也要重置
            reset:function(){
                
                console.log(code);
                // 先让原先的蛇下树
                for(let i = 0;i < this.snake.bodyEleArr.length;i++){
                    this.snake.bodyEleArr[i].remove();
                }
                // 然后重置
                this.snake.reset();
                // 渲染新的蛇
                this.renderSnake();
            }
        }

        // 定义蛇的构造函数
        function Snake(headImg,bodyImg){
            this.headImg = headImg;
            this.bodyImg = bodyImg;
            // 给蛇一开始设置身体加上头部的长度
            this.bodyArr = [{x: 0,y: 0},{x: 1,y: 0}];
            // 给蛇添加属性,使其能够让蛇一开始的身体不管有多少个都能够创建元素
            // 用数组的map映射方法,用来将该数组中的任何一个都能够创建元素
            this.bodyEleArr = this.bodyArr.map( function(){
                return document.createElement("div");
            });
            // 给蛇的身体与头部添加width和height,常量不用传值
            this.stepX = 20;
            this.stepY = 20;
            // 设置蛇头移动的方向:默认为向右
            this.dirction = "right";
        }
        // 定义蛇的构造函数的原型方法
        // 运用的是第二种方法:直接重定义蛇的原型对象
        Snake.prototype = {
            constructor:Snake,
            // 定义蛇的渲染方法,让其具有样式
            render:function(){
                // 将蛇的身体与头部分开,先给身体设置样式,因为长度不固定,所以要用到for循环
                // 数组的前面都是身体,最后一个是头部
                for(let i = 0;i < this.bodyArr.length - 1;i++){
                    // 给蛇的身体添加样式
                    this.bodyEleArr[i].style.backgroundImage = "url(" + this.bodyImg + ")";
                    this.bodyEleArr[i].style.width = this.stepX + "px";
                    this.bodyEleArr[i].style.height = this.stepY + "px";
                    this.bodyEleArr[i].style.position = "absolute";
                    this.bodyEleArr[i].style.left = this.bodyArr[i].x * this.stepX + "px";
                    this.bodyEleArr[i].style.top = this.bodyArr[i].y * this.stepY + "px";
                }
                // 给蛇的头部添加样式
                this.bodyEleArr[this.bodyArr.length - 1].style.backgroundImage = "url(" + this.headImg + ")";
                this.bodyEleArr[this.bodyArr.length - 1].style.width = this.stepX + "px";
                this.bodyEleArr[this.bodyArr.length - 1].style.height = this.stepY + "px";
                this.bodyEleArr[this.bodyArr.length - 1].style.position = "absolute";
                this.bodyEleArr[this.bodyArr.length - 1].style.left = this.bodyArr[this.bodyArr.length - 1].x * this.stepX + "px";
                this.bodyEleArr[this.bodyArr.length - 1].style.top = this.bodyArr[this.bodyArr.length - 1].y * this.stepY + "px";
            },
            // 定义蛇的前进的方法
            forword:function(){
                // 在同一个方向上移动位置
                // 是将蛇的尾巴砍下,让头部往前进一步
                // 先将尾巴砍下,数组
                this.bodyArr.shift();
                // 在给蛇的头部设置一个新的位置,在此基础上先要判断蛇移动的方向是如何
                //获取旧的头部位置
                var oldHead = this.bodyArr[this.bodyArr.length - 1];
                // 定义一个新的头部位置
                var newHead = {
                    x: oldHead.x,
                    y: oldHead.y
                }
                if(this.dirction === "left"){
                    newHead.x--;
                }else if(this.dirction === "right"){
                    newHead.x++;
                }else if(this.dirction === "up"){
                    newHead.y--;
                }else if(this.dirction === "down"){
                    newHead.y++;
                }
                //要想移动就得将其放入数组中,才能上树
                this.bodyArr.push(newHead);

            },
            // 定义一个蛇头改变方向的方法
            changeDirection:function(dirction){
                // 用dirction来改变方向
                this.dirction = dirction;
            },
            // 定义蛇的生长函数
            growUp:function(){
                // 想让蛇长大,那么就必须让身体多一个,直接在数组的头部添加一个
                this.bodyArr.unshift(this.bodyArr[this.bodyArr.length - 1]);
                // 添加完成之后就要创建其元素
                this.bodyEleArr.unshift(document.createElement("div"));
            },
            // 蛇的重置
            reset:function(){
                // 蛇的重置就是将一开始的状态再写一遍
                // 给蛇一开始设置身体加上头部的长度
                this.bodyArr = [{x: 0,y: 0},{x: 1,y: 0}];
                // 给蛇添加属性,使其能够让蛇一开始的身体不管有多少个都能够创建元素
                // 用数组的map映射方法,用来将该数组中的任何一个都能够创建元素
                this.bodyEleArr = this.bodyArr.map( function(){
                    return document.createElement("div");
                });
                //当蛇重置好就要给他渲染样式
                this.render();
            }
        }


        // 定义食物的构造函数
        function Food(foodImg){
            this.foodImg = foodImg;
            // 在此创建元素
            this.ele = document.createElement("div");
        }

        // 给食物设置食物的原型对象
        Food.prototype = {
            constructor:Food,
            // 给食物添加方法
            // 食物的渲染方法:要想要渲染,则必须将其创建出来
            render:function(){
                this.ele.style.position = "absolute";
                this.ele.style.width = 20 + "px";
                this.ele.style.height = 20 + "px";
                this.ele.style.backgroundImage = "url(" + this.foodImg + ")";
            }
        }

        // 定义一个蛇对象
        var snake = new Snake("./imgs/head.png","./imgs/body.png");
        // 调用蛇的渲染方法
        snake.render();
        // 定义食物对象
        var food = new Food("./imgs/food.png");
        food.render();

        // 获取到map元素
        var map = document.querySelector(".map");

        // 定义一个游戏的对象并进行传参
        var game = new Game(snake,food,map);
    </script>
</body>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值