JS案例----贪吃蛇(源码)

由于我笔记本键盘原因,为了方便我操作,将上下左右方向键设置为英文字母 I K J L 

可以自己在document.onkeydown中自行修改.这篇内容是纯代码篇

分析的篇章会在后面发.

注:仅简单实现基础游戏功能,存在部分bug.功能并不完善

<!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>
    <script>
        //要素: 地图  食物  蛇?
        //步骤1:封装一个地图类
            //地图的   背景  宽  高  定位:父相子绝
        function Map(){
            this.width = "1600px";
            this.height = "800px";
            this.backgroundColor = "#ebf1dd";
            this.position = "relative";
            //用一个属性来保存div的值,以便于后面被调用
            this._map = null;

            //步骤1.1:封装一个显示地图类
            this.show = function(){
                //创建一个div
                this._map = document.createElement("div");
                this._map.style.width = this.width;
                this._map.style.height = this.height;
                this._map.style.backgroundColor = this.backgroundColor;
                this._map.style.position = this.position;
                //将this._map挂载到 body中
                document.body.appendChild(this._map);
            }
        }
        //实例化地图类
        var map = new Map();
//***********************************************************************************
        //步骤2:封装一个食物类
//***********************************************************************************
        function Food(){
            this.width = "20px";
            this.height = "20px";
            this.backgroundColor = "#e5b9b7";
            this.position = "absolute";
            this.borderRadius = "100%";

            this.left = 0; //初始化x坐标
            this.top = 0; //初始化y坐标

            //用一个属性来保存div的值,以便于后面被调用
            this._food = null;

            //步骤1.1:封装一个显示食物方法
            this.show = function(){
                //步骤3.1:判断this._food,阻止重复显示食物
                if(!this._food){
                    //创建一个div
                    this._food = document.createElement("div");
                    this._food.style.width = this.width;
                    this._food.style.height = this.height;
                    this._food.style.backgroundColor = this.backgroundColor;
                    this._food.style.position = this.position;
                    this._food.style.borderRadius = this.borderRadius;
                    
                    //将this._food追加到 map._map中,即:挂载到背景图的div中
                    map._map.appendChild(this._food);  
                }

                //调用随机数方法,随机获取(x,y)坐标值
                this.randPos();

                //定义食物出现的坐标(x,y)
                this._food.style.left = this.left*20+"px";
                this._food.style.top = this.top*20+"px";
            }
            //步骤2.1封装一个随机数方法
            this.randPos = function(){
                this.left = Math.floor(Math.random()*80);
                this.top = Math.floor(Math.random()*40);
            }
        }
        //实例化食物类
        var food = new Food();
//***********************************************************************************
        //步骤3:定义蛇类
