js 贪吃蛇

不管是写法 还是逻辑结构上 都有待提高 希望园子里的高手拍砖 提意见

<!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>

posted @ 2011-02-20 19:03  CallMeTommy  阅读(390)  评论(3编辑  收藏  举报