JS版贪吃蛇

代码

1.JS链表代码(网上的)

View Code
/**
* 单向链表
* by snandy 2011
*
*/
LinkedList = function(){

function Node(data, next) {
this.data = data || null;
this.next = next || null;
}
Node.prototype = {
getValue: function() {
return this.data;
},
setValue: function(obj) {
this.data = obj;
},
getNext: function() {
return this.next;
},
setNext: function(node) {
this.next = node;
}
};
Node.prototype.constructor = Node;


function nodeByIndex(index, head) {
var node = head;
var i = 0;
// 第一个
if(index===0) {
return node;
}
while(node.next) {
if(i===index) {
return node;
}
node = node.next && node.next;
i++;
}
// 最后 一个
return node;

}

// 一次循环获取当前节点和其前驱
function nodeByData(data, list) {
var prev = null,
node = list.head;
while(node.next) {
if(node.data == data) {
if(node==list.head) {
return {
prev: null,
curr: node
};
}
else {
return {
prev: prev,
curr: node
};
}
}
prev = node;
node = node.next;
}
if(node.data == data) {
// 链表只有一个元素时,第一个元素没有前驱,不会进入while内
if(list.size() === 1) {
return {
prev: null,
curr: node
};
}
// 最后一个元素没有后继,不会进入while内
else {
return {
prev: prev,
curr: node
};
}
}
// 没有找到
return null;
}

function LinkedList() {
this.head = null;
this.tail = null;
this.length = 0;
}

LinkedList.prototype = {
add: function(index, obj) {
if(obj === undefined || obj === null || typeof index != 'number') {
throw new Error('add failed, invalid param');
}
// 逆向取 -1,如取最后一个元素
if(index < 0) {
index = this.length + index;
}
// 空链表/索引越界
if(index<0 || index>this.length) {
throw new Error('add failed, invalid index');
}

var newNode = new Node(obj);
if(index==0) {
if(this.head) {
newNode.setNext(this.head);
this.head = newNode;
}
else {
this.head = this.tail = newNode;
}
}
else {
var node = nodeByIndex(index-1, this.head),
next = node.next;
node.setNext(newNode);
newNode.setNext(next);
}
this.length++;

},
get: function(index) {
if(typeof index !== 'number') {
throw new Error('get failed, invalid param');
}
// 逆向取 -1,如取最后一个元素
if(index < 0) {
index = this.length + index;
}
// 空链表/索引越界
if(this.isEmpty() || index<0 || index>=this.length) {
throw new Error('Index: ' + index + ', Size: ' + this.length);
}

var node = nodeByIndex(index, this.head);

return node.data;
},
getFirst: function() {
return this.get(0);
},
getLast: function() {
return this.get(this.length-1);
},
set: function(index, obj) {

// 逆向取 -1,如取最后一个元素
if(index < 0) {
index = this.length + index;
}
// 空链表/索引越界
if(this.isEmpty() || index<0 || index>=this.length) {
throw new Error('Index: ' + index + ', Size: ' + this.length);
}

var node = nodeByIndex(index, this.head);

node.data = obj;

},
size: function() {
return this.length;
},
clear: function() {
this.head.next = null;
this.head = null;
},
remove: function(obj) {
var nodes = nodeByData(obj, this);

if(nodes === null) {
throw new Error('remove failed, the node does not exist');
}

var curr = nodes.curr,
prev = nodes.prev;

// 删除第一个元素,注意第一个元素没有前驱
if(prev === null) {
this.head = curr.next;
curr.next = null;
curr = null;
}
else {
prev.setNext(curr.next);
curr.next = null;
curr = null;
}
this.length--;
// 维护tail,但开销太大
//this.tail = nodeByIndex(this.length-1, this.head);
},
isEmpty: function() {
return this.head === null;
},
addLast: function(obj) {
this.add(this.length, obj);
},
addFirst: function(obj) {
this.add(0, obj);
},
contains: function(obj) {
var node = this.head;
if(this.isEmpty()) {
return false;
}
while(node.next) {
if(node.data == obj) {
return true;
}
node = node.next;
}
// 第一个(length为1时)和最后一个元素
if(node.data == obj) {
return true;
}
return false;
},
toString: function() {
var str = '',
node = this.head;

if(this.isEmpty()) {
return '[]';
}
str = '[' + node.data;
while(node.next) {
node = node.next;
str += ',' + node.data;
}
str += ']';

return str;
}

};

LinkedList.prototype.constructor = LinkedList;

return LinkedList;

}();

