自己修改的一个贪吃蛇的小游戏,请大家评评
很久以前,在学习JavaScript的时候,发现了网上有很多小游戏。对其中的贪吃蛇这个小游戏很感兴趣,就上网查询了一下。参考了一下“海浪 2005-8-15 贪吃蛇”这个版本的编写思路。重新整理的一下。请大家给点参考一下,特别是针对键盘控制这块,如何在游戏结束的时候,能够取消对键盘的控制呢?或者说是恢复原来的状态,然后再次点击开始的时候,还能够复原对键盘的控制。这个是我现在这个程序的一个小毛病,还没有找到解决办法。下面是源程序,我加注了很多注解,主要是给自己将来看的。
代码中用了jQuery这个框架,对dom的操作简便了不少。
这个论坛没有看到贴附件的选项呀!!
程序代码:/**
* @author 赵兵。感觉非常喜欢JavaScript的变量函数的概念,很好用
* 现在的问题好像就是对于键盘的绑定问题啦,如果游戏结束,如何清楚对键盘的绑定,以免作弊现象呢?这个还需要做进一步的完善。
*/
var game={};//这是唯一可见的命名空间,也就是说除了这个别的都隐藏了
(function(){//采用匿名函数的方式,将下面的对象和程序进行隐藏
var option={x:25,y:20}//地图的大小
var symbol={wall:"■",
inter:" ",
snake:"○",
head:"●",
food:"◎"
}//使用 lambda表达式来表示数组?其实就是一种特殊的数据结构,很好用的数据结构
game.status=['TBD',0];//有四种状态:playing,stop,dead,TBD,第二个参数是记录一次游戏中的死亡次数的,这是由于死亡以后,还以通过键盘来控制小蛇的运行方向,所以还有可以作弊的机会,但是死亡次数记录在第二个参数中
game.play=function(){
game.gott=game.gott || setInterval("game.play()",180);//很喜欢这种变量赋值的表达
var go = snake.go(); //小蛇开始运行
//game.snake=snake.bo();//测试用
//game.map=map.bo();//测试用
game.status[0]="playing";
switch(go){
case "dead":
clearInterval(game.gott); //判断游戏是否结束
game.gott=null;
game.status[0]="dead";
game.status[1]+=1;
alert("Game is Over!"); break;
case "ok":
break;
}
map.write();//将地图更新到html上
$("#status").html(game.status.join(","));//将测试的
}
game.start=function(){//游戏初始化
map.init(option.x,option.y);
snake.init();
food.init();
$(document).keydown(function(e){game.ctrl(e);});//键盘控制的了解,还是太少了,不过可以看出来,这是需要传递一个参数的。如何能够取消键盘的控制看来还得去思考一下才好呀。这个函数到底是什么意思呢?如何将这种绑定取消呢?
game.play();
$("#dir").html('右');//显示默认的方向
}
game.resume=function(){
game.gott=game.gott || setInterval("game.play()",180);
}
game.stop=function(){
clearInterval(game.gott);
game.gott=null;
game.status[0]="stop";
//取消键盘的绑定还是需要做进一步的修改的
map.write();//将地图更新到html上
$("#status").html(game.status.join(","));//将测试的
}
game.ctrl=function(e)//键盘控制函数
{
switch (e.keyCode)
{
case 38: snake.chdir(0); break;
case 39: snake.chdir(1); break;
case 40: snake.chdir(2); break;
case 37: snake.chdir(3); break;
case 83: game.stop();break;//这个快捷键的设置好像有点问题 s
case 71: game.resume();break; //g 继续
}
}
var map=function(x,y){//地图对象
//这里主要是一些公共变脸的申请与地图的初始化
var sq = symbol.wall;//边界符号
var sk = symbol.inter;//空白符号
var marr = [];
for(var iy=0; iy<y; iy++){
marr[iy] = [];
for(var ix=0; ix<x; ix++)marr[iy][ix] = (ix==0||iy==0||ix==x-1||iy==y-1)?sq:sk; //地图数组的初始化
}
return {
x:x,
y:y,
init:function(x,y){//地图数组的初始化
map.x=x;
map.y=y;
for(var iy=0; iy<y; iy++){
marr[iy] = [];
for(var ix=0; ix<x; ix++)marr[iy][ix] = (ix==0||iy==0||ix==x-1||iy==y-1)?sq:sk;
}
},
bo:function(){
return marr;
},
write:function(){//将数组中的数据写入网页的地图中
var str = "";
for(var ii=0; ii<y; ii++)
str += marr[ii].join("")+"<br>";
$("#mapbox").html(str);
},
reset:function(x,y,s){//对数组中的数据进行重新设置,默认是空白符号
var str = s || sk;
marr[y][x] = str;},
judge:function(x,y,s){//判断数组中的符号与给与的符号是否相等,默认与空白符号对比
var str = s || sk;
return marr[y][x] == str;}
}
}(option.x,option.y);//通过这种方式直接将变量变成了一个对象实例 var x=function(){}();直接运行实例函数生成对象
var snake=function(){
var length=4;//初始长度
var sarr = [{x:3,y:5}];//小蛇的身体
//var his =[{step:0,dir:1}];//想增加历史记录,步骤以及方向的记录
var step=0;
return {
init:function(){//小蛇的初始化函数
sarr = [{x:3,y:5}];
length = 4;
snake.dir=1;
step=0;
//his=[{step:0,dir:1}];
},
addbody:function(x,y){//将作为位置增加到小蛇的身体中来
sarr.unshift({x:x,y:y});//将位置增加到数组中,看来需要对JavaScript的各种函数有一个参考资料才好,压入数组的做法与下面的算法有关系
map.reset(sarr[1].x,sarr[1].y,symbol.snake);//设置地图原先头的位置的符号
map.reset(x,y,symbol.head);
},
delbody:function(){//去掉多出的身体
var dot=sarr.pop();//
map.reset(dot.x,dot.y);
},
bo:function(){return sarr;},//返回小蛇的身体数组
dir:1,//小蛇的运行方向,默认是1
chdir:function(n){//改变小蛇的运行方向
var head=snake.newhead(n);
//if(Math.abs(snake.dir-n)!=2)//不允许直接回头,但是如果在一个循环时间内,两次该方向就有可能回头,这是这个程序的一个毛病!
if(!(head.x==sarr[1].x && head.y==sarr[1].y))//通过这种方式可以判断是否在一个循环内是否真的回头啦
{snake.dir=n;
//his.push({step:step,dir:snake.dir});//历史记录小蛇的运行记录
switch(n){
case 0:var dir = '上';break;
case 1:var dir = '右';break;
case 2:var dir = '下';break;
case 3:var dir = '左';break;
}
$("#dir").html(dir);//将新的方向显示到html上面去
}
},
//his:function(){return his;},//返回小蛇的记录历史
newhead:function(dir){
var x = sarr[0].x + [0,1,0,-1][dir];//新小蛇头的位置,二维情况下的赋值就是这样的一个数组
var y = sarr[0].y + [-1,0,1,0][dir];
return {x:x,y:y};
},
go:function(){//小蛇的运行函数,主要是针对蛇头的新位置进行判断以及相关的处理
var head=snake.newhead(snake.dir);
var x = head.x;//新小蛇头的位置,二维情况下的赋值就是这样的一个数组
var y = head.y;
var isfood=map.judge(x,y,symbol.food);//判断新的位置是否为食物
step+=1;
if(!map.judge(x,y) && !isfood){//如果不是食物(就是碰到自己了),或者碰到墙壁就表示结束了
return 'dead'; }
if(isfood){//如果是食物,则加分、蛇身变长、产生新的食物
length+=1;
food.addscore();
food.newfood();
}
snake.addbody(x,y);
if(sarr.length>length){snake.delbody();}
return 'ok';
}
}
}();
var food=function(){
var score=-100;
return {
init:function(){//食物初始化
score=-100
food.newfood();
food.addscore();
},
addscore:function(){//加分
score+=100;
$("#fan").html(score);
},
newfood:function(){//产生新的食物
var x = Math.floor(Math.random()*(map.x-2))+1;
var y = Math.floor(Math.random()*(map.y-2))+1;
if(map.judge(x,y)){//判断是否随机生成的点是否为空白
map.reset(x,y,symbol.food);
}else{
food.newfood();
}
}
}
}();
})();//这里生成了新的空间,有别于直接的空间,这是一个隐蔽的空间
$(document).ready(function(){
$('#start').click(function(){game.start();});
$('#stop').toggle(function(){game.stop();$("#stop").val('resume');},function(){game.resume();$("#stop").val('stop');});
});[[it] 本帖最后由 ice024 于 2008-8-10 08:45 编辑 [/it]]






