网页游戏“贪食蛇”简析

在很早学 QuickBasic 的时候,就有一个蛇吃食物的游戏,当时是作为 Basic 的一个示例提供的。当时只顾得玩了,竟没想到要把那些高人写的代码好好分析一下。现在做 Web 开发,有一个用 Javascript 写的类似的小游戏,就花了大半天好好看了一下代码,觉得写的不错。

    功能:蛇吃食物有三种情况:走到的地方有食物;走到的地方没有食物;走到的地方是墙壁。吃到食物后,蛇的身体会变长;碰到墙壁后 Game Over,询问是否重新开始。

    整个游戏是在一个<div>框子(地图)里展开的,蛇有地图里的一系列<div>构成,初始状态(刚刚打开页面)蛇是一个<div>框,蛇头和蛇尾是在一起的,就是这个<div>框,以后吃了食物后<div>个数会变多,蛇就会长长。食物用一个<span>框表示,初始时和蛇一样其位置是随机产生的。蛇和食物的坐标用<div>和<span>的绝对位置表示。

    算法的关键是当蛇移动到新的位置后,判断前述的三种情况,做出相应的处理。而二维数组 Map[][] 就是判断的依据。二维数组 Map[][]通过其元素的值来表示蛇身、食物和空地。蛇身、食物和空地的值分别为’S'、’F'和’0′。

    用 Javascript 编程和其他语言的一个大的区别就是键盘的控制代码不同。js是通过 Key=event.keyCode 语句获取键盘码,再在多分支 switch 结构里分别处理。看完这些代码就会对浏览器里的键盘控制有所了解了。

    当然该段代码的最大价值还是让我们了解到网页游戏的大概写法,而算法其实是最重要的,把一个游戏的设想变为一堆包含许多的函数的结构化的代码,是值得我们借鉴和学习的。

    代码里有我的注释,结合我的以上大概分析介绍差不多能看懂了。

    题外问题:
    本人在调试的时候打算给原来的代码加一段地图内方格显示功能,就写了个ShowGrid()函数,采用代码生成方格。但由于在2层循环内完成方格显示,效率十分低下,生成15*10的方格需要大约6秒。生成30*20 的方格竟然需要几分钟。基本不能采用此方法。改进建议:采用图片,既美观,速度也快。

    改进建议:
    - 增加速度控制功能;
    - 美化界面,增加蛇头、蛇身和蛇尾形状。美化地图;
    - 增加声音;
    - 增加换肤功能;
    - 修正:长度等于或大于2节的蛇体,按倒退键时结束游戏的错误;

 

  
  
  
  
  1. <HTML> 
  2.   <head> 
  3.     <meta http-equiv=”Content-Type” content=”text/html; charset=gb2312> 
  4.     <title>贪吃蛇</title> 
  5.   </head> 
  6.  
  7.   <STYLE> 
  8.     .Food { background-color: green;}  
  9.     .Snake {background-color: red;}  
  10.     .grid {border:1px solid #000}  
  11.   </STYLE> 
  12.  
  13.   <SCRIPT langyage=”javascript”> 
  14.     var Rows=10 
  15.     var Cells=15 
  16.     var Num=20  //正方形格子的边长  
  17.     var BorderWidth=5 
  18.     var SpeedUp=5000 
  19.  
  20.     //创建地图  
  21.     function CreateMap()  
  22.     {  
  23.       BW = eval(Cells*Num + 2*BorderWidth)  //宽度  
  24.       BH = eval(Rows*Num + 2*BorderWidth)   //高度  
  25.       document.body.innerHTML+=’<div id=MainMap style=position:absolute;left:’+(document.body.clientWidth-BW)/2+’;top:’+(document.body.clientHeight-BH)/2+’;width:’+BW+’;height:’+BH+’;border-width:’+BorderWidth+’;border-style:outset;border-color:#0000ff></div>’  
  26.  
  27.       Map = new Array() //创建全局数组Map[]  
  28.       for(y=0; y<Rows; y++)  
  29.       {  
  30.        Map[y]=new Array() //创建全局二维数组Map[][],初始值为’0′  
  31.        for(x=0; x<Cells; x++)  
  32.          Map[y][x] = ‘0′  //’0′值表示“空地”  
  33.       }  
  34.  
  35.       //ShowGrid();  //显示地图内格子  
  36.  
  37.       Sx = parseInt(Math.random()*Cells) //创建全局变量Sx,赋予随机数  
  38.       Sy = parseInt(Math.random()*Rows)  //创建全局变量Sy,赋予随机数  
  39.       CreateSnake()  //生成蛇 - div  
  40.       CreatFood()    //生成食物 - span  
  41.       AllDiv = MainMap.all.tags(’DIV’)   //创建全局数组AllDiv,初始只有一个元素AllDiv[0](表示蛇头)。MainMap是div的ID  
  42.       AllSpan = MainMap.all.tags(’SPAN’) //创建全局数组AllSpan,始终只有一个元素AllSpan[0](表示食物)  
  43.     }  
  44.  
  45.     //显示地图内格子  
  46.     function ShowGrid()  
  47.     {  
  48.       for(r=0; r<Rows; r++)  //行  
  49.       {  
  50.         t = r*Num;  
  51.         for(c=0; c<Cells; c++)  //列  
  52.         {  
  53.           l = c*Num;  
  54.           MainMap.innerHTML += ‘<table style=”position:absolute;left:’+ l +’;top:’+ t +’;width:’+Num+’;height:’+Num+’;” cellpadding=0 cellspacing=0><tr><td align=center valign=middle class=grid>O</td></tr><table>’  
  55.         }  
  56.       }  
  57.     }  
  58.  
  59.     //创建蛇的初始位置,赋予初始值’S’  
  60.     function CreateSnake()  
  61.     {  
  62.       //<div></div>表示蛇身,通过调用本函数,可以累加到若干个<div></div>,蛇身变长  
  63.       //注意 y 和 x 是“蛇”<div>的自定义属性。一直保存着蛇尾(!)的当前位置  
  64.       //初始时,蛇头、蛇尾是同一个位置  
  65.       MainMap.innerHTML += ‘<div x=’+Sx+’ y=’+Sy+’ style=position:absolute;left:’+Sx*Num+’;top:’+Sy*Num+’;width:’+Num+’;height:’+Num+’;overflow:hidden class=Snake></div>’  
  66.       Map[Sy][Sx]=’S'  //Snake首字母  
  67.     }  
  68.  
  69.     //创建食物的位置,赋予初始值’F’  
  70.     //食物的初始位置不能与蛇的初始位置相同,只能在空地放置食物。  
  71.     //若随机产生的2位置相同,则递归执行,直到不相同为止  
  72.     function CreatFood()  
  73.     {  
  74.       Fx = parseInt(Math.random()*Cells)  
  75.       Fy = parseInt(Math.random()*Rows)  
  76.       if(Map[Fy][Fx]==’0′)  //如果是空地  
  77.       {  
  78.        MainMap.innerHTML += ‘<span style=position:absolute;left:’+Fx*Num+’;top:’+Fy*Num+’;width:’+Num+’;height:’+Num+’;overflow:hidden class=Food></span>’  
  79.        Map[Fy][Fx]=’F'  //Food首字母  
  80.       }  
  81.       else  
  82.        CreatFood() //递归  
  83.     }  
  84.  
  85.     //主移动–判断蛇头当前位置是什么  
  86.     function Move()  
  87.     {  
  88.       Sx += GoX  //自动行走,Map[Sy][Sx]为当前位置  
  89.       Sy += GoY  
  90.       if(Sy<0||Sy>=Rows) //碰墙,重新开始  
  91.         Move1()  
  92.       else  
  93.       {  
  94.        SnakeFront = Map[Sy][Sx]  
  95.        if(SnakeFront==’0′) //蛇头当前位置是空地  
  96.          Move2()  
  97.        else  
  98.        {  
  99.         if(SnakeFront==’F') //蛇头当前位置是食物  
  100.           Move3()  
  101.         else  
  102.          Move1()  
  103.       }  
  104.      }  
  105.     }  
  106.  
  107.     //重新开始  
  108.     function Move1()  
  109.     {  
  110.       if(confirm(”Game Over,重新开始?”))  
  111.         window.location.reload()  
  112.     }  
  113.  
  114.     var Times=200 
  115.  
  116.     //蛇行走到的当前位置是空地时  
  117.     function Move2()  
  118.     {  
  119.       Map[AllDiv[0].y][AllDiv[0].x]=’0′  //蛇走开后,把原位置设置为’0′,表示是空地  
  120.       AllDiv[0].removeNode(true)  //把蛇头删除,在下面的 CreateSnake()语句重新生成  
  121.       CreateSnake()  //在新的位置生成蛇的<div> 
  122.       setTimeout(’Move()’,Times)  //再次移动  
  123.     }  
  124.  
  125.     //蛇行走到的当前位置是食物时  
  126.     function Move3()  
  127.     {  
  128.       CreateSnake()  //蛇数组当前元素不删除,<div>累加一次,蛇长长一节  
  129.       AllSpan[0].removeNode(true)  //把食物删除,在下面的 CreatFood()语句重新生成  
  130.       CreatFood()  //再次随机生成食物  
  131.       setTimeout(’Move()’,Times)  //再次移动  
  132.     }  
  133.  
  134.     //蛇越行越快  
  135.     function oTimes()  
  136.     {  
  137.       Times -5 
  138.       if(Times>5)  
  139.         setTimeout(’oTimes()’, SpeedUp)  
  140.     }  
  141.  
  142.     document.onkeydown=KeyDown 
  143.     //方向  
  144.     function KeyDown()  
  145.     {  
  146.       Key=event.keyCode  
  147.       switch(Key){  
  148.       case 37:  
  149.         Dir(-1,0);break  //左方向键  
  150.       case 39:  
  151.         Dir(1,0);break   //右方向键  
  152.       case 38:  
  153.         Dir(0,-1);break  //上方向键  
  154.       case 40:  
  155.         Dir(0,1);break}  //下方向键  
  156.       return false  
  157.     }  
  158.  
  159.     var Star=0 
  160.  
  161.     function Dir(x,y)  
  162.     {  
  163.       GoX=x 
  164.       GoY=y 
  165.       if(Star==0)  
  166.       {  
  167.         oTimes()  
  168.        Star=1 
  169.        Move()  
  170.      }  
  171.     }  
  172.  
  173.     //页面打开时运行  
  174.     onload = CreateMap;  //注意无”()”,不是 CreateMap()  
  175.     //在<body>中调用的语法是:<BODY onload=”CreateMap()”>,必须加”()”  
  176.   </SCRIPT> 
  177.  
  178.   <BODY> 
  179.   <div id=”help”> 
  180.    红色方块表示蛇,绿色方块表示食物。按方向键开始。<br> 
  181.   </div> 
  182.   </BODY> 
  183.   </HTML> 

 

你可能感兴趣的:(游戏,网页,休闲,贪食蛇,简析)