没有写博客的习惯,这篇算心血来潮,算篇近几天编写的小程序纪实.
以编写此程序的方式结束Javascript的本阶段的学习.编写的目的在于熟悉javascript的编程方式,包括代码风格,面向对象的运用等.
回到程序,说说Snake的移动的实现方法.其实很简单,向头部添加Unit,然后删除尾部.其他,参见注释.
程序包括一个html文件:snake.html和一个js文件:snake.js
snake.html:
$s(function(){
$s.SnakeContext.init();
});
snake.js:
1.沒有牆壁,左與右連接,上與下連接. * 2.蛇頭碰撞到自身時死亡. * 相容性: * 調試部分) * * 作者:pcenshao * 轉載請註明來自: * http://blog.cs.net/pywepe
* http://blog.cs /
(function(){
$s = function(){
if(typeof arguments[0] == "string"){
return document.getElementById(arguments[0]);
}else if(typeof arguments[0] == "function"){🠜𠟠 = arguments[0];
}
}
$s.UNIT_WIDTH = 10; // 單元的寬度 $s.UNIT_HEIGHT = 10; $s.PANEL_HEIGHT = 20; // 邏輯高度 $s.STEP = 250 ; // 每一步的時間 $s.HEAD_COLOR = "red"; // 蛇頭顏色
* 食物的顏色 */ $s.COLORS = ["blue","green","#494e8f","#905d1d","#845538"#84557575d ; /* * 除錯相關 * $s.DEBUG 存在處理開關 * $s.DEBUG 存在.不顯示 * $s .HEAD_LOCATION_ID 監視蛇頭位置的結點id,若不存在,則不顯示 */ $s.DEBUG = false; CATION_ID = "headLocation "; $s.Dir = { // 代表方向,強制以$s.Dir.UP方法呼叫,避免參數錯誤
LEFT : { },
RIGHT : {},
NONE : {}
STOP : {},
RUNNGIN : {},
: {}
};
$s.Unit = function(){Min
¢ this.x = 0;
this .y = 0;
this.view = new $s.UnitView();
};
$s.Unit .prototype.repaint = function(){
if(this.view != null){
}
};
$s. Snake = function(){
this.units = [];
};
$s.Snake.prototype.init = function(dir,count){
var x = 5;
; i
var u = new $s.Unit();
u.
this.units.push(u); if(i == (count - 1 )) { u.color = $s.HEAD_COLOR; } }; $s.Snake.prototype.crash = f$s.Snake.prototype.crash = function(){unction(x,y){unction( // 傳入頭部的位置,回傳true表示碰撞本身
for(var i = this.units.length - 2 ; i >= 0 ; i --){ // 不包括頭本身 this.units[i];
}
}
return false;
.prototype.go = function(){ // 判斷前方是否有食物 // 是否有對鎠 var head = this.units[this.units.length - 1]; _x = head.x; _y = head.y;
if(this.crash(_x,_y)){ // 判斷是否碰撞到自身
$s.SnakeContext.stop();
return;
}
Dir.LEFT){
_x --;
_x ++;
}else if(dir == $s.Dir.UP) {
_y --;
}else if(dir = }
// 實現左右連結,上下連線 >= $s.PANEL_WIDTH){
_x = 0;
_x = $s.PANEL_WIDTH - 1;
}
_ }
_ if( PANEL_HEIGHT){
_y = 0;
}🎠 _y = $s.PANEL_HEIGHT - 1;
}
// 新頭
if($s.SnakeContext.hasFood(_x,_y)){ // 下一步碰到食物
this.units[this.units.length - 1] ; // 因為eat方法可以改變頭部,所以重新取得
_x = head.x;
if(dir == $s.Dir.LEFT){
--;
}else if(dir == $s.Dir.RIGHT){ }else if(dir == $s.Dir.UP){
}else if(dir == $s.Dir.DOWN){ head.color = $s.HEAD_COLOR; .units[this.units.length - 2]; oldHead.color = $s.BODY_COLOR;
return;
}
();
$s.NodePool.releaseNode(tail);
h.y = _y;
this.units.push(h);
.units.length - 1; i >= 0; i --){
var u = this.units[i];
u.color = $s.HEAD_COLOR;
u.color = $s.BODY_COLOR;
}
};
$s.Snake.prototype.eat = function(x,y){
var food = $s.Snake food.alive = false;
this .units.push(food.unit);
$s.SnakeContext.oneat();
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);
. return {x:x ,y:y}; } };this.unit = new $s.Unit( );
this.unit.x = x;
this.unit.y = y;
LOp. length - 1) ];
this.unit.color = color;
this.alive = true;
}; $s.Food.prototype.locateOn = function(x ,y){ return this.unit.x == x && this.unit.y == y; };目的是提高效率
* 因為snake的移動是透過刪除尾部結點並向頭部添加結點實現的,
* 在這個過程中會有大量的結點創建操作,為了操作效率,所以對結點進行池化管理.
* 尾部的結點不刪除,而是隱藏,需要結點時可以重複使用
*/
};
$s.NodePool. _findHideNode = function(){ // 尋找隱藏的div結點
for(var i = 0 ; i
if(n.style.display == "none"){
return n; 🎠 }
return null;
};
$s.NodePool.createNode = function(){
$s.NodePool.createNode = function(){🎠 pooledNode = this._findHideNode();
if(pooledNode != null){
var newNode = document.createElement("div");
newNode);
return newNode;
}
if(node != undefined && node != null){
if(node instanceof $s.Unit){
var view = node.view;
var div = view.node;
}
}
}
}
$s.Unit
this.node = null; }; $s.UnitView。 prototype.repaint = function(){ if(this.node == null){ // 初始化 tag.style.width = $s.UNIT_WIDTH + "px"; tag.style.height = $s.UNIT_HEIGHT + "px"; tag.style.borderWidth = "1px"; 標籤.樣式.borderColor = "白色"; tag.style.margintLeft = "1px"tag.style.marginTop = "1px";
tag.style. marginBottom = "1px";
tag.style.backgroundColor = this.unit.color; // 顏色由模型單位指定
tag.style.position = "absolute";位置指定為絕對時,表示孩子相對容器絕對定位。
tag.style.display = "block"
var x = this.unit.x * $s.UNIT_WIDTH;
= this.unit.y * $s.UNIT_HEIGHT;
tag.style.top = y + "px";
this.node = tag;
$s.SnakeContext.panelView.append(this) ;
var x = this.unit.x * $s.UNIT_WIDTH; var x = this.unit.x * $s.UNIT_WIDTH; = this.unit.y * $s.UNIT_HEIGHT;
tag.style.top = y + "px"; tag.style.backgroundColor = this. unit.color; } } ;
var panel = document.createElement("div");
.style.width = ($s.PANEL_WIDTH * $s.UNIT_WIDTH ) + "px";
panel.style.height = ($s.PANEL_HEIGHT * $s.UNIT_HEIGHT ) + .borderStyle = "dotted";
面板。 style.borderColor = "紅色";
panel.style.borderWidth = "1px";
"auto";
panel.style.marginTop = "50px";
panel.style.position = "relative"; panel.style.position = "relative"; panel .style.marginBottom = "auto";
this.node = panel;
var len = document.createElement("div");
len.style. marginLeft = "auto";
len.style.marginRight = "auto";
len.
len.style.fontSize = "12px";
len.innerHTML = "長度:";
document.body.appendChild(len);Conpmmo.
var startBn = document.createElement("button "); startBn.innerHTML = "開始"; startBn.style.marginLeft$s.SnakeContext.run();
};
$s.SnakeContext._startBn = startBn;
var pauseBn = document.createElement("button");
pauseBn.innerHTML = "暫停";
pauseBn.style.marginLeft = "10px";
pauseBn.onclick = function(){
};
$s.SnakeContext._pauseBn = pauseBn;
body.appendChild(pauseBn);
/*
stopBn.innerHTML = "停止";
stopBn.style.marginLeft = "10px";
stopBn.onclick = function(){
$s. $s.SnakeContext._stopBn = stopBn;
document.body.appendChild(stopBn);
restartBn.style.marginLeft = "10px";
restartBn.onclick = function(){
window.location.href = window.location.href;
}; document.body.appendChild(restartBn);
"div");
line.style.height = "10px";
var span = document.createElement("span");
span.style.color = "gray";
span.style.fontSize = "12px";
document.body.appendChild(span); var 調試= document.createElement("input"); debug.type = "checkbox"; debug.checked = $s.DEBUG; debug.onchange = function(){ }; document.body.appendChild(debug); View; 嘗試{ this.node.appendChild(unitView.node); }catch(e){ 警報(e); } }; * 指定__根的成員為成員成員 * 啟動程序的方法: * window.onload = function () { * $s.SnakeContext.init(); * } 目錄: $s.Dir.NONE, 州: $s.State .STOP , goTimer : null, if(this.state != $s.State.RUNNGIN){}, : function(){ 暫停: function(){ this._set狀態($s.State.PAUSE ); }, _setState : 函數{
window.clearInterval(this.goTimer);
this.state = s;
}
for(var f in this.foods){
if(f.x == x && f.y == y){
} } 返回 null; }, 初始化函數(){this.panelView = new $s.PanelView(); this.snake = new $s.Snake() ; this.dir = $s.Dir.DOWN; this._len.innerHTML = "長度:" + 3;
? window.event.keyCode;
}其他{
code = e.keyCode;
}
var str = "";
var oldDir = $s.SnakeContext.dir;
switch(code){
案例37: // 左
.Dir.RIGHT){
一樣為 $
}
str = "左";
休息;
案例 38 : // 向上
if($s.SnakeContext.dir != $s.Dir.DOWN){
$s.SnakeContext.目錄= $s.Dir.UP;
}
str = "向上";
休息;
案例39: // 右
if($s.SnakeContext.dir != $s.Dir.LEFT){
$s.SnakeContext.dir = $s.Dir.RIGHT;
str = "右";
案例40: // 向下
if($s.SnakeContext.dir ! ){
$s.SnakeContext.目錄= $s.Dir.DOWN;
}
str = "向下";
休息;
}
if($s.SnakeContext.dir != oldDir ){
if($s.DEBUG){
.KEY_UP_DIR_ID);
v.innerHTML = "方向鍵:" + str;
}
}
if($s.SnakeContext .goTimer! =空白) {
window.clearInterval $s.SnakeContext.goTimer = null;
$ s.snakecontext.snake.go();
$ s.snakecontext.gotimer = window.setInterval(function(){
$ s.snakecontextup );
}
🎠 var loc = $s.Random.randomLocation($s.PANEL_WIDTH - 1, $s.PANEL_HEIGHT - 1); loc.x,loc.y); },panelView : null, 食物: null , if(this.food.alive){ // 目前食物還有一個 return; ?
loc = $s.Random.randomLocation($s.PANEL_WIDTH - 1,$s.PANEL_HEIGHT - 1);
);
this.food = new $s.Food(loc.x,loc.y);
Overlap : function(loc){ // 檢查是否與Snake重疊,重疊時回傳true
var x = loc.x;
its.length ; i ++ ){
var u = this.snake 。單位[i];
}
},
hasFood : 函數(x,y){
if($s.DEBUG){
if(xt){
xt.innerHTML = "頭部位置:(" + x + "," + xt.innerHTML = "頭部位置:(" + x + "," + x + "," + y+「)」;
}
return this.food.locateOn(x,y) : 函數(啟用){
if(啟用!= $s.DEBUG) {
$s .DEBUG = 啟用;
var i = $s($s.KEY_UP_DIR_ID);
i = $s ($s.HEAD_LOCATION_ID); i);
}else{ //
$s .SnakeContext._hide( i);
i = $s($s.HEAD_LOCATION_ID); $s.SnakeContext._hide(i);
}
_show : 函數(標籤){
if (標籤){
tag.style.display = "block";
}
},
_hide : 函數(標籤){
if(tag){
tag.style. display = "無」;
}
if(this._startBn){
if(this._pauseBn ){ this._pauseBn.disabled = true; } if(this._stopBn){ this._stopBn.disabled = true; }
alert("掛了");
},
this._len.innerHTML = "長度:" + this.snake.units.length;}, _startBn : null,
_restartBn : null,
_len : null