//***********************************************************************************
        function Snake(){
            this.width = "20px";
            this.height = "20px";
            this.position = "absolute";
            this.borderRadius = "100%";
            //定义蛇身体,是个二维数组
            //在设置完移动后,回来添加一个数组值:null,管理自身的部分
            this.body = [[25,20,"#ffc000",null],[24,20,"#fbd5b5",null],[23,20,"#fbd5b5",null]];

            //封装显示蛇的方法
            this.show = function(){
                //因为蛇身体是一个二维数组,所以用for...of循环遍历
                for(var i of this.body){
                    //判断是否已创建蛇身,不再重复生成
                    if(!i[3]){
                        i[3] = document.createElement("div");
                        i[3].style.width = this.width;
                        i[3].style.height = this.height;
                        i[3].style.position = this.position;
                        i[3].style.borderRadius = this.borderRadius;
                        i[3].style.backgroundColor = i[2];
                        //将创建的蛇身体div 挂载到 map 的div中
                        map._map.appendChild(i[3]);
                    }
                    i[3].style.left = i[0] * 20 + "px";
                    i[3].style.top = i[1] * 20 + "px";
                    
                }
            }

            //添加运动方向的属性,默认不动
            this.direct = null;

            //封装蛇运动的方法
            this.move = function(){
                //处理蛇尾移动
                //获取蛇身数组,蛇身移动时,末尾一个的坐标等于前一个的坐标
                // 即将尾坐标替换成它的前一个坐标

                //判断,当蛇头不动时,即this.direct 为 false,则不执行蛇尾的移动
                if(this.direct){
                    for(var i=this.body.length-1;i>0;i--){
                    this.body[i][0] = this.body[i-1][0]; //替换x坐标
                    this.body[i][1] = this.body[i-1][1]; //替换y坐标
                    }
                }
                
                //处理蛇头移动
                switch (this.direct) {
                    case "up":
                        this.body[0][1] -= 1;  
                        break;
                    case "down":
                        this.body[0][1] += 1;  
                        break;
                    case "left":
                        this.body[0][0] -= 1;  
                        break;
                    case "right":
                        this.body[0][0] += 1;  
                        break;
                }
                //蛇运动后,要重新显示,所以调用this.show()方法

                //判断如果出界,则不再调用这个方法
                if(!(this.body[0][0] < 0 || this.body[0][0] > 79 || this.body[0][1] < 0 || this.body[0][1] > 39)){
                    this.show();
                }
            }
            
            //封装蛇吃食物的方法
            this.eat = function(){
                //当食物生成在蛇身体内时,自动吃掉,积分增加
                //循环变量蛇身的所有坐标,判断是否等于食物的坐标
                
                if(this.body[0][0] == food.left && this.body[0][1] == food.top){
                    //坐标相等表示吃到了
                    //食物刷新
                    food.show()
                    //每吃一个食物,加十分.
                    score += 10;

                    //蛇身长度加一个单位
                    //注意:新的蛇身部分的坐标值,只要不出现在地图中,设置为几都无所谓
                    //原因:因为当蛇移动时,末尾的蛇身的坐标会等于前一个蛇身的坐标,所以马上会更新到贪吃蛇的尾部
                    this.body.push([-10,-10,"#fbd5b5",null]);
                }   

            }

            //封装蛇出界的方法
            this.outLine = function(){
                if(this.body[0][0] < 0 || this.body[0][0] > 79 || this.body[0][1] < 0 || this.body[0][1] > 39){
                    //坐标出界,游戏结束
                    //停止运动,即:停止定时器,使蛇不再动,并提示Game Over
                    clearInterval(id);
                    alert("不撞南墙不回头!");
                    alert("游戏结束,总得分:"+score+"分");
                }
            }

            //封装蛇追尾的方法
            this.eatSelf = function(){
                for(var i=4;i<this.body.length;i++){
                    if(this.body[0][0] == this.body[i][0] && this.body[0][1] == this.body[i][1]){
                        //蛇头坐标等于蛇身的坐标,表示吃到自己,游戏结束
                        clearInterval(id);
                        alert("撞到自己了!");
                        alert("游戏结束."+"总得分:"+score+"分");
                    }
                }
            }
        }
        //实例化蛇类
        var snake = new Snake();
        
//***********************************************************************************
        //从这里开始执行
//***********************************************************************************
        //定义全局积分变量,并初始化值为0
        var score = 0;
        window.onload = open;
        function open(){
            //设置一个h1标签计分
            var h1 = document.getElementsByTagName("h1");
            //调用地图类的show()方法
            map.show();
            //调用食物类的show()方法
            food.show();
            //调用蛇类的show()方法
            snake.show();
            //小技巧:设置一个函数,将snake.move()放入函数内,此时,move()方法的调用者就是snake了
            function run(){
                snake.eat();
                snake.outLine();
                snake.eatSelf();
                snake.move();
                h1[0].innerHTML = "游戏积分: <font color=red>"+score+"</font> 分" ;  
            }
            //设置定时器调用蛇类的move()方法,让蛇一直动
            id = setInterval(run,60);
            //绑定键盘事件,控制蛇移动的方向,同时判断,不允许蛇回头
            document.onkeydown = function(event){
                switch (event.keyCode) {
                    
                    case 73:
                        if(snake.direct != "down"){
                            snake.direct = "up";
                        }
                        break;
                    case 75:
                        if(snake.direct != "up"){
                            snake.direct = "down";
                        }
                        break;
                    case 74:
                        if(snake.direct != "right"){
                            snake.direct = "left";
                        }
                        break;
                    case 76:
                        if(snake.direct != "left"){
                            snake.direct = "right";
                        }
                        break;
                    case 32:
                        if(confirm("是否提前结束游戏?")){
                            clearInterval(id);
                            alert("游戏结束!")
                            alert("总得分:"+score+"分");
                        }
                        break;
                }
            }   
        }
    </script>
</head>
<body>
    <h1></h1>
</body>
</html>

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值