<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>贪吃蛇</title>
<style>
body{font-size: 12px;}
.food
{
background: url("images/food1.gif") no-repeat;
/*background-color:green;*/
overflow:hidden;
position:absolute;
}
.snake_head
{
background-color: red;
border:3px solid gold;
position:absolute;
}
.snake_body
{
background-color: orange;
border:2px dotted white;
position:absolute;
}
.snake_tail
{
background-color: peachpuff;
border:2px dotted white;
position:absolute;
}
.grid
{
border-style:solid;
border-color:#0000ff;
border-top-width:0;
border-right-width:1;
border-bottom-width:1;
border-left-width:0;
padding:0;
}
.mainmap
{
position:absolute;
border-style:outset;
border-color:#0000ff;
border-width:5;
}
.table
{
position:absolute;
overflow:hidden;
border-collapse:collapse;
}
</style>
</head>
<BODY>
<div id="help">
红色方块表示蛇头,按方向键控制蛇吃食物<br><br>
行数:
<select id="rows">
<option>25</option>
<script language="javascript">
for(var ct=10;ct<=30;ct++)
document.write('<option>' + ct + '</option>');
</script>
</select>
<br>
列数:
<select id="cells">
<option>30</option>
<script language="javascript">
for(var ct=10;ct<=40;ct++)
document.write('<option>' + ct + '</option>');
</script>
</select>
<br>
<button onclick="reCreateMap()"> 设置 </button>
<br><br>
【初始化:】F5 功能键<br>
【暂停:】S 字母键<br><br>
【显示/隐藏网格:】G 字母键<br><br>
【加速:】PageUP 键<br>
【减速:】PageDown 键<br>
</div>
【速度:】<span id="speed" style="color:red"></span>
<br><br><div id="mapxy"></div>
<div
<br><br>
蛇只能吃食物,<br>不能触墙,<br>也不能咬自己
</div>
<script langyage="javascript">
var Rows = document.getElementById('rows').options[0].text;
var Cells = document.getElementById('cells').options[0].text;
var Num = 20; //正方形格子的边长
var SpeedUp = 5000;
var Times = 200;
var Start = 0;
var ShowGrid = true;
var ShowBackground = true;
var BorderWidth = 5;
var MainMap = null;
var AllDiv = new Array();
var AllSpan = new Array();
var Sx = Sy = 0;
var Map = null;
var GoX,GoY,LastX,LastY;
var moving = null;
var AllDiv=null, AllSpan=null;
//重新创建地图
function reCreateMap()
{
Rows = document.getElementById('rows').options[document.getElementById('rows').selectedIndex].text;
Cells = document.getElementById('cells').options[document.getElementById('cells').selectedIndex].text;
document.body.removeChild(MainMap);
CreateMap();
}
//创建地图
function CreateMap()
{
BW = eval(Cells * Num + 2 * BorderWidth); //宽度
BH = eval(Rows * Num + 2 * BorderWidth); //高度
//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+';></div>'
MainMap = document.createElement('div');
MainMap.className = 'mainmap';
if(ShowBackground)
MainMap.style.backgroundImage = "url('images/bgpic.jpg')";
MainMap.style.left = (document.body.clientWidth - BW) / 2;
MainMap.style.top = (document.body.clientHeight - BH) / 2;
MainMap.style.width = BW;
MainMap.style.height = BH;
document.body.appendChild(MainMap);
//创建全局数组Map[]
/*
Map = new Array() //创建全局数组Map[]
for(y=0; y<Rows; y++)
{
Map[y]=new Array() //创建全局二维数组Map[][],初始值为'0'
for(x=0; x<Cells; x++)
Map[y][x] = '0' //'0'值表示“空地”
}
*/
Map = new Array();
for(y = 0; y < Rows; y++)
{
//创建全局二维数组Map[][],初始值为'0'
Map.push(new Array());
for( x = 0; x < Cells; x++)
Map[y].push('0'); //'0'值表示“空地”
}
//显示地图内格子
if (ShowGrid)
MainMap.appendChild(CreateGrid(' '));
//创建全局变量Sx,赋予随机数
Sx = parseInt(Math.random() * Cells);
//创建全局变量Sy,赋予随机数
Sy = parseInt(Math.random() * Rows);
//生成蛇 - div
CreateSnake();
//生成食物 - span
CreatFood();
//创建全局数组AllDiv,保存着蛇身各节<div>。AllDiv[0]为蛇尾。MainMap是div的ID
AllDiv = MainMap.getElementsByTagName('div'); //等价于AllDiv = MainMap.all.tags('DIV')
//创建全局数组AllSpan,始终只有一个元素AllSpan[0]
AllSpan = MainMap.getElementsByTagName('span'); //等价于AllSpan = MainMap.all.tags('SPAN')
}
//创建地图内格子(Rows*Cells 大小的 Table)
function CreateGrid(celltext)
{
var table = document.createElement('table');
table.className = 'table';
table.style.left = 0;
table.style.top = 0;
table.setAttribute('id','grid');
table.setAttribute('border','0'); //table.border = '0';
table.setAttribute('cellspacing','0');
table.setAttribute('cellpadding','0');
var tbody = document.createElement("tbody");
table.insertBefore(tbody, null);
for (var i=0; i<Rows; i++)
{
var tr = document.createElement('tr');
for(var j=0; j<Cells; j++)
{
var td = document.createElement('td');
td.className = 'grid';
td.width = Num; //td.style.width = Num;
td.height = Num; //td.style.height = Num;
var text = document.createTextNode(celltext);
td.insertBefore(text, null);
tr.insertBefore(td, null);
}
tbody.insertBefore(tr, null);
}
return table;
}
//创建蛇的位置,赋予值'S'
function CreateSnake()
{
//<div>表示蛇身,通过调用本函数,可以累加到若干个,蛇身变长
//注意 y 和 x 是“蛇”<div> 的自定义属性。一直保存着蛇身体各节的Map坐标,与Map[][]联系
//初始时,蛇头、蛇尾是同一个位置
var div = document.createElement('div');
div.className = 'snake_head';
div.setAttribute('x',Sx);
div.setAttribute('y',Sy);
div.style.left = Sx * Num;
div.style.top = Sy * Num;
div.style.width = Num;
div.style.height = Num;
MainMap.appendChild(div);
Map[Sy][Sx] = 'S'; //Snake首字母
//蛇身长度
//document.all.mapxy.innerHTML = AllDiv.length;
if (AllDiv!=null)
{
if (AllDiv.length>1)
{
AllDiv[0].className = 'snake_tail'; //蛇尾
for (var i=1;i<AllDiv.length-1;i++) //蛇身
AllDiv[i].className = 'snake_body';
}
}
}
//创建食物的位置,赋予初始值'F'
//食物的初始位置不能与蛇的初始位置相同,只能在空地放置食物。
//若随机产生的2位置相同,则递归执行,直到不相同为止
function CreatFood()
{
Fx = parseInt(Math.random() * Cells);
Fy = parseInt(Math.random() * Rows);
if(Map[Fy][Fx] == '0') //如果是空地
{
MainMap.appendChild(CreatSpan(Fx * Num,Fy * Num,Num));
Map[Fy][Fx] = 'F'; //Food首字母
}
else
{
CreatFood(); //递归
}
}
//生成食物的span
function CreatSpan(l,t,num)
{
var span = document.createElement('span');
span.style.left = l;
span.style.top = t;
span.style.width = num;
span.style.height = num;
span.className = 'food';
return span;
}
//主移动--判断蛇头前面的是什么
function Move()
{
//自动行走,Map[Sy][Sx]为蛇头前面位置
Sx += GoX;
Sy += GoY;
//碰墙,重新开始
if(Sy < 0 || Sy >= Rows)
{
Move1();
}
else
{
SnakeFront = Map[Sy][Sx];
switch(SnakeFront)
{
case '0': //蛇前是空地
Move2();
break;
case 'F': //蛇前面是食物
Move3();
break;
case 'S': //蛇前面是自己的身体
Move1();
break;
default: //啥都不是就是超出地图范围game over
Move1();
}
}
}
//重新开始
function Move1()
{
if(confirm("Game Over,重新开始?"))
{
//window.location.reload();
reCreateMap();
Start = 0;
}
else
window.close();
}
//蛇行走到的当前位置是空地时
function Move2()
{
//蛇走开后,把原位置设置为'0',表示是空地
//把蛇数组当前元素删除,在下面的 CreateSnake()语句重新生成
Map[AllDiv[0].getAttribute('y')][AllDiv[0].getAttribute('x')] = '0';
var fatherNode = AllDiv[0].parentNode; //AllDiv[0].removeNode(true);
fatherNode.removeChild(AllDiv[0]);
//在新的位置生成蛇的<div>
CreateSnake();
//再次移动
moving = setTimeout('Move()',Times);
}
//蛇行走到的当前位置是食物时
function Move3()
{
//蛇数组当前元素不删除,<div>累加一次,蛇长长一节
CreateSnake();
//把食物数组当前元素删除,在下面的 CreatFood()语句重新生成
var parentNode = AllSpan[0].parentNode; //AllSpan[0].removeNode(true)
parentNode.removeChild(AllSpan[0]);
//再次随机生成食物
CreatFood();
//再次移动
moving = setTimeout('Move()',Times);
}
//蛇行加速
function oTimes(step)
{
if(step>0 && Times>30)
Times -= step;
if(step<0 && Times<400)
Times -= step;
document.getElementById('speed').innerHTML = Times;
//If(Times > 5) setTimeout('oTimes()', SpeedUp);
}
//绑定键盘事件
document.onkeydown = KeyDown;
//按键
function KeyDown(e)
{
if(e)
Key = e.keyCode;
else
Key = window.event.keyCode
switch(Key)
{
case 37: //左方向键
Dir(-1,0);
break
case 39: //右方向键
Dir(1,0);
break
case 38: //上方向键
Dir(0,-1);
break
case 40: //下方向键
Dir(0,1);
break
case 33: //PageUp - speed up
oTimes(5);
break;
case 34: //PageDown - speed down
oTimes(-5);
break;
case 66: // B - Show/Hidden Background
ShowBackground = !ShowBackground;
if(ShowBackground)
{
MainMap.style.backgroundImage = "url('images/bgpic.jpg')";
//MainMap.style.backgroundRepeat="repeat-x repeat-y";
//MainMap.style.backgroundRepeat="no-repeat";
}
else
MainMap.style.backgroundImage = "url('')";
break;
case 71: // G - Show/Hidden Grid
ShowGrid = !ShowGrid;
if(ShowGrid)
MainMap.appendChild(CreateGrid(' '));
else
MainMap.removeChild(document.getElementById('grid'));
break;
case 83: // s - stop
clearTimeout(moving);
Start = 0;
break;
}
return false
}
function Dir(x,y)
{
GoX = x;
GoY = y;
if( Start == 0 )
{
LastX = x;
LastY = y;
clearTimeout(moving);
Start = 1;
Move();
}
else
{
/* 增加的反方向判断 */
//检查上次行动方向和本次行动方向,如果方向正好相反那么还是保持上次的前进方向
if (GoX + LastX == 0 && GoY + LastY == 0)
{
GoX = LastX;
GoY = LastY;
}
else
{ //如果不一样则记住本次的行动方向
LastX = GoX;
LastY = GoY;
}
}
}
//绘制地图
CreateMap();
document.getElementById('speed').innerHTML = Times;
</script>
</BODY>
</HTML>
作者:张庆(网眼)
演示地址:http://www.why100000.com/_lab/docs/js_code/snake_pro/snake_pro.htm
更多文章:http://blog.why100000.com
2008-9-23