自己修改的一个贪吃蛇的小游戏,请大家评评
很久以前,在学习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]]