如何用javascript实现围棋游戏

& lthead & gt

& ltmeta http-equiv = " Content-Type " Content = " text/html;charset=utf-8" />

& lttitle & gt禅棋传奇

& ltstyle type="text/css " >

div {位置:绝对;宽度:23px高度:23px}

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

. b 1 { background-image:URL(' b 1 . gif ');}

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

. B3 {背景-图像:URL(' B3 . gif ');}

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

. b5 { background-image:URL(' b5 . gif ');}

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

. B7 {背景-图像:URL(' B7 . gif ');}

. b8 { background-image:URL(' b8 . gif ');}

。BX {背景-图像:URL(' bx . gif ');}

. d0 { background-image:URL(' d0 . gif ');}

. d 1 { background-image:URL(' d 1 . gif ');}

. c0 { background-image:URL(' c0 . gif ');}

. c 1 { background-image:URL(' c 1 . gif ');}

& lt/style & gt;

& lt/head & gt;

& ltbody & gt

& ltscript type = " text/JavaScript " & gt;

//& lt;![CDATA[

array . prototype . indexOf = function(item)//对数组扩展一个index of方法,检索是否为“已知元素”。

{

for(var I = 0;我& ltthis .长度;i++)

if (this[i] == item)

返回I;

return-1;

};

Var Site = //定义一个棋位类。

