不管是写法 还是逻辑结构上 都有待提高 希望园子里的高手拍砖 提意见
<!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>Untitled Page</title>
<style>
.snake_table { border:1px solid black; }
.snake_table td { width:10px; height:10px; }
.snake_table_over { background:black; }
.snake_table_over td { width:10px; height:10px; }
.snake_tdSelect { background:black; }
.snake_tdFood { background:blue; }
</style>
<script>
function FixFunc(_this, func) {
if (arguments.length > 2) { var f = function () { func.apply(_this, Array.prototype.slice.call(arguments, 2)); } }
else { var f = function () { return func.apply(_this); } } return f;
}
var Snake = {};
Snake.Subject = function (user) { this.Center = user; }
Snake.Subject.prototype = {
Center: null,
Channel: [{ x: 9, y: 9 }, { x: 9, y: 10 }, { x: 9, y: 11}],
speed: 50,
length: 3,
fix: "right",
lastfix: null
}
Snake.Control = function () { }
Snake.Control.prototype = {
KeyBoard: function (evt) {
if (window.event) { evt = window.event; }
var keycode = evt.keyCode || evt.charCode;
Snake.Game.ChangeFix(keycode);
}
}
Snake.Map = function () { }
Snake.Map.prototype = {
x: 20,
y: 20,
element: null,
config: { subClass: "snake_tdSelect", foodClass: "snake_tdFood" },
Build: function () {
var t = []; t.push("<table class='snake_table'>");
for (var i = 1; i <= this.x; i++) {
t.push("<tr>");
for (var j = 1; j <= this.y; j++) { t.push("<td></td>"); }
t.push("</tr>");
}
t.push("</table>");
if (document.getElementById("snake_div")) { //
document.getElementById("snake_div").innerHTML = t.join("");
this.element = document.getElementById("snake_div").firstChild;
}
else { alert("没有找到指定容器"); }
},
BuildFrom: function () { }, //暂时搁置
FindCell: function (x, y) { return this.element.rows[x].cells[y]; }, //找到某行某列的cell
SelectCell: function (x, y) { var el = this.FindCell(x, y); el.className = this.config.subClass; },
UnSelectCell: function (x, y) { var el = this.FindCell(x, y); el.className = ""; },
FoodCell: function (x, y) { var el = this.FindCell(x, y); el.className = this.config.foodClass; },
UnFoodCell: function (x, y) { var el = this.FindCell(x, y); el.className = ""; }
}
Snake.Game = {
element: null, hasBorder: false, map: null, control: null, subject: null, LxObj: null, hasNew: false, keytime: 0, score: 0,
config: { subClass: "snake_tdSelect", foodClass: "snake_tdFood", GameOver: "snake_table_over" },
food: { x: 0, y: 0 },
Init: function () {
//初始化对象
this.map = new Snake.Map(this);
this.control = new Snake.Control(this);
this.subject = new Snake.Subject(this);
document.onkeydown = this.control.KeyBoard; //注册键盘事件
this.map.Build(); //创建画布
this.element = this.map.element; //填充element
this.InitSnake(); //初始化 subject
this.NewFood(); //初始化 食物
this.LxObj = setInterval(FixFunc(this, this.OnTime), this.subject.speed); //开始
},
OnTime: function () { this.Move(); },
InitSnake: function () {
var td;
for (var i = 0; i < this.subject.Channel.length; i++) {
td = this.map.FindCell(this.subject.Channel[i].x, this.subject.Channel[i].y);
td.className = this.config.subClass;
}
td = null;
},
Move: function () {
var s = this.subject, first = s.Channel.length - 1;
var newSubject = { x: s.Channel[first].x, y: s.Channel[first].y };
this.NextPlace(s.fix, newSubject);
if (!this.Afoul(newSubject)) return;
if (!this.hasNew) { //是否有新的
var lastel = s.Channel.shift();
this.map.UnSelectCell(lastel.x, lastel.y);
} else { this.hasNew = false; }
s.Channel.push(newSubject);
this.InitSnake(); //画snake
},
NextPlace: function (fix, cur) { //
switch (fix) {
case "right":
if (!this.hasBorder && cur.y >= (this.map.y - 1)) { cur.y = 0; }
else if (cur.y >= (this.map.y - 1)) { this.End(); }
else { cur.y = cur.y + 1; }
break;
case "left":
if (!this.hasBorder && cur.y <= 0) { cur.y = this.map.y - 1; }
else if (cur.y <= 0) { this.End(); }
else { cur.y = cur.y - 1; }
break;
case "up":
if (!this.hasBorder && cur.x <= 0) { cur.x = this.map.x - 1; }
else if (cur.x <= 0) { this.End(); }
else { cur.x = cur.x - 1; }
break;
case "down":
if (!this.hasBorder && cur.x >= (this.map.x - 1)) { cur.x = 0; }
else if (cur.x >= (this.map.x - 1)) { this.End(); }
else { cur.x = cur.x + 1; }
break;
}
},
NewFood: function () { //新食物
var x = parseInt(Math.random() * 19);
var y = parseInt(Math.random() * 19);
for (var i = 0; i < this.subject.Channel.length; i++) {
if (x == this.subject.Channel[i].x && y == this.subject.Channel[i].y) { return this.NewFood(); }
}
this.food = { "x": x, "y": y };
this.map.FoodCell(x, y); //设定className
},
Afoul: function (json) { //撞击
this.EatFootd(json);
if (this.hasBorder) { //有边界的情况
if ((this.map.x - 1) < json.x || (this.map.y - 1) < json.y || json.x < 0 || json.y < 0) { this.End(); return false; }
}
var arr = this.subject.Channel;
for (var i = 0; i < arr.length; i++) {
if (arr[i].x == json.x && arr[i].y == json.y) { this.End(); return false; }
}
return true;
//可以穿墙的情况
},
EatFootd: function (json) {
if (this.food.x == json.x && this.food.y == json.y) {
this.ScoreTotal();
this.NewFood();
this.hasNew = true;
}
},
ScoreTotal: function () {
this.score += 500 / this.subject.speed;
document.getElementById("score_span").innerText = this.score;
},
End: function () {
clearInterval(this.LxObj); //先结束
//this.element.className = this.config.GameOver;
},
ChangeFix: function (code) { ///*Snake.Game*/
var tmpTime = new Date().getTime();
if ((tmpTime - this.keytime) < this.subject.speed) return;
this.keytime = tmpTime;
this.subject.lastfix = this.subject.fix;
switch (code) {
case 37: //left
if (this.subject.fix == "right" || this.subject.fix == "left") return;
this.subject.fix = "left";
break;
case 38: //up
if (this.subject.fix == "down" || this.subject.fix == "up") return;
this.subject.fix = "up"; break;
case 39: //right
if (this.subject.fix == "left" || this.subject.fix == "right") return;
this.subject.fix = "right"; break;
case 40: //down
if (this.subject.fix == "up" || this.subject.fix == "down") return;
this.subject.fix = "down"; break;
}
}
}
window.onload = function () { Snake.Game.Init(); }
</script>
</head>
<body>
<div id="snake_div">
</div>
<div id="score_div">
得分:<span id="score_span"></span>
</div>
</body>
</html>