2.贪吃蛇html页面

View Code
<!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>
<title>Snake Page</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="LinkList.js"></script>

<script type="text/javascript">

$("document").ready(function(){
//全局变量
var mapheightnum=25; //地图宽度格数
var mapwidthnum=25; //地图高度格数
var snakebody = new LinkedList();//描述蛇身体的列表
var snakedir; //蛇头方向
var tidck; //时间定时对象
var snakespeed=200; //蛇的速度
var IsFood=false; //是否吃到食物(只读)
var IsWall=true; //是否可以穿墙
var barLength=6 //障碍物连续的长度


//在页面上画地图
$("#mainpanel").append(CreateMap(mapheightnum,mapwidthnum));
InitGame();


//初始化游戏游戏
function InitGame()
{
//暂停按钮不可用
$("#btnPause").attr("disabled","disabled");
$("#btnStart").attr("disabled","");
//初始化蛇
snakebody = new LinkedList();
InitSnake();
PaintSnake(snakebody);
$(".sankelegth").text(snakebody.size());
//画一个食物
ProductFood();
}

/*开始游戏*/
function StartGame(){
tidck=window.setInterval(function(){

//移动蛇
MoveSnake(snakebody,snakedir);

//判定蛇是否死了
if(IsDead(snakebody))
{
gameover();
return false;
}

//画蛇
PaintSnake(snakebody);
//判定蛇是否吃到食物
IsFood=($(".food").attr("id")==snakebody.get(0).x+"_"+snakebody.get(0).y);
if(IsFood)
{
ProductFood();
}
},snakespeed);
}

//游戏结束
function gameover(){
$("#div_over").show("fast");
snakebody = new LinkedList();
PauseGame();
}

/*暂停游戏*/
function PauseGame(){
clearInterval(tidck);
}

//向地图上加载障碍物
function AddBar(){
InitGame();
var x;
var y;
x=randNum(2,mapwidthnum-6);
y=randNum(2,mapheightnum-6);
for(var j=0;j<barLength;j++)
{
$("#"+(x++)+"_"+y+"").addClass("bar");
}
x=randNum(8,mapwidthnum-6);
y=randNum(8,mapheightnum-6);
for(var j=0;j<barLength;j++)
{
$("#"+x+"_"+(y++)+"").addClass("bar");
}
//重新生产一个食物
ProductFood();

}


//判定蛇是否吃到食物
function IsEatFood(headid,foodid){
if(headid==foodid) return true;
return false;
}

//判定蛇是否死了
function IsDead(snakebody){
//碰到自己
if(ContainsBody(snakebody,snakebody.get(0)))
{
return true;
}
//碰到墙
if(snakebody.get(0).x>=mapwidthnum||snakebody.get(0).x<0||snakebody.get(0).y>=mapheightnum||snakebody.get(0).y<0)
{
return true;
}

//碰到障碍物
if(MeetBar())
{
return true;
}
return false;
}


//判定是否碰到障碍物
function MeetBar()
{
var flag=false;
$(".bar").each(function(){
if((snakebody.get(0).x+"_"+snakebody.get(0).y)==$(this).attr("id"))
{
flag=true;
}
});
return flag;
}


//生产一个食物
function ProductFood(){
var foodY=randNum(0,mapheightnum-1);
var foodX=randNum(0,mapwidthnum-1);

while(Contains(snakebody,{x:foodX,y:foodY})||BoolFoodOnBar({x:foodX,y:foodY}))
{
foodY=randNum(0,mapheightnum-1);
foodX=randNum(0,mapwidthnum-1);
}
$("td").removeClass("food");
$("#"+foodX+"_"+foodY).addClass("food");
}

//判定食物是否在障碍物上面
function BoolFoodOnBar(food){
var flag=false;
$(".bar").each(function(){
if((food.x+"_"+food.y)==$(this).attr("id"))
{
flag=true;
}
});
return flag;
}

//选择速度事件
$("#slspeed").change(function(){
snakespeed=$("#slspeed").val();
$("#btnPause").click();
PauseGame();
$("#btnStart").focus();
});

//按键事件
$(document).keydown(function(event){
switch(event.keyCode)
{
case 32:
if(!$("#btnStart").attr("disabled"))
{
$("#btnStart").click();
}
else
{
$("#btnPause").click();
}
break;
case 38:
if(snakedir!="D"&&snakedir!="U"){snakedir="U";}
break
case 40:
if(snakedir!="U"&&snakedir!="D"){snakedir="D";}
break
case 37:
if(snakedir!="R"&&snakedir!="L"){snakedir="L";}
break
case 39:
if(snakedir!="L"&&snakedir!="R"){snakedir="R";}
break
default:
//do nothing;
}
});

//蛇移动
function MoveSnake(snakebody,snakedir){
switch(snakedir)
{
case "R":
snakebody.addFirst({x:snakebody.get(0).x+1,y:snakebody.get(0).y});
if(IsWall)
{
if(snakebody.get(0).x>=mapwidthnum)
{
snakebody.get(0).x=snakebody.get(0).x-mapwidthnum;
}
}
IsEatFood();
break
case "L":
snakebody.addFirst({x:snakebody.get(0).x-1,y:snakebody.get(0).y});
if(IsWall)
{
if(snakebody.get(0).x<0)
{
snakebody.get(0).x=snakebody.get(0).x+mapwidthnum;
}
}
IsEatFood();
break
case "D":
snakebody.addFirst({x:snakebody.get(0).x,y:snakebody.get(0).y+1});
if(IsWall)
{
if(snakebody.get(0).y>=mapheightnum)
{
snakebody.get(0).y=snakebody.get(0).y-mapheightnum;
}
}
IsEatFood();
break
case "U":
snakebody.addFirst({x:snakebody.get(0).x,y:snakebody.get(0).y-1});
if(IsWall)
{
if(snakebody.get(0).y<0)
{
snakebody.get(0).y=snakebody.get(0).y+mapheightnum;
}
}
IsEatFood();
break
default:
//do nothing;
}
}

//判定是否吃到食物
function IsEatFood(){
if(!IsFood){
snakebody.remove(snakebody.get(snakebody.size()-1));
//$("#sankelegth").text(snakebody.size());
$(".sankelegth").text(snakebody.size());
}
}

//画蛇在页面上
function PaintSnake(snakebody){
$("td").removeClass("snakebody");
for(var i=0;i<snakebody.size();i++){
$("#"+snakebody.get(i).x+"_"+snakebody.get(i).y).addClass("snakebody");
}
}

//初始化蛇
function InitSnake(){
snakebody.addLast({x:3,y:12});
snakebody.addLast({x:2,y:12});
snakebody.addLast({x:1,y:12});
snakedir="R";
}

//是否在蛇身体链表中
function Contains(snakebody,food)
{
for(var i=0;i<snakebody.size();i++)
{
if(snakebody.get(i).x==food.x&&snakebody.get(i).y==food.y)
{
return true;
}
}
return false;
}

//蛇头是否碰到蛇身体链表中
function ContainsBody(snakebody,food)
{
for(var i=1;i<snakebody.size();i++)
{
if(snakebody.get(i).x==food.x&&snakebody.get(i).y==food.y)
{
return true;
}
}
return false;
}


//画地图方法
function CreateMap(mapheightnum,mapwidthnum){
var strtab="<table id='maintable' cellspacing='0'>"
for(var i=0;i<mapwidthnum;i++)
{
strtab+="<tr>"
for(var j=0;j<mapheightnum;j++)
{
var id=j+"_"+i;
strtab+="<td id='"+id+"'></td>"
}
strtab+="</tr>"
}
strtab+="</table>"
return strtab;
}

//产生一个随机数 从开始覆盖上边界
function randNum(under, over){
switch(arguments.length){
case 1: return parseInt(Math.random()*under+1)-1;
case 2: return parseInt(Math.random()*(over-under+1) + under);
default: return 0;
}
}


//是否穿墙
$("#rWall").click(function(){
if($(this).attr("checked")){
IsWall=true;
}
else{
IsWall=false;
}
});


//是否有障碍物
$("#rBar").click(function(){
if($(this).attr("checked")){
AddBar();
PauseGame();
$("#btnStart").focus();
}
else{
$("#maintable tr td").removeClass("bar");
InitGame();
PauseGame();
$("#btnStart").focus();
}
});

$("#rLine").click(function(){
if(!$(this).attr("checked")){
$("#maintable tr td").css("border-color",$("#maintable").css("background-color"));
}
else{
$("#maintable tr td").css("border-color","gray");
}
});

$("#btnPause").click(function(){
PauseGame();
$("#btnStart").attr("disabled","");
$(this).attr("disabled","disabled");
});

$("#btnStart").click(function(){
StartGame();
$(this).attr("disabled","disabled");
$("#btnPause").attr("disabled","");
});
});

