87,910
社区成员
发帖
与我相关
我的任务
分享
<html>
<head>
<style>
.unit{
width:20px;
height:20px;
position:absolute;
border:solid 1px black;
}
.backlayer{
width:600px;
height:600px;
border:solid 1px gray;
position:absolute;
margin:0px;
}
</style>
<script language="javascript">
var $$ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
var INISBODY=10; //身体初始长度
var Global=function(){ //单元格属性
this.WIDTH=30;
this.HEIGHT=30;
this.CELL_SIZE=20;
return this;
}
function fillRect(xpos,ypos,color){
var backlayer=$$("backlayer");
var obj=document.createElement("div");
obj.className="unit";
obj.style.top=600-ypos*(Global().CELL_SIZE);
obj.style.left=xpos*Global().CELL_SIZE;
obj.style.backgroundColor=color;
backlayer.appendChild(obj);
}
function LinkList(){ //模拟链表类
this.x=[];
this.y=[];
}
LinkList.prototype={
removeLast:function(){ //移除尾结点
var x=this.x.pop();
var y=this.y.pop();
return [x,y];
},
addFirst:function(ret){ //增加头结点
var x=[ret[0]];
var y=[ret[1]];
this.x=x.concat(this.x);
this.y=y.concat(this.y);
},
getFirst:function(){ //得到头结点
return [this.x[0],this.y[0]];
},
addLast:function(ret){ //增加尾结点
this.x.push(ret[0]);
this.y.push(ret[1]);
},
getLen:function(){ //得到结点长度
return this.x.length;
}
}
function Snake(){ //蛇身类
this._UP=1; //4个方向用数字来表示
this._DOWN=-1;
this._LEFT=2;
this._RIGHT=-2;
this._oldDirection=''; //前次移动方向
this._newDirection=''; //新移动方向
this._body=new LinkList(); //蛇身体数据结构
this.onInit();
}
Snake.prototype={
onInit:function(){ //初始化,蛇在正中间
var x = Global().WIDTH / 2;
var y = Global().HEIGHT / 2;
for (var bodyno = 0; bodyno < INISBODY; bodyno++) {
this._body.addLast([x - bodyno, y]);
}
this._oldDirection = this._newDirection = this._RIGHT;
this._life=true;//生命,碰到墙壁或者自身都判定为死(false);
},
move:function() { //按方向移动身体,用数据结构来表示就是:增加头结点,移除尾结点
if (!(this._oldDirection + this._newDirection == 0)) {//如果和上一次方向相反的话不做任何动作
this._oldDirection = this._newDirection;
}
this._oldTail=this._body.removeLast();
var x = this._body.getFirst()[0];
var y = this._body.getFirst()[1];
switch (this._oldDirection) {
case this._DOWN:
y--;
if (y <=0) {
this._life=false;
}
break;
case this._UP:
y++;
if (y > Global().HEIGHT) {
this._life=false;
}
break;
case this._LEFT:
x--;
if (x < 0) {
this._life=false;
}
break;
case this._RIGHT:
x++;
if (x >= Global().WIDTH) {
this._life=false;
}
break;
}
var newhead = [x, y];
this._body.addFirst(newhead);
},
changeDirect:function(direction) { //转换方向
this._newDirection = direction;
},
eatFood:function() {
this._body.addLast(this._oldTail);
},
getHead:function(){
return this._body.getFirst();
},
onDraw:function() { //画出单元格结点所在位置,就是蛇身
for(var bodyno=0;bodyno< this._body.getLen(); bodyno++){
fillRect(this._body.x[bodyno],this._body.y[bodyno],"blue");
}
},
isEatBody:function(){ //判断是否吃到身体
var isEat=false;
for(var bodyno=1;bodyno< this._body.getLen(); bodyno++){
if((this._body.x[bodyno]==this.getHead()[0])&&(this._body.y[bodyno]==this.getHead()[1])){
isEat=true;
};
}
return isEat;
},
isInBody:function(point){ //判断某点是否在身体内,主要是避免产生的食物点在蛇身内
var isIn=false;
for(var bodyno=0;bodyno< this._body.getLen(); bodyno++){
if((this._body.x[bodyno]==point[0])&&(this._body.y[bodyno]==point[1])){
isIn=true;
};
}
return isIn;
},
isEatGround:function(){//是否撞到墙壁死
return !this._life;
}
}
function Food(){ //食物类
this.x=0;
this.y=0;
}
Food.prototype={
onDraw:function() {
fillRect(this.x,this.y,"red");
},
isSnakeEatFood:function(snake) { //判断蛇是否吃到食物,用蛇头点坐标和食物坐标位置判断
return (this.x==snake.getHead()[0]&&this.y==snake.getHead()[1]);
},
setLocation:function(point){ //设置食物所在位置
this.x=point[0];
this.y=point[1];
}
}
function Controller(){
this.snake=new Snake();
this.food=new Food();
}
Controller.prototype={ //控制器类,用来对上面几个对象进行操控,对外进行事件监听
newGame:function(){
var point=this.getFoodLocation();
this.food.setLocation(point);
this.run();
},
changeDirect:function(direction){
this.snake.changeDirect(direction);
},
getFoodLocation:function(){ //随机获得食物位置,while作用是避免食物出现在蛇身内
var point=[];
point[0]=parseInt(Math.random()*Global().WIDTH);
point[1]=parseInt(Math.random()*Global().HEIGHT)+1;
while(this.snake.isInBody(point)){
point[0]=parseInt(Math.random()*Global().WIDTH);
point[1]=parseInt(Math.random()*Global().HEIGHT)+1;
}
return point;
},
run:function(){
this.snake.move();
if(this.food.isSnakeEatFood(this.snake)){
this.snake.eatFood();
var point=this.getFoodLocation();
this.food.setLocation(point);
}
if(this.snake.isEatGround()||(this.snake.isEatBody())){
clearTimeout(this._timer);
$$("gameover").style.display="block"
return;
}
$$("backlayer").innerHTML='';
this.snake.onDraw();
this.food.onDraw();
this._timer=setTimeout('game.run()',100);
}
}
var game;
window.onload=function(){
game=new Controller();
game.newGame();
document.onkeydown= function(){
var e=window.event||arguments[0];
var code=e.keyCode;
var dire=(code==37&&2)||(code==38&&1)||(code==39&&-2)||(code==40&&-1);
game.changeDirect(dire);
}
}
</script>
</head>
<body>
<div class="backlayer" id="backlayer"></div>
<div id="gameover" style="position:absolute;left:300px;top:300px;display:none;font-size:30px">Game Over</div>
</body>
</html>