代码改变世界

jQuery 贪吃蛇

2008-03-25 16:50    阅读(902)  评论(0编辑  收藏  举报
jQuery是个好东西,不过一直没忙得过来做点什么,于是模仿它的风格写了一个贪吃蛇游戏练练手。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>贪吃蛇 By:iSLee</title>
<style type="text/css">
div 
{ font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px; padding:10px; }
#toolbar 
{ border:1px solid #6699CC; }
#footer 
{ clear:both; }

.place 
{ border:1px solid #ccc; border-collapse:collapse; }
.place td 
{ border:1px solid #ccc; width:10px; height:10px; font-size:0; }

.sbody 
{ background-color:blue; }
.space 
{ background-color:#fff; }
.apple 
{ background-color:red; }
.speedup 
{ background-color:green; }
.speeddown 
{ background-color:yellow; }

.control td 
{ width:70px; }
.control td input 
{ width:100%; font-family:Verdana, Arial, Helvetica; }
</style>
<script type="text/javascript" language="JavaScript" src="jquery.pack.js"></script>
</head>
<body>

<div id="toolbar">
    
<table>
        
<tr>
            
<td>
                
<table class="control">
                    
<tr>
                        
<td></td>
                        
<td><input type="button" value="Up (W)" onclick="up()" /></td>
                        
<td></td>
                    
</tr>
                    
<tr>
                        
<td><input type="button" value="Left (A)" onclick="left()" /></td>
                        
<td><input type="button" value="Stop (P)" onclick="stop()" /></td>
                        
<td><input type="button" value="Right (D)" onclick="right()" /></td>
                    
</tr>
                    
<tr>
                        
<td></td>
                        
<td><input type="button" value="Down (S)" onclick="down()" /></td>
                        
<td></td>
                    
</tr>
                
</table>
            
</td>
            
<td>
                
<input type="button" value="尾巴+" onclick="appendbody('+',1)" />
                
<input type="button" value="尾巴++" onclick="appendbody('+',2)" />
                
<input type="button" value="尾巴-" onclick="appendbody('-',1)" />
            
</td>
            
<td>
                (需要 jQuery 包支持)
<br />
                
<span class='sbody'> </span>:障碍物,蛇身亦是障碍物。<br />
                
<span class='apple'> </span>:食物,吃后可增加蛇身长度。<br />
                
<span class='speedup'> </span>:速度,吃后可增加移动速度。<br />
                
<span class='speeddown'> </span>:速度恢复,恢复到初始速度。
            
</td>
        
<tr>
    
</table>

</div>

<div id="place"></div>
<div id="info"></div>

<div id="footer">
  
<hr size="1" />
  Copyright iSLee 2008.2
</div>

<script type="text/javascript" language="JavaScript">
/*
    代码写的比较乱,主要是想练手一下不同写法和不同模式,基本上是随想到哪里就写到哪里。
    使用了 jQuery 1.21 版本,函数记忆不熟,有些代码还可以通过它简化。
    最后就是执行效率好像不是很高,没太多考虑,不过作为贪吃蛇游戏是足够了,还有很多改进空间,但就到这里吧,我懒得写了 :P
*/

//地区数据设计:0空白地带 1障碍物 2食物 3加速宝物 4恢复速度宝物

    Game 
= {
        Snark : { 
//
            Body : [
                { x:
9, y:9 },
                { x:
9, y:8 },
                { x:
9, y:7 }
            ],
            Dir : 
'down',
            Length : 
3,
            Speed : 
400
        },
        Place : { 
//活动区域
            Body : new Array(), //区域数据
            Size : null//大小
            Create : function() { //创建数据
                for (i = 0; i < this.Size; i++) {
                    x 
= new Array()
                    
for (j = 0; j < this.Size; j++) {
                        
if (i == 0 || i == this.Size - 1 || j == 0 || j == this.Size - 1) {
                            x.push(
1);
                        } 
else {
                            x.push(
0);
                        }
                    }
                    
this.Body.push(x);
                }
            },
            
//绘制地图
            Draw : function(obj) {
                way 
= 'string';
                
switch (way) {
                    
case 'jQuery':
                        
// jQuery 组合元素方法,速度很慢
                        tb = $('<table border="1" cellpadding="0" cellspacing="0" class="place"></table>');
                        x 
= this.Size; y = this.Size;
                        
for (i = 0; i < x; i++) {
                            tr 
= $('<tr></tr>');
                            tb.append(tr);
                            
for (j = 0; j < y; j++) {
                                
switch (this.Body[i][j]) {
                                    
case 0:
                                        tr.append($(
'<td class="space" id="x' + j + 'y' + i + '"></td>'));
                                        
break;
                                    
case 1:
                                        tr.append($(
'<td class="sbody" id="x' + j + 'y' + i + '"></td>'));
                                        
break;
                                }
                            }
                        }
                        
break;
                    
case 'insertRow':
                        
// insertRow 方法,速度一般
                        tb = $('<table border="1" cellpadding="0" cellspacing="0" class="place"></table>')[0];
                        
for (i = 0; i < this.Size; i++) {
                            tr 
= tb.insertRow();
                            
for (j = 0; j < this.Size; j++) {
                                td 
= tr.insertCell(j);
                                td.id 
= 'x' + j + 'y' + i;
                                
switch (this.Body[i][j]) {
                                    
case 0:
                                        td.className 
= 'space';
                                        
break;
                                    
case 1:
                                        td.className 
= 'sbody';
                                        
break;
                                }
                            }
                        }
                        
break;
                    
case 'string':
                        
// 组合字符串方法,速度最快
                        tb = '<table border="1" cellpadding="0" cellspacing="0" class="place">';
                        
for (i = 0; i < this.Size; i++) {
                            tb 
+= '<tr>';
                            
for (j = 0; j < this.Size; j++) {
                                tb 
+= '<td id="x' + j + 'y' + i + '"';
                                
switch (this.Body[i][j]) {
                                    
case 0:
                                        tb 
+= ' class="space"';
                                        
break;
                                    
case 1:
                                        tb 
+= ' class="sbody"';
                                        
break;
                                }
                                tb 
+= '></td>';
                            }
                            tb 
+= '</tr>';
                        }
                        tb 
+= '</table>';
                        
break;
                }
                $(obj).html(tb);
            }
        }
    }

//初始化
Game.Place.Size = 40;
Game.Place.Create();
Game.Place.Draw(
'#place');

//取得随机整数
function GetRandom(min, max) {
    
return parseInt(Math.random() * (max - min + 1+ min)
}

//创建食物
function CreateApply() {
    x 
= GetRandom(119);
    y 
= GetRandom(119);
    
if (Game.Place.Body[y][x] != 0) {
        CreateApply();
    } 
else {
        GetGrid(x,y).removeClass().addClass(
'apple');
        Game.Place.Body[y][x] 
= 2;
    }
}

//创建3个食物
CreateApply();
CreateApply();
CreateApply();

//创建速度宝物
function CreateSpeed(css,val) {
    x 
= GetRandom(119);
    y 
= GetRandom(119);
    
if (Game.Place.Body[y][x] != 0) {
        CreateSpeed(css,val);
    } 
else {
        GetGrid(x,y).removeClass().addClass(css);
        Game.Place.Body[y][x] 
= val;
    }
}

//创建一个加速宝物,一个减速宝物
CreateSpeed('speedup',3);
CreateSpeed(
'speeddown',4);

    createSnark 
= function() {
        
for (i = 0; i< Game.Snark.Length; i++) {
            showbody(Game.Snark.Body[i]);
        }
    }

//获取表格单元格子
function GetGrid(x, y) {
    
return $('#x' + x + 'y' + y);
}

    showbody 
= function(o) {
        GetGrid(o.x,o.y).removeClass().addClass(
'sbody');
    }
    showspace 
= function(o) {
        GetGrid(o.x,o.y).removeClass().addClass(
'space');
        Game.Place.Body[o.y][o.x] 
= 0;
    }

//增加或减少身体长度,小于等于0时游戏将出错
    appendbody = function(m,n) {
        
for (i = 0; i < n; i++) {
            
switch (m) {
                
case "+":
                    Game.Snark.Body.push(Game.Snark.Body[Game.Snark.Length 
- 1]);
                    Game.Snark.Length
++;
                    
break;
                
case "-":
                    showspace(Game.Snark.Body[Game.Snark.Length 
- 1]);
                    Game.Snark.Body.pop();
                    Game.Snark.Length
--;
                    
break;
            }
        }
    }

//操控函数
    dirchanged = false//方向是否被改变
//
改变方向
    function changedir(a,b) {
        
if (dirchanged == false) {
            
if (Game.Snark.Dir != a) {
                Game.Snark.Dir 
= b;
                dirchanged 
= true;
            }
        }
    }
    up 
= function() {
        changedir(
'down','up');
    }
    down 
= function() {
        changedir(
'up','down');
    }
    left 
= function() {
        changedir(
'right','left');
    }
    right 
= function() {
        changedir(
'left','right');
    }
    stop 
= function() { Game.Snark.Dir = ''; dirchanged = true; }
//行动
    changed = false;
    move 
= function() {
        
//检查方向
        switch (Game.Snark.Dir) {
            
case 'up':
                change(
0-10);
                
break;
            
case 'down':
                change(
010);
                
break;
            
case 'left':
                change(
-100);
                
break;
            
case 'right':
                change(
100);
                
break;
        }
        
//显示测试数据,打开显示将导致执行速度降低
        //showinfo(Game.Snark.Body[0].x, Game.Snark.Body[0].y);
        //循环
        setTimeout('move()', Game.Snark.Speed);
    }
//获取键盘
    keydown = function(key) {
        
switch (key) {
            
case 119: up(); break;
            
case 115: down(); break;
            
case 97: left(); break;
            
case 100: right(); break;
            
case 112: stop(); break;
        }
    }
//信息
    showinfo = function(x, y) {
        $(
'#info').html('x:' + x + ' y:' + y + '<br />speed:' + Game.Snark.Speed + '<br />');
        str 
= '';
        
for (i = 0; i < Game.Place.Size; i++) {
            
for (j = 0; j < Game.Place.Body[i].length; j++) {
                str 
+= '' + Game.Place.Body[i][j];
            }
            str 
+= '<br />';
        }
        $(
'#info').append(str);
    }
//逻辑
    change = function(x, y, n) {
        dirchanged 
= false;
        
//消除尾巴
        showspace(Game.Snark.Body[Game.Snark.Length - 1]);
        
//取得当前头部坐标
        _x = Game.Snark.Body[0].x + x;
        _y 
= Game.Snark.Body[0].y + y;
        
//将要移动到的坐标
        point = { x:_x, y:_y };
        
//增加头部数据
        Game.Snark.Body.unshift(point);
        
//检查区域数据
        switch (Game.Place.Body[point.y][point.x]) {
            
case 1:
                
//碰撞障碍物,游戏结束
                stop();
                alert(
'Game Over');
                
break;
            
case 2:
                
//吃到食物
                appendbody('+',1);
                CreateApply();
                
break;
            
case 3:
                
//增加速度,关闭测试数据可增加执行速度,否则速度到一定时将不会增加,实际速度可能远不如100毫秒。
                if ((Game.Snark.Speed - 50>= 100) {
                    Game.Snark.Speed 
= Game.Snark.Speed - 50
                }
                CreateSpeed(
'speedup',3);
                
break;
            
case 4:
                
//恢复默认速度
                Game.Snark.Speed = 400;
                CreateSpeed(
'speeddown',4);
                
break;
        }
        
//修改区域数据
        Game.Place.Body[point.y][point.x] = 1;
        
//绘制头部
        showbody(Game.Snark.Body[0]);
    }

//开始游戏,游戏停止后可能会无法再复原,只能刷新页面。我还是懒
    createSnark();
    move();
    $(document.body).keypress(
function(){keydown(window.event.keyCode)});

/*
    综上所述,我还是相当的懒的 *^_^*
*/

</script>

</body>
</html>