JavaScript实现的贪吃蛇算法及其研究(三)

内容接上一章JavaScript实现的贪吃蛇算法及其研究(二).

我们已经大致完成了Head类,接下来我们需要完成Body类,让蛇身跟随蛇头进行运动.

Body类现在是这样的:

function Body(){  
    this.part=[];
    this.move=function(){};
    this.increase=function(){};
}

Body.part是用于储存蛇身数据的数组,其内容为JSON对象,格式如下:

{
    x:value,
    y:value
}

在上一章中,Head类中调用的Body.move和Body.increase方法都带有一个head参数,所以我们也在这里给方法加上head参数.现在Body类是这样的:

function Body(){  
    this.part=[];
    this.move=function(head){

    };
    this.increase=function(head){

    };
}

increase方法

想一下我们玩过的贪吃蛇游戏,在蛇吃掉食物时,身体会增长一段,这时蛇身的尾巴部分就作为那增长的一段而没有移动位置,这就是增长的效果了.

在调用increase方法时,蛇头已经进行了移动,蛇头原来的位置目前是空的,这是蛇移动后身体最开始一段应该所在的位置,我们需要将它用蛇头原来的坐标数据填上.

this.part.unshift(head);  

head参数的数据已经是标准的part数据,所以直接用unshift方法将head移进数组的第一个元素即可.

move方法

move方法的思路与increase方法一致,区别在于move方法会移除part数组的最后一个元素,可以用pop方法简单实现,代码如下:

this.part.pop();  
this.increase(head);  

在这里直接调用了increase方法完成向前移动的任务,也可以用unshift替代那行代码.

这段代码实际上还存在一个逻辑上的缺陷,即当part的length为0时,会由于unshift增加一个元素,导致即使蛇头不吃食物,也会自动出现一个蛇身的情况.解决这个问题我们只需要加上一条判断:

if(this.part.length>0){  
    this.part.pop();
    this.increase(head);
}

Next

到目前为止,关于蛇的相关内容已经彻底结束了,蛇已经可以作为一个对象进行移动,进食等运动.代码也增长到了99行:

var World={  
    Size:{
        width:20,
        height:20
    }
    Food:{
        x:undefined,
        y:undefined,
        generate:function(){}
    }
}

var Direction={  
    up:1,
    right:2,
    down:-1,
    left:-2
};

function Snake(){  
    var self=this;

    function Head(){
        this.x=9;
        this.y=9;
        this.direction=undefined;
        this.move=function(direction){
            var head={
                x:this.x,
                y:this.y
            };
            if(direction+this.direction==0){
                direction=this.direction;
            }
            this.direction=direction;
            switch(direction){
                case Direction.up:
                    this.y--;
                    break;
                case Direction.right:
                    this.x++;
                    break;
                case Direction.down:
                    this.y++;
                    break;
                case Direction.left:
                    this.x--;
            }
            if(eat(this.x,this.y)){
                self.body.increase(head);
                World.Food.generate();
            }else   if(hitCheck(this.x,this.y) || eatSelfCheck(this.x,this.y)){

            }else{
                self.body.move(head);
            }
        };
        function eat(x,y){
            if(x==World.Food.x && y==World.Food.y){
                return true;
            }else{
                return false;
            }
        }
        function hitCheck(x,y){
            if(x<0 || y<0 || x==World.Size.width || y==World.Size.height){
                return true;
            }else{
                return false;
            }
        }
        function eatSelfCheck(x,y){
            var part=self.body.part;
            for(var i=part.length;i--;){
                if(x==part[i].x && y==part[i].y){
                    return true;
                }
            }
            return false;
        }
    }

    function Body(){
        this.part=[];
        this.move=function(head){
            if(this.part.length>0){
                this.part.pop();
                this.increase(head);
            }
        };
        this.increase=function(head){
            this.part.unshift(head);
        };
    }

    this.body=new Body();
    this.head=new Head();
}
var snake=new Snake();  

在下一章中,将完成食物的生成算法.

JavaScript实现的贪吃蛇算法及其研究(四)