当前位置: 代码迷 >> JavaScript >> JavaScript简略贪吃蛇,基本面向对象
  详细解决方案

JavaScript简略贪吃蛇,基本面向对象

热度:188   发布时间:2012-10-30 16:13:36.0
JavaScript简单贪吃蛇,基本面向对象

?

程序包括一个html文件:snake.html和一个js文件:snake.js

???? snake.html:

<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JavaScript简单贪吃蛇</title>
<script type="text/javascript" src="snake.js"></script>
<script type="text/javascript" >
?? ?$s(function(){
?? ??? ?$s.SnakeContext.init();?? ??? ?
?? ?});
</script>
</head>
<body>?? ?
<div id="headLocation"></div>
<div id="keyup"></div>
</body>
</html>

snake.js:

/*
?* JavaScript简单贪吃蛇.基本面向对象.
?* 规则:
?*??? 1.没有墙,左与右连接,上与下连接.
?*??? 2.当蛇头碰撞到自身时死亡.
?* 兼容性:
?*??? 完全支持Firefox,Chrome
?*??? 基本支持IE(除了调试部分)
?*
?* 作者:pcenshao
?* 转载请注明来自:
?*??? http://blog.csdn.net/pywepe
?*??? http://pcenshao.taobao.com
?*/
(function(){
?? ?
??? $s = function(){
?? ??? ?if(arguments.length == 1){
?? ??? ??? ?if(typeof arguments[0] == "string"){
?? ??? ??? ??? ?return document.getElementById(arguments[0]);?? ?
?? ??? ??? ?}else if(typeof arguments[0] == "function"){
?? ??? ??? ??? ?window.onload = arguments[0];
?? ??? ??? ?} ?
?? ??? ?}
??? };?? ?
?? ?
?? ?$s.UNIT_WIDTH = 10; // 单元的宽度
?? ?$s.UNIT_HEIGHT = 10;
?? ?$s.PANEL_WIDTH = 30; // 逻辑宽度?? ?
?? ?$s.PANEL_HEIGHT = 20; // 逻辑高度
?? ?$s.STEP = 250 ;? // 每一步的时间
?? ?$s.HEAD_COLOR = "red"; // 蛇头颜色
?? ?$s.BODY_COLOR = "black"; // 蛇体颜色
?? ?/*
?? ? * 食物的颜色
?? ? */
?? ?$s.COLORS = ["blue","green","#494e8f","#905d1d","#845538","#77ac98","#8552a1"];
?? ?
?? ?/*
?? ? * 调试相关
?? ? * $s.DEBUG 调试信息显示开关
?? ? * $s.KEY_UP_DIR_ID 监视方向键的结点id,若不存在,则不显示
?? ? * $s.HEAD_LOCATION_ID 监视蛇头位置的结点id,若不存在,则不显示
?? ? */
?? ?$s.DEBUG = false;
?? ?$s.KEY_UP_DIR_ID = "keyup";
?? ?$s.HEAD_LOCATION_ID = "headLocation";
?? ?
?? ?$s.Dir = {? // 代表方向,强制以$s.Dir.UP方法调用,避免参数错误
?? ??? ?UP : {},
?? ??? ?DOWN : {},
?? ??? ?LEFT : {},
?? ??? ?RIGHT : {},
?? ??? ?NONE : {}
?? ?};
?? ?
?? ?$s.State = { // 代表状态
?? ??? ?STOP : {},
?? ??? ?RUNNGIN : {},
?? ??? ?PAUSE : {}?? ??? ??? ?
?? ?};
?? ?
?? ?$s.Unit = function(){ // 一个单元格,用MVC的眼光看,Unit是模型,UnitView是视图
?? ??? ?this.x = 0;
?? ??? ?this.y = 0;
?? ??? ?this.view = new $s.UnitView();
?? ??? ?this.view.unit = this;
?? ??? ?this.color = $s.BODY_COLOR;
?? ?};
?? ?$s.Unit.prototype.repaint = function(){
?? ??? ?if(this.view != null){
?? ??? ??? ?this.view.repaint(); // 通知重绘?? ?
?? ??? ?}?? ?
?? ?};?? ??? ??? ?
?? ?
?? ?$s.Snake = function(){
?? ??? ?this.units = [];
?? ?};?? ?
?? ?
?? ?$s.Snake.prototype.init = function(dir,count){
?? ??? ?var x = 5;
?? ??? ?var y = 5;
?? ??? ?for(var i = 0 ; i < count ; i ++){
?? ??? ??? ?var u = new $s.Unit();
?? ??? ??? ?u.x = x ;
?? ??? ??? ?u.y = y ++;
?? ??? ??? ?this.units.push(u);
?? ??? ??? ?if(i == (count - 1 )){
?? ??? ??? ??? ?u.color = $s.HEAD_COLOR;
?? ??? ??? ?}
?? ??? ??? ?u.repaint();
?? ??? ?}
?? ?};
?? ?
?? ?$s.Snake.prototype.crash = function(x,y){ // 传入头部的位置,返回true表示碰撞自身
?? ??? ?for(var i = this.units.length - 2 ; i >= 0 ; i --){ // 不包括头自身
?? ??? ??? ?var u = this.units[i];
?? ??? ??? ?if(u.x == x && u.y == y){
?? ??? ??? ??? ?return true;?? ?
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return false;
?? ?};
?? ?
?? ?$s.Snake.prototype.go = function(){
?? ??? ?// 判断前方是否有食物
?? ??? ?// 是否撞墙
?? ??? ?var _x = 0 , _y = 0;
?? ??? ?var head = this.units[this.units.length - 1];
?? ??? ?_x = head.x;
?? ??? ?_y = head.y;
?? ??? ?var dir = $s.SnakeContext.dir;
?? ??? ?
?? ??? ?if(this.crash(_x,_y)){ // 判断是否碰撞到自身
?? ??? ??? ?$s.SnakeContext.stop();
?? ??? ??? ?$s.SnakeContext.ondead(); // 触发dead事件
?? ??? ??? ?return;
?? ??? ?}
?? ??? ?
?? ??? ?if(dir == $s.Dir.LEFT){
?? ??? ??? ?_x --;?? ??? ?
?? ??? ?}else if(dir == $s.Dir.RIGHT){
?? ??? ??? ?_x ++;
?? ??? ?}else if(dir == $s.Dir.UP){
?? ??? ??? ?_y --;
?? ??? ?}else if(dir == $s.Dir.DOWN){
?? ??? ??? ?_y ++;
?? ??? ?}
?? ??? ?
?? ??? ?// 实现左右连接,上下连接
?? ??? ?if(_x >= $s.PANEL_WIDTH){
?? ??? ??? ?_x = 0;
?? ??? ?}
?? ??? ?if(_x < 0){
?? ??? ??? ?_x = $s.PANEL_WIDTH - 1;?? ?
?? ??? ?}
?? ??? ?if(_y >= $s.PANEL_HEIGHT){
?? ??? ??? ?_y = 0;
?? ??? ?}
?? ??? ?if(_y < 0){
?? ??? ??? ?_y = $s.PANEL_HEIGHT - 1;?? ?
?? ??? ?}
?? ??? ?
?? ??? ?var h = new $s.Unit(); // 新头
?? ??? ?if($s.SnakeContext.hasFood(_x,_y)){ // 下一步碰到食物
?? ??? ??? ?this.eat(_x,_y);
?? ??? ??? ?head = this.units[this.units.length - 1]; // 因为eat方法可以改变头部,所以重新获取
?? ??? ??? ?_x = head.x;
?? ??? ??? ?_y = head.y;
?? ??? ??? ?
?? ??? ??? ?if(dir == $s.Dir.LEFT){
?? ??? ??? ??? ?_x --;?? ??? ?
?? ??? ??? ?}else if(dir == $s.Dir.RIGHT){
?? ??? ??? ??? ?_x ++;
?? ??? ??? ?}else if(dir == $s.Dir.UP){
?? ??? ??? ??? ?_y --;
?? ??? ??? ?}else if(dir == $s.Dir.DOWN){
?? ??? ??? ??? ?_y ++;
?? ??? ??? ?}
?? ??? ??? ?head.color = $s.HEAD_COLOR;
?? ??? ??? ?head.repaint();
?? ??? ??? ?var oldHead = this.units[this.units.length - 2];
?? ??? ??? ?oldHead.color = $s.BODY_COLOR;
?? ??? ??? ?oldHead.repaint();
?? ??? ??? ?return;
?? ??? ?}
?? ??? ?
?? ??? ?var tail = this.units.shift();
?? ??? ?$s.NodePool.releaseNode(tail);?? ??? ?
?? ??? ?
?? ??? ?h.x = _x;
?? ??? ?h.y = _y;
?? ??? ?this.units.push(h);
?? ??? ?
?? ??? ?for(var i = this.units.length - 1; i >= 0; i --){
?? ??? ??? ?var u = this.units[i];
?? ??? ??? ?if(i == (this.units.length - 1)){ // 头
?? ??? ??? ??? ?u.color = $s.HEAD_COLOR;
?? ??? ??? ?}else{
?? ??? ??? ??? ?u.color = $s.BODY_COLOR;
?? ??? ??? ?}
?? ??? ??? ?u.repaint();
?? ??? ?}
?? ??? ?
?? ?};
?? ?
?? ?$s.Snake.prototype.eat = function(x,y){
?? ??? ?var food = $s.SnakeContext.food;
?? ??? ?if(food != null){
?? ??? ??? ?food.alive = false;
?? ??? ??? ?this.units.push(food.unit);
?? ??? ??? ?$s.SnakeContext.oneat();
?? ??? ?}else{
?? ??? ??? ?alert("error:no food on (" + x + "," + y + ")");?? ?
?? ??? ?}?? ??? ?
?? ?}
?? ?
?? ?/*
?? ? * 随机数产生器,提供简便的方法
?? ? */
?? ?$s.Random = {
?? ??? ?randomNumber : function(lower,upper){ // 返回区间[lower,upper]的整数
?? ??? ??? ?var choices = upper - lower + 1;
?? ??? ??? ?return Math.floor(Math.random() * choices + lower); // value = Math.floor(Math.random() * 可能值的个数 + 第一个可能的值)
?? ??? ?},
?? ??? ?randomLocation : function(maxX,maxY){
?? ??? ??? ?var x = $s.Random.randomNumber(0,maxX);
?? ??? ??? ?var y = $s.Random.randomNumber(0,maxY);
?? ??? ??? ?return {x:x,y:y};
?? ??? ?}?? ?
?? ?};
?? ?
?? ?$s.Food = function(x,y){ // 代表食物,由一个Unit表示
?? ??? ?this.unit = new $s.Unit();
?? ??? ?this.unit.x = x;
?? ??? ?this.unit.y = y;
?? ??? ?var color = $s.COLORS[$s.Random.randomNumber(0,$s.COLORS.length - 1)];
?? ??? ?this.unit.color = color;
?? ??? ?this.alive = true;
?? ??? ?
?? ??? ?this.unit.repaint();
?? ?};
?? ?$s.Food.prototype.locateOn = function(x,y){
?? ??? ?return this.unit.x == x && this.unit.y == y;
?? ?};
?? ?
?? ?/*
?? ? * HTML结点池,主要目的是提高效率
?? ? * 因为snake的移动是通过删除尾部结点并向头部添加结点实现的,
?? ? * 在这个过程中会有大量的结点创建操作,为了操作效率,所以对结点进行池化管理.
?? ? * 尾部的结点不删除,而是隐藏,需要结点时可以重用之
?? ? */?? ?
?? ?$s.NodePool = {
?? ??? ?nodes : []
?? ?};
?? ?$s.NodePool._findHideNode = function(){ // 查找隐藏的div结点?? ??? ?
?? ??? ?for(var i = 0 ; i < this.nodes.length ; i ++){
?? ??? ??? ?var n = this.nodes[i];
?? ??? ??? ?if(n.style.display == "none"){
?? ??? ??? ??? ?return n;?? ?
?? ??? ??? ?}?? ?
?? ??? ?}
?? ??? ?return null;
?? ?};
?? ?$s.NodePool.createNode = function(){
?? ??? ?var pooledNode = this._findHideNode();
?? ??? ?if(pooledNode != null){
?? ??? ??? ?return pooledNode;?? ?
?? ??? ?}else{
?? ??? ??? ?var newNode = document.createElement("div");
?? ??? ??? ?this.nodes.push(newNode);
?? ??? ??? ?return newNode;
?? ??? ?}
?? ?};
?? ?$s.NodePool.releaseNode = function(node){
?? ??? ?if(node != undefined && node != null){
?? ??? ??? ?if(node instanceof $s.Unit){
?? ??? ??? ??? ?var view = node.view;
?? ??? ??? ??? ?if(view != null){
?? ??? ??? ??? ??? ?var div = view.node;
?? ??? ??? ??? ??? ?div.style.display = "none";
?? ??? ??? ??? ?}
?? ??? ??? ?}?? ??? ??? ?
?? ??? ?}?? ?
?? ?}
?? ?
?? ?$s.UnitView = function(){ // Unit的视图
?? ??? ?this.unit = null;
?? ??? ?this.node = null;
?? ?};
?? ?$s.UnitView.prototype.repaint = function(){
?? ??? ?if(this.node == null){ // 初始化
?? ??? ??? ?var tag = $s.NodePool.createNode();
?? ??? ??? ?tag.style.width = $s.UNIT_WIDTH + "px";
?? ??? ??? ?tag.style.height = $s.UNIT_HEIGHT + "px";
?? ??? ??? ?tag.style.borderStyle = "dotted";
?? ??? ??? ?tag.style.borderWidth = "1px";
?? ??? ??? ?tag.style.borderColor = "white";?? ??? ?
?? ??? ??? ?tag.style.margintLeft = "1px";
?? ??? ??? ?tag.style.marginRight = "1px";
?? ??? ??? ?tag.style.marginTop = "1px";
?? ??? ??? ?tag.style.marginBottom = "1px";
?? ??? ??? ?tag.style.backgroundColor =? this.unit.color; // 颜色由模型Unit指定
?? ??? ??? ?tag.style.position = "absolute"; //容器的position指定为relative,孩子的position指定为absolute时,表示孩子相对容器绝对定位.
?? ??? ??? ?
?? ??? ??? ?tag.style.display = "block"; // 重要,因为从NodePool取现的结点是隐藏状态的
?? ??? ??? ?
?? ??? ??? ?var x = this.unit.x * $s.UNIT_WIDTH;
?? ??? ??? ?var y = this.unit.y * $s.UNIT_HEIGHT;
?? ??? ??? ?tag.style.top = y + "px";
?? ??? ??? ?tag.style.left = x + "px";
?? ??? ??? ?
?? ??? ??? ?this.node = tag;
?? ??? ??? ?$s.SnakeContext.panelView.append(this);
?? ??? ?}else{
?? ??? ??? ?var tag = this.node;
?? ??? ??? ?
?? ??? ??? ?var x = this.unit.x * $s.UNIT_WIDTH;
?? ??? ??? ?var y = this.unit.y * $s.UNIT_HEIGHT;
?? ??? ??? ?tag.style.top = y + "px";
?? ??? ??? ?tag.style.left = x + "px";
?? ??? ??? ?tag.style.backgroundColor = this.unit.color;
?? ??? ?}
?? ?};?? ?
?? ?
?? ?$s.PanelView = function(){ // 整个游戏区域,包括按钮区
?? ??? ?var panel = document.createElement("div");
?? ??? ?panel.style.width = ($s.PANEL_WIDTH * $s.UNIT_WIDTH ) + "px";
?? ??? ?panel.style.height = ($s.PANEL_HEIGHT * $s.UNIT_HEIGHT ) + "px";
?? ??? ?panel.style.borderStyle = "dotted";
?? ??? ?panel.style.borderColor = "red";
?? ??? ?panel.style.borderWidth = "1px";
?? ??? ?panel.style.marginLeft = "auto";
?? ??? ?panel.style.marginRight = "auto";
?? ??? ?panel.style.marginTop = "50px";
?? ??? ?panel.style.position = "relative"; // 容器的position指定为relative,孩子的position指定为absolute时,表示孩子相对容器绝对定位.
?? ??? ?panel.style.marginBottom = "auto";
?? ??? ?this.node = panel;
?? ??? ?document.body.appendChild(panel);
?? ??? ?
?? ??? ?var len = document.createElement("div");
?? ??? ?len.style.marginLeft = "auto";
?? ??? ?len.style.marginRight = "auto";
?? ??? ?len.style.marginBottom = "20px";
?? ??? ?len.style.color = "gray";
?? ??? ?len.style.fontSize = "12px";
?? ??? ?len.innerHTML = "长度:";
?? ??? ?document.body.appendChild(len);
?? ??? ?$s.SnakeContext._len = len;
?? ??? ?
?? ??? ?var startBn = document.createElement("button");
?? ??? ?startBn.innerHTML = "开始";
?? ??? ?startBn.style.marginLeft = "10px";
?? ??? ?startBn.onclick = function(){
?? ??? ??? ?$s.SnakeContext.run();
?? ??? ?};
?? ??? ?$s.SnakeContext._startBn = startBn;
?? ??? ?document.body.appendChild(startBn);
?? ??? ?
?? ??? ?var pauseBn = document.createElement("button");
?? ??? ?pauseBn.innerHTML = "暂停";
?? ??? ?pauseBn.style.marginLeft = "10px";
?? ??? ?pauseBn.onclick = function(){
?? ??? ??? ?$s.SnakeContext.pause();?? ?
?? ??? ?};
?? ??? ?$s.SnakeContext._pauseBn = pauseBn;
?? ??? ?document.body.appendChild(pauseBn);
?? ??? ?
?? ??? ?/*
?? ??? ?var stopBn = document.createElement("button");
?? ??? ?stopBn.innerHTML = "停止";
?? ??? ?stopBn.style.marginLeft = "10px";
?? ??? ?stopBn.onclick = function(){
?? ??? ??? ?$s.SnakeContext.stop();?? ?
?? ??? ?};
?? ??? ?$s.SnakeContext._stopBn = stopBn;
?? ??? ?document.body.appendChild(stopBn);
?? ??? ?*/
?? ??? ?
?? ??? ?var restartBn = document.createElement("button");
?? ??? ?restartBn.innerHTML = "重新开始";
?? ??? ?restartBn.style.marginLeft = "10px";
?? ??? ?restartBn.onclick = function(){
?? ??? ??? ?window.location.href = window.location.href;
?? ??? ?};
?? ??? ?$s.SnakeContext._restartBn = restartBn;
?? ??? ?document.body.appendChild(restartBn);
?? ??? ?
?? ??? ?var line = document.createElement("div");
?? ??? ?line.style.height = "10px";
?? ??? ?document.body.appendChild(line);
?? ??? ?
?? ??? ?var span = document.createElement("span");
?? ??? ?span.style.color = "gray";
?? ??? ?span.style.fontSize = "12px";
?? ??? ?span.innerHTML = "调试";
?? ??? ?document.body.appendChild(span);
?? ??? ?
?? ??? ?var debug = document.createElement("input");
?? ??? ?debug.type = "checkbox";?? ??? ?
?? ??? ?debug.checked = $s.DEBUG;
?? ??? ?debug.onchange = function(){
?? ??? ??? ?$s.SnakeContext.setDebug(debug.checked);
?? ??? ?};?? ??? ?
?? ??? ?document.body.appendChild(debug);
?? ??? ?
?? ?};
?? ?$s.PanelView.prototype.append = function(unitView){
?? ??? ?try{
?? ??? ??? ?this.node.appendChild(unitView.node);
?? ??? ?}catch(e){
?? ??? ??? ?alert(e);?? ?
?? ??? ?}?? ??? ?
?? ?};
?? ?
?? ?/*
?? ? * 全局环境类,代表应用?? ??? ?
?? ? * 约定以_开头的成员为私有成员
?? ? * 启动程序的方法:
?? ? * window.onload = function(){
?? ? *?? ? $s.SnakeContext.init();
?? ? * }
?? ? */
?? ?$s.SnakeContext = {?? ?
?? ??? ?dir : $s.Dir.NONE,
?? ??? ?state : $s.State.STOP,
?? ??? ?goTimer : null,?? ??? ?
?? ??? ?run : function(){?? ??? ??? ?
?? ??? ??? ?if(this.state != $s.State.RUNNGIN){
?? ??? ??? ??? ?this.state = $s.State.RUNNGIN;
?? ??? ??? ??? ?this.goTimer = window.setInterval(function(){
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.updateFood();
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.snake.go();?? ??? ?
?? ??? ????????????????????????????????????????? },$s.STEP);
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ?},
?? ??? ?stop : function(){
?? ??? ??? ?this._setState($s.State.STOP);
?? ??? ?},
?? ??? ?pause : function(){
?? ??? ??? ?this._setState($s.State.PAUSE);
?? ??? ?},
?? ??? ?_setState : function(s){
?? ??? ??? ?if(this.state != s && this.goTimer != null){
?? ??? ??? ??? ?window.clearInterval(this.goTimer);
?? ??? ??? ??? ?this.goTimer = null;
?? ??? ??? ??? ?this.state = s;
?? ??? ??? ?}?? ?
?? ??? ?},
?? ??? ?getFood : function(x,y){
?? ??? ??? ?for(var f in this.foods){
?? ??? ??? ??? ?if(f.x == x && f.y == y){
?? ??? ??? ??? ??? ?return f;?? ?
?? ??? ??? ??? ?}?? ?
?? ??? ??? ?}?? ?
?? ??? ??? ?return null;
?? ??? ?},
?? ??? ?init : function(){?? ?
?? ??? ??? ?this.panelView = new $s.PanelView();
?? ??? ??? ?this.snake = new $s.Snake();
?? ??? ??? ?this.dir = $s.Dir.DOWN;
?? ??? ??? ?this.snake.init($s.Dir.UP,3);
?? ??? ??? ?this._len.innerHTML = "长度:" + 3;
?? ??? ??? ?
?? ??? ??? ?document.body.onkeyup = function(e){
?? ??? ??? ??? ?var code = null;
?? ??? ??? ??? ?if(window.event){ // fuck的IE
?? ??? ??? ??? ??? ?code = ?? ?window.event.keyCode;
?? ??? ??? ??? ?}else{
?? ??? ??? ??? ??? ?code = ?? ?e.keyCode;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?var str = "";
?? ??? ??? ??? ?var oldDir = $s.SnakeContext.dir;
?? ??? ??? ??? ?switch(code){
?? ??? ??? ??? ??? ?case 37: // left
?? ??? ??? ??? ??? ??? ?if($s.SnakeContext.dir != $s.Dir.RIGHT){
?? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.dir = $s.Dir.LEFT;?? ?
?? ??? ??? ??? ??? ??? ?}?? ?
?? ??? ??? ??? ??? ??? ?str = "left";
?? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case 38 : // up
?? ??? ??? ??? ??? ??? ?if($s.SnakeContext.dir != $s.Dir.DOWN){
?? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.dir = $s.Dir.UP;?? ?
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ?
?? ??? ??? ??? ??? ??? ?str = "up";
?? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case 39: // right
?? ??? ??? ??? ??? ??? ?if($s.SnakeContext.dir != $s.Dir.LEFT){
?? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.dir = $s.Dir.RIGHT;?? ?
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ?
?? ??? ??? ??? ??? ??? ?str = "right";
?? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case 40: // down
?? ??? ??? ??? ??? ??? ?if($s.SnakeContext.dir != $s.Dir.UP){
?? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.dir = $s.Dir.DOWN;?? ?
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?str = "down";
?? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?if($s.SnakeContext.dir != oldDir){
?? ??? ??? ??? ??? ?if($s.DEBUG){
?? ??? ??? ??? ??? ??? ?var v = $s($s.KEY_UP_DIR_ID);
?? ??? ??? ??? ??? ??? ?if(v){
?? ??? ??? ??? ??? ??? ??? ?v.innerHTML = "方向键:" + str;
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?if($s.SnakeContext.goTimer != null){
?? ??? ??? ??? ??? ??? ?window.clearInterval($s.SnakeContext.goTimer);
?? ??? ??? ??? ??? ??? ?$s.SnakeContext.goTimer = null;?? ??? ??? ?
?? ??? ??? ??? ??? ?}?? ?
?? ??? ??? ??? ??? ?$s.SnakeContext.snake.go();
?? ??? ??? ??? ??? ?$s.SnakeContext.goTimer = window.setInterval(function(){
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.updateFood();
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?$s.SnakeContext.snake.go();?? ??? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? },$s.STEP);
?? ??? ??? ??? ?}?? ??? ??? ?
?? ??? ??? ?};
?? ??? ??? ?
?? ??? ??? ?var loc = $s.Random.randomLocation($s.PANEL_WIDTH - 1, $s.PANEL_HEIGHT - 1);
?? ??? ??? ?this.food = new $s.Food(loc.x,loc.y);
?? ??? ??? ?
?? ??? ?},
?? ??? ?snake : null,
?? ??? ?foods : [],
?? ??? ?panelView : null,
?? ??? ?food : null,
?? ??? ?updateFood : function(){
?? ??? ??? ?if(this.food.alive){ // 当前Food还存活
?? ??? ??? ??? ?return;?? ?
?? ??? ??? ?}
?? ??? ??? ?var loc = null;
?? ??? ??? ?do{

?????????????? // 随机产生一个点,直到不Snake重叠???
?? ??? ??? ???? loc = $s.Random.randomLocation($s.PANEL_WIDTH - 1,$s.PANEL_HEIGHT - 1);
?? ??? ??? ?}while(this.overlap(loc));?? ?
?? ??? ??? ?this.food = new $s.Food(loc.x,loc.y);
?? ??? ??? ?
?? ??? ?},
?? ??? ?overlap : function(loc){ // 检查是否与Snake重叠,当重叠时返回true
?? ??? ??? ?var x = loc.x;
?? ??? ??? ?var y = loc.y;
?? ??? ??? ?for(var i = 0 ; i < this.snake.units.length ; i ++ ){
?? ??? ??? ??? ?var u = this.snake.units[i];
?? ??? ??? ??? ?if(u.x == x && u.y == y){
?? ??? ??? ??? ??? ?return true;?? ?
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?return false;
?? ??? ?},
?? ??? ?hasFood : function(x,y){
?? ??? ??? ?if($s.DEBUG){
?? ??? ??? ??? ?var xt = $s($s.HEAD_LOCATION_ID);
?? ??? ??? ??? ?if(xt){
?? ??? ??? ??? ??? ?xt.innerHTML = "头部位置:(" +? x + "," + y + ")";?? ??? ?
?? ??? ??? ??? ?}?? ??? ??? ??? ?
?? ??? ??? ?}?? ??? ??? ??? ?
?? ??? ??? ?return this.food.locateOn(x,y);
?? ??? ?},
?? ??? ?setDebug : function(enable){
?? ??? ??? ?if(enable != $s.DEBUG){
?? ??? ??? ??? ?$s.DEBUG = enable;
?? ??? ??? ??? ?if($s.DEBUG){ // 显示
?? ??? ??? ??? ??? ?var i = $s($s.KEY_UP_DIR_ID);
?? ??? ??? ??? ??? ?$s.SnakeContext._show(i);
?? ??? ??? ??? ??? ?i = $s($s.HEAD_LOCATION_ID);
?? ??? ??? ??? ??? ?$s.SnakeContext._show(i);
?? ??? ??? ??? ?}else{ // 隐藏
?? ??? ??? ??? ??? ?var i = $s($s.KEY_UP_DIR_ID);
?? ??? ??? ??? ??? ?$s.SnakeContext._hide(i);
?? ??? ??? ??? ??? ?i = $s($s.HEAD_LOCATION_ID);
?? ??? ??? ??? ??? ?$s.SnakeContext._hide(i);
?? ??? ??? ??? ?}
?? ??? ??? ?}?? ?
?? ??? ?},
?? ??? ?_show : function(tag){
?? ??? ??? ?if(tag){
?? ??? ??? ??? ?tag.style.display = "block";?? ?
?? ??? ??? ?}?? ?
?? ??? ?},
?? ??? ?_hide : function(tag){
?? ??? ??? ?if(tag){
?? ??? ??? ??? ?tag.style.display = "none";?? ?
?? ??? ??? ?}?? ?
?? ??? ?},
?? ??? ?ondead : function(){ // Snake死亡时回调
?? ??? ??? ?if(this._startBn){
?? ??? ??? ??? ?this._startBn.disabled = true;
?? ??? ??? ?}
?? ??? ??? ?if(this._pauseBn){
?? ??? ??? ??? ?this._pauseBn.disabled = true;?? ?
?? ??? ??? ?}
?? ??? ??? ?if(this._stopBn){
?? ??? ??? ??? ?this._stopBn.disabled = true;?? ?
?? ??? ??? ?}
?? ??? ??? ?alert("挂了");?? ?
?? ??? ?},
?? ??? ?oneat : function(){ // Snake长度增加时回调
?? ??? ??? ?this._len.innerHTML = "长度:" + this.snake.units.length;?? ?
?? ??? ?},
?? ??? ?_startBn : null,
?? ??? ?_pauseBn : null,
?? ??? ?_stopBn : null,
?? ??? ?_restartBn : null,
?? ??? ?_len : null
?? ?};
?? ?
})();

?

  相关解决方案