{

Create: function(x,y)//chess类的构造函数。

{

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 = parse int((x-9)/9)+1+(parse int((y-9)/9)+1)* 3;//计算背景样式

//我。_ back style = " B "+((s = = 4 & amp;& amp(x/3)% 2 = = 1 & amp;& amp(y/3)%2==1)?“X”:s);

我。_ back style = " B "+(((x/3)% 2 = = 1 & amp;& amp(y/3)%2==1)?“X”:s);

我。填充=这个。填充;//关联填充国际象棋位置的方法。

我。紧=这个。紧绷;//气密性的相关计算方法。

我。杀=这个。杀;//关联计算死子方法。

me.onclick = this。玩;//将onclick事件绑定到Play方法。

我。fill();//最初填补空白。

还我;//返回棋位对象,实际上是封装的div对象。

},

Fill: function(dot,going) //填充棋子的方法,是否going~~是“当前步”。

{

if(点==未定义)

这个。classname = this。_ back style//如果没有子项,则设置为背景样式。

其他

this.className =(去哪里?“C”:“D”)+dot;//如果有孩子,区别对待“当前步骤”。

this.dot = dot//保存棋子状态

},

Play: function() // chess方法,由onclick事件触发。

{

If (this.dot == undefined) //放置点必须处于无子级状态,否则不会被处理。

{

var deads = this。kill(current^1);//计算可以杀死的孩子。如果current是当前颜色,那么current 1是相反的颜色。

if(deads . length = = 1 & amp;& ampthis == rob)返回;//抢劫身份确认后,直接拒绝;如果这步棋你能背一个以上的儿子,那就不算抢劫。

for(var I = 0;我& lt空载长度;i++)

死者[我]。fill();//根据死子列清空,一个一个。

if(i==1)

rob = dead[0]//如果这一步只有一个孩子被举起,记录举起的位置为抢劫位置。

else if(I & gt;0 || !这个。紧(当前))//存在影响代码效率的判断。对于能生产电梯的作业,不需要判断是否“禁止入内”;另外,如果要引入“化贫为禁”的规则,这里需要改变算法。

Rob = null //清除抢劫位。这个条件就是判断。如果你能多养几个孩子,或者不禁止你下手,你就从抢劫状态中解脱了。

否则返回;//这里对应的返回应该是只有没有进气点的情况。

sound . play();//有声音!

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

if(步骤)step.site.Fill(步骤. site . dot);//更新上一步子级的位图。

这个。填充(当前,真);//填写当前“步骤”

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

当期^= 1;//与1异或,只需颠倒黑白棋子即可。

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

disline.value +=((当前?黑色:':'白色:')+曲目[曲目。长度-1]。site.x+''+tracks [tracks。长度-1]。site . y+' \ n ');

disline . scroll top = disline . scroll height;

};

},

紧:function (dot) //计算紧凑块。此时,如果dot==undefined,对应的是电梯的遍历,这个指向当前点。

{

var life = this.dot == undefined?这个:未定义;//生命是“气”的定义;如果现在的职位没有孩子,那就是松了一口气。对应下落子的遍历,当前位置必须没有子。

dot = dot ==未定义?this . dot:dot;//这个逻辑是对应电梯的遍历。

if (dot == undefined)返回undefined;

var block = this.dot == undefined?[]:[这个];//定义的“块”,在葡萄干的遍历中,找到葡萄干就放入块中,然后判断有多少“气”。

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

var site = this

while(真)

{

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

{

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

If (link) //确定目标位置的上下左右。如果有位置,继续。如果没有位置,则对应棋盘外的区域。

if (link.dot!= undefined) //如果有子,则判断是否是同色,甚至是“块”

{

if(link . dot = = dot & amp;& ampblock . index of(link)& lt;0 )

block.push(链接);//这段是“块”的遍历,前提是找到周围的同色,找到后判断是否是新的“知”,把“新”放进“块”。

}

else if(!命)//无子女,则更新“齐”

生活=链接

else if(生活!=链接)

返回未定义的;//在葡萄干的遍历中,如果找到两个“齐”,就不用再计算了。

};

如果(i & gt= block . length)break;//遍历“块”的结束条件是列表中的最后一个对象不产生新的相邻子对象。

site = block[I];

i++;

};

返回块;//只用一口气返回块。在电梯的遍历中,这对应着可能被删除的子列,然后判断是不是“劫”

},

Kill: function(dot) //计算被杀死的孩子。目前这个指向滴点,dot指向需要判断的死亡儿童的颜色。

{

var deads =[];//定义死的子列

for(var dx =-1;dx & lt=1;dx++)for(var dy =-1;dy & lt=1;dy++) if(!dx^!Dy) // XOR,有且仅有一个为真,可以对应相邻子。

{

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

如果(网站& amp& amp(site.dot == dot))

{

var块=站点。紧();//分别上下左右遍历,找到被压缩的“块”,然后合并成“死子列”

if(block)deads = deads . concat(block);//concat merge运算,不识别“同项”,只按围棋规则判断,对“劫”没有影响。

//如果需要精确统计升降人数,这里的算法需要更新。

};

};

返回deads//返回可以提升的死子块。

}

};//象棋网站

var板=新数组(19);//全局棋盘数组,代表棋盘。

var Tracks =[];//象棋线索数组,数组元素为Step对象。

var电流= 0;//当前子,0表示太阳黑子,1表示白子,交替。

var rob = null//如果有抢劫,记录抢劫位置。

for(var x = 0;x & lt19;x++)

{

Board[x] =新数组(19);

for(var y = 0;y & lt19;y++)

Board[x][y] = Site。创建(x,y);//按位置创建象棋对象。

};

if(navigator . user agent . index of(' MSIE ')& gt;-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 = " & lt;bgsound src = ' play.wav ' & gt};

};

文档。body . on context menu = function()//右键驱动后悔棋事件。

{

var step = tracks . pop();

如果(步骤)

{

step . site . fill();

for(var I = 0;我& lt步长;i++)

step.deads[i]。填充(当前);

step = Tracks[Tracks . length-1];

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

当期^= 1;//颠倒黑白棋子。

};

返回false//不弹出菜单。

};

函数GetSite(x,y) //从棋盘上取棋位的函数,过线时不抛出异常。

{

if(x & gt;= 0 & amp& ampx & lt19 & amp;& ampy & gt= 0 & amp& ampy & lt19)

返回板[x][y];

};

功能步骤(地点,死亡)//棋步类别,记录每一步棋的状态。

{

this.site = site//记录移动的位置

this.deads = deads//记录当前棋步杀死的棋子集合。

};

函数PrintWay() //国际象棋路线

{

var str= ' ',coler =

for(var I = 0;我& lt轨道.长度;i++)

{

步骤=轨道[I];

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

str = str+" Di "+(I+1)+" Bu "+coler+" Fang X "+Step。网站。x+" Y "+步进。网站。y+" \ n ";

}

alert(str);

}

document . body . ondblclick = print way;

document.onkeypress = function(事件)

{

var k = (window.event?window . event . key code:event . which)-49;//按‘1’进入自动下棋操作,‘1’= 0x 31 = 49。

if(k & lt;0 | | k & gt1)返回;

for(var x = 0;x & lt19;x++)for(var y = 0;y & lt19;y++)板[x][y]。fill();

tracks . length = 0;

电流= 0;

with(goes[k])for(var I = 0;我& lt长度;i+=3)

board[charCodeAt(I+1)-65][charCodeAt(I)-65]。fill(charCodeAt(I+2)-48);

};

& lt/body & gt;

& lt/html & gt;