贪吃蛇游戏相信各位读者都玩过,本系列文章将解析贪吃蛇游戏的算法及其在JavaScript语言中的实现. 首先回忆一下我们玩过的贪吃蛇游戏,它是由三个部分组成的:蛇,食物,背景.其中背景在实际的算法中只起装饰性的作用,所以我将背景替代为另一个词”场景”,下面将这三个部分拆分开来讲解,逐个完成我们的贪吃蛇算法.
场景
要完成贪吃蛇游戏,首先要给贪吃蛇一个活动的空间,这个活动的空间,就是”场景”.
贪吃蛇游戏中的世界是一个二维的世界,而二维平面通常使用网格来进行区分,所以我们创建一个名为World的静态类,为这个世界设定大小以确定其边界.
var World={
Size:{
width:20,
height:20
}
}
这样我们就创造了一个大小为20×20的空间,这是在游戏中贪吃蛇可以进行活动的区域.
食物
食物是游戏的目标,它是随机生成在世界上的,所以我们干脆把食物放进World类.
食物有2个坐标属性和1个用于生成食物坐标的方法.
Food:{
x:undefined,
y:undefined,
generate:function(){}
}
蛇
在贪吃蛇游戏的规则中,蛇被以下几个规则约束:
蛇头不能咬到蛇身,咬到则游戏结束.
蛇撞到墙壁会死,撞到则游戏结束.
蛇只能朝三个方向移动,不能直接调头.
蛇吃掉食物后蛇身会变长.
蛇身随着蛇头的轨迹进行移动.
这几个规则都围绕着蛇本身展开,其中还有2个规则是造成游戏结束的,显然我们需要使用面向对象编程来设计代码.我们将蛇头和蛇身视为两个对象,创建一个Snake类,在Snake类中创建Head类和Body类.
function Snake(){
function Head(){}
function Body(){}
this.body=new Body();
this.head=new Head();
}
var snake=new Snake();
蛇头
蛇头应该包含一个坐标属性,说明蛇头的位置,所以我们给Head类添加上x和y属性,并赋予它们初始值,x和y应该对应于World中所规划出的空间.
this.x=9;
this.y=9;
我们知道,如果你不控制贪吃蛇的方向,贪吃蛇会自动向蛇头所在的方向前进,蛇头的方向也是你最后一次控制贪吃蛇时的方向.所以我们再给蛇头添加direction属性,由于最开始蛇的方向未知,我们给它赋予undefined的初始值(在JavaScript中,如果不给变量赋值,初始值即为undefined,此处是为了突出蛇头朝向的未知性).
this.direction=undefined;
除了这3个属性,蛇头还应该有2个动作:move和eat,分别完成”移动”和”吃”.
this.move=function(){};
this.eat=function(){};
2个游戏结束的判断:hitCheck和eatSelfCheck,分别用来判断”撞墙”和”自食”.
this.hitCheck=function(){};
this.eatSelfCheck=function(){};
至此蛇头可能需要用到的元素都已经定义完毕了.
蛇身
蛇身相对于蛇头来说,结构要简单一点.
存储蛇身部分坐标的数组part:
this.part=[];
完成蛇身移动的动作move:
this.move=function(){};
完成蛇身增长的动作increase:
this.increase=function(){};
Next
现在,我们的代码是这样的,虽然各部分功能还没有完成,但看起来总算还是有些条理.
var World={
Size:{
width:20,
height:20
}
Food:{
x:undefined,
y:undefined,
generate:function(){}
}
}
function Snake(){
function Head(){
this.x=9;
this.y=9;
this.direction=undefined;
this.move=function(){};
this.eat=function(){};
this.hitCheck=function(){};
this.eatSelfCheck=function(){};
}
function Body(){
this.part=[];
this.move=function(){};
this.increase=function(){};
}
this.body=new Body();
this.head=new Head();
}
var snake=new Snake();
在下一章中,将完成Head类.