</script>



<style type="text/css">
/*字体样式*/
body{
color:#000000;
font-family:"微软雅黑","黑体";
font-size:15px;
line-height:15px;
text-shadow:1px 1px 1px #999999;
color:gray;
}
/*主div样式*/
#mainpanel{

}
/*右div样式*/
#rightpanel{
width:150px;
border:solid 3px gray;
text-align:left;
padding-left:10px;
}
/*右div中div样式*/
#rightpanel div{
margin-top:3px;
}
/*右div中表格样式*/
.btn{
background:#d4d0c8;
border:solid 1px gray;
cursor:pointer;
color:#404040;
}
/*主表格样式*/
#maintable{
border-bottom:solid 3px gray;
border-right:solid 3px gray;
border-left:solid 2px gray;
border-top:solid 2px gray;
}
/*主表格单元格样式*/
#maintable tr td{
border-top:solid 1px gray;
border-left:solid 1px gray;
width:15px;
height:15px;
}
/*蛇身样式*/
.snakebody{
background:green;
}
/*食物样式*/
.food{
background:#5280A8;
}
/*蛇速度下拉框样式*/
#slspeed{
width:45px;
font-size:12px;
}
/*标题样式*/
#title{
text-align:center;
}
/*蛇身长度显示样式*/
.sankelegth{
color:#F69310;
font-size:20px;
}
/*说明样式*/
#comment{
font-size:12px;
}

