當前位置:編程學習大全網 - 源碼下載 - 如何用javascript實現圍棋遊戲

如何用javascript實現圍棋遊戲

<head>

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

<title>禪棋傳說</title>

<style type="text/css">

div { position: absolute; width: 23px; height: 23px; }

.B0 { background-image: url('B0.gif'); }

.B1 { background-image: url('B1.gif'); }

.B2 { background-image: url('B2.gif'); }

.B3 { background-image: url('B3.gif'); }

.B4 { background-image: url('B4.gif'); }

.B5 { background-image: url('B5.gif'); }

.B6 { background-image: url('B6.gif'); }

.B7 { background-image: url('B7.gif'); }

.B8 { background-image: url('B8.gif'); }

.BX { background-image: url('BX.gif'); }

.D0 { background-image: url('D0.gif'); }

.D1 { background-image: url('D1.gif'); }

.C0 { background-image: url('C0.gif'); }

.C1 { background-image: url('C1.gif'); }

</style>

</head>

<body>

<script type="text/javascript">

//<![CDATA[

Array.prototype.indexOf = function (item) //給數組擴展壹個indexOf方法,用來檢索是否為"已知元素"

{

for ( var i=0; i<this.length; i++)

if (this[i] == item)

return i;

return -1;

};

var Site = //定義壹個棋位類

{

Create: function(x, y) //棋位類的構造函數

{

var me = document.createElement("div"); //建壹個div對象,將其擴展並封裝成棋位。

document.body.appendChild(me); //附加到DOM樹,實現棋位的呈現。

me.x = x; //記錄棋位的X坐標

me.y = y; //記錄棋位的Y坐標

me.style.left = x * 23 + "px"; //設置棋位水平方向的絕對位置

me.style.top = y * 23 + "px"; //設置棋位垂直方向的絕對位置

// var s = ((x-9)%9?0:(x-9)/9)+1+(((y-9)%9?0:(y-9)/9)+1)*3; //計算背景式樣,這個算法有冗余,簡化為下面的算法.

var s = parseInt((x-9)/9)+1+(parseInt((y-9)/9)+1)*3; //計算背景式樣

// me._backStyle = "B" + ((s==4&&(x/3)%2==1&&(y/3)%2==1) ? "X" : s);

me._backStyle = "B" + (((x/3)%2==1&&(y/3)%2==1) ? "X" : s);

me.Fill = this.Fill; //關聯壹個填充棋位的方法。

me.Tight = this.Tight; //關聯計算緊氣方法。

me.Kill = this.Kill; //關聯計算死子方法。

me.onclick = this.Play; //綁定onclick事件到Play方法。

me.Fill(); //初始填充空子。

return me; //返回棋位對象,其實是壹個封裝了的div對象。

},

Fill: function(dot, going) //填充棋子的方法,going~~是否"當前步".

{

if ( dot == undefined )

this.className = this._backStyle //無子,就設置為背景式樣。

else

this.className = (going ? "C" : "D") + dot; //有子,區別對待"當前步"

this.dot = dot; //保存棋子狀態

},

Play: function() //行棋方法,由onclick事件觸發

{

if ( this.dot == undefined ) //落子點必須為無子狀態,否則不處理.

{

var deads = this.Kill(current^1); //計算可以殺死的子,current為當前顏色,則current^1為對方顏色

if (deads.length == 1 && this == rob) return; //確認的打劫狀態後,直接拒絕;如果此步落子可以提不止壹子,則不是打劫

for(var i=0; i<deads.length; i++)

deads[i].Fill(); //按照死子列清空,one by one

if(i==1)

rob = deads[0] //如果此步只提了壹個子,記錄被提位置為打劫位置.

else if (i>0 || !this.Tight(current)) //這裏有壹個影響代碼效率的判斷,對於能產生提子的操做,不需要再判斷是否"緊氣禁入";此外,如果要引入"變窮為禁"的規則,這裏需要改變算法

rob = null //清打劫位,這個條件是判斷,如果能夠提多子,或者不是禁止著手,則解除"打劫"狀態

else return; //這裏對應的返回,應該是只有無氣禁入點的情況.

sound.play(); //落子有聲!

var step = Tracks[Tracks.length-1];

if(step) step.site.Fill(step.site.dot); //更新此前壹"步"的子的位圖

this.Fill(current, true); //填入當前"步"的子

Tracks.push( new Step(this, deads) );

current ^= 1; //用1來異或,正好反轉黑白棋子。

var disline = document.getElementById('list');

disline.value += ((current ? '黑:': '白:')+Tracks[Tracks.length-1].site.x+' '+Tracks[Tracks.length-1].site.y+'\n');

disline.scrollTop = disline.scrollHeight;

};

},

Tight: function (dot) //計算緊氣的塊,此時如果dot==undefined,則對應提子的遍歷,this指向當前點.

{

var life = this.dot == undefined ? this : undefined; //life為"氣"的定義;當前位無子則算壹口氣,對應落子的遍歷,當前位置必然無子.

dot = dot == undefined ? this.dot : dot; //這個邏輯是對應提子的遍歷

if (dot == undefined) return undefined;

var block = this.dot == undefined ? [] : [this]; //定義的"塊",在提子的遍歷中,發現子就放入塊,再判斷有多少"氣".

var i = this.dot == undefined ? 0 : 1;

var site = this;

while (true)

{

for(var dx=-1;dx<=1;dx++) for(var dy=-1;dy<=1;dy++) if(!dx^!dy)

{

link = GetSite(site.x + dx, site.y + dy);

if (link) //判斷目標位置的上下左右,有位則繼續,"無位"對應棋盤以外的區域.

if (link.dot != undefined) //有子,則判斷是否為同色,連"塊"

{

if (link.dot == dot && block.indexOf(link) < 0 )

block.push(link); //此壹段為"塊"的遍歷,條件是找四周的同色子,找到後判斷是否為新"知道","新"則放入"塊"

}

else if (!life) //無子,則更新"氣"

life = link

else if (life != link)

return undefined; //在提子的遍歷中,如果發現有兩"氣"了,則無須再算

};

if ( i >= block.length) break; //"塊"的遍歷結束條件為,列表的最後壹個對象沒有產生新的相鄰子.

site = block[i];

i ++;

};

return block; //返回只有壹口氣的塊,在提子的遍歷中,這對應了可能被提掉的子列,再去判斷是否為"打劫"

},

Kill: function(dot) //計算殺死的子,目前this指向落子點,dot指向需要判斷的死子顏色.

{

var deads = []; //定義死子列

for(var dx=-1;dx<=1;dx++) for(var dy=-1;dy<=1;dy++) if(!dx^!dy) //異或,有且只有壹個為真,可對應到相鄰子.

{

var site = GetSite(this.x + dx, this.y + dy);

if (site && (site.dot == dot))

{

var block = site.Tight(); //分別對上下左右進行遍歷,查找被緊氣的"塊",然後合並成為"死子列"

if (block) deads = deads.concat(block); //concat 合並操作,此操作並未識別"同項",僅以圍棋規則判斷,對"打劫沒有影響".

//如果需要準確的提子數目統計,這裏的算法需要更新.

};

};

return deads; //返回可以提子的死子塊

}

}; //棋位類 Site