/*游戏结束div*/
#div_over{
left:50%;
margin-left:-150px;
top:100px;
border:solid 4px #d4D0C8;
position:absolute;
height:150px;
width:300px;
background:#D5E4FF;
display:none;
}

/*障碍物样式*/
.bar{
background-color:gray;
}

</style>

</head>


<body>
<center>

<table><tr><td>
<div id="mainpanel">
</div></td>
<td>
<div id="rightpanel">
<div id="title"><h4>贪吃蛇&nbsp;&nbsp;</h4></div>
<hr/>
<div><input id="btnStart" type="button" class="btn" value="开始游戏" /></div>
<div><input id="btnPause" type="button" class="btn" value="暂停游戏" /></div>
<br/>
<hr/>
<div><label for="rWall">是否穿墙</label><input id="rWall" type="checkbox" checked="checked"/></div>
<div><label for="rLine">显示网格</label><input id="rLine" type="checkbox" checked="checked"/></div>
<div><label for="rBar">有障碍物</label><input id="rBar" type="checkbox"/></div>
<div>
速度:
<select id="slspeed">
<option value="600">600</option>
<option value="500">500</option>
<option value="400">400</option>
<option value="300">300</option>
<option value="200" selected="selected">200</option>
<option value="100">100</option>
<option value="50">50</option>
<option value="25">25</option>
</select>
</div>
<br/>
<hr/>
<div style=" height:20px">
蛇的长度:<span class="sankelegth"></span>
</div>
<br/>
<hr/>
<div id="comment">
空格键(开始/暂停)<br/>
←↑→↓键(方向键)<br/>
</div>
</div></td>
</tr></table>
</center>

<div id="div_over">
<center>
<br/><br/><br/>
你失败了,蛇身最大长度<span class="sankelegth"></span>,点击重新开始。<br/><br/>
<input id="btnRestart" type="button" value="重新开始" class="btn" onclick="window.location.reload();" />
<input id="btnClose" type="button" value="关闭页面" class="btn" onclick="window.close();"/>
</center>
</div>
</body>
</html>

3.在IE下效果理想



posted on 2011-10-26 17:34  寂寞成灾  阅读(264)  评论(0编辑  收藏  举报

导航