var Board = new Array(19); //全局的Board數組,表示棋盤。

var Tracks = []; //行棋線索數組,數組元素是Step對象。

var current = 0; //當前要下的子,0表示黑子,1表示白子,交替。

var rob = null; //如果有打劫時,記錄打劫位置。

for(var x = 0 ; x < 19; x++)

{

Board[x] = new Array(19);

for(var y = 0; y < 19; y++)

Board[x][y] = Site.Create(x, y); //按位置創建棋位對象。

};

if (navigator.userAgent.indexOf(' MSIE ') > -1) //為IE瀏覽器構造聲音對象

{

var sound = document.body.appendChild(document.createElement("bgsound"));

sound.play = function(){this.src = "play.wav"};

}

else //為Firefox等其他瀏覽器構造聲音對象

{

var sound = document.body.appendChild(document.createElement("span"));

sound.play = function(){this.innerHTML = "<bgsound src='play.wav'>"};

};

document.body.oncontextmenu = function() //右鍵驅動悔棋事件

{

var step = Tracks.pop();

if (step)

{

step.site.Fill();

for (var i=0; i<step.deads.length; i++)

step.deads[i].Fill(current);

step = Tracks[Tracks.length-1];

if (step) step.site.Fill(current, true)

current ^= 1; //反轉黑白棋子。

};

return false; //不彈出菜單。

};

function GetSite(x, y) //從棋盤取棋位的函數,越界不拋出異常。

{

if (x>=0 && x<19 && y>=0 && y<19)

return Board[x][y];

};

function Step(site, deads) //棋步類,記錄每壹步棋的狀態

{

this.site = site; //記錄棋步的位置

this.deads = deads; //記錄被當前棋步殺死的棋子集合

};

function PrintWay() //行棋路線

{

var str='', coler='';

for (var i=0;i <Tracks.length;i++)

{

step = Tracks[i];

coler = (i%2) ? "白" : "黑";

str=str+"第"+(i+1)+"步"+coler+"方 X"+step.site.x+" Y"+step.site.y+" \n";

}

alert(str);

}

document.body.ondblclick = PrintWay;

document.onkeypress = function(event)

{

var k = (window.event ? window.event.keyCode : event.which) - 49; //按'1'可以進入自動擺棋操作,'1'=0x31=49

if(k<0 || k>1) return;

for(var x=0; x<19; x++) for(var y=0; y<19; y++) Board[x][y].Fill();

Tracks.length = 0;

current = 0;

with(goes[k]) for(var i=0; i<length;i+=3)

Board[charCodeAt(i+1)-65][charCodeAt(i)-65].Fill(charCodeAt(i+2)-48);

};

</body>

</html>

  • 上一篇:叮咚買菜付款說版本過低怎麽回事
  • 下一篇:關於PHP中SESSION取值的問題?
  • copyright 2024編程學習大全網