找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24931|回复: 32

js实现的单机双人象棋演示及其分析

[复制链接]
发表于 2004-9-1 21:55:00 | 显示全部楼层 |阅读模式
本程序实现的功能为本地二人对弈中国象棋,实现语言为javascript+VML,在windows 2000 pro+IE 6sp1的环境下测试通过。
程序默认的起始颜色为红色,只有执红色一方可以先走棋,双方轮流下棋,老将被吃则认为输棋,棋局结束,可以通过刷新页面重新开始。
下棋的时候,点击要走的棋子,将显示当前可走位置(小矩形)和可吃位置(加上红色框标记),然后点击对应位置即可走棋。如果要改选其他棋子,直接点击即可。

程序的演示地址:
http://island.vip51.dig86.com/chess/chess.htm


设计概述:
在一个复杂的、有界面、有交互的程序中,将控制模块与表现模块区分,分别编写是很有效的做法。这样能够使对界面、运算等的操作集中统一,便于修改与测试。
在整体设计上,本程序采用了将判断可行位置算法下放的做法。传统的象棋程序一般先取得欲移动棋子类型,然后由统一的算法判断目标位置是否可行。本程序把判断目标位置是否合法的方法下放到棋子,控制模块在判断当前走法合法性的时候,取得这个棋子对象,并且调用此对象的canGo方法来判断目标位置是否可行,这种做法比较有利于让程序充分体现面向对象特性。
棋盘单独作为一个模块实现,它具有一定规模,且实现了一个针对性比较强的功能,因此将它与其他模块隔离,单独编写。这个模块的主要事件集中在图形化效果的表现,同时也应当主意结构的层次性和合理性,并且应当向外界提供所生成棋盘的引用,让控制模块可以将棋子挂接在这个根元素上。
棋子本质为div对象,包含了一个图标文件,并且具有附加属性,如:颜色、种类、位置等。各种棋子有不少相似属性,但是具体差别还是不小,比如各棋子的判断可行位置走法。因此,先编写一个具有普遍性的棋子模块,拥有棋子的基本属性:坐标、图标、当前是否被攻击等情况,然后分别对于每种棋子,创建单独的模块。这个过程中采用了一种“伪继承”技术:在单独的棋子模块中,创建了一个通用的棋子变量,并且对它附加了一个canGo方法,然后,把这个棋子变量作为自己的创建结果返回出去。
为什么称这个为“伪继承”呢?很明显,js并不支持继承,而且,继承的实现方法并非如此。但是,我们做了继承所做的事情,即为父类型的对象添加了属性、方法,因此扩展了它的属性和方法,并且,最后将扩展完成的对象当作自己构造出来的对象返回出去,使得结果对象除了具有父对象的属性、方法,还拥有自己特有的属性及方法,因此,我们可以说这是某种形式的继承。
在程序中建立了一个全局二维数组situation用于保存棋子列表,各棋子对象存放其自身坐标等信息,还定义了各常量用于标记棋子颜色、种类等通用信息。
程序中所使用的资源文件有棋子图标及标记可走位置的图标。棋盘为VML代码绘制,各棋子分别置于单个div中,由一个外部的HTC文件控制其行为。这个HTC做了这样的事情:在点击当前棋子所在的div时,HTC中的check函数对当前点击对象进行处理,决定应当走棋或者其他操作。
在点击棋子时,将根据遍历棋盘坐标代入该棋子canGo方法的结果,取得可以移动的位置。如果这些位置当前没有棋子,则认为是可走位置,在对应位置产生一个Blank对象,放置一个提示图标。Blank对象同样是棋子模块的伪继承,它没有canGo方法,只保存了基本属性,专门用于标志可走位置。如果这些位置当前存在棋子,并且棋子的颜色与自身不同,则认为是可吃位置,将对应棋子加上红色边框标记,同时将其beAttack属性设为真。这样,走棋的时候即可据此判断。
走棋后,程序需要清除以前那些过期的标记,这是通过一个遍历实现的,从棋盘中检索到灰色对象,即认为它是标记,直接清除。另外,吃子的实现比较复杂,反复尝试replaceChild方法以后放弃了,因为遇到意想不到的问题,所以通过遍历检索来取代被吃棋子。这个步骤似乎可能有比较简便的实现方法,希望高手指教。

附记:很久以前,在51js论坛看见幻宇前辈的js版星际,就产生做这个象棋的念头,然后花一个小时参考美洲豹的VML教程写了棋盘,却因为各种原因搁置了。这次重新捡起来,花了一天半时间写了其他所有部分,测试了一会,没发现bug,先发布出来,给大家玩玩。有兴趣的朋友可以继续做,做成能够联机的版本,不是很难。此外,我暂时有一个部分没有设计,就是老将见面的判断,有空补上,hoho。基本的说明就先写这么多,以后慢慢把各部分代码加上注释,发在这里,大家不要着急啊。
发表于 2004-9-1 21:59:00 | 显示全部楼层
谁想办法用HTA模拟写一个吧。

PS:得,我没时间。不要叫我做 :)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-1 22:01:00 | 显示全部楼层
hta我一点都不会,不过无所谓啊,想来也不用多久,我这个不过花了两天,hoho。不许偷懒,你自己出题自己给我做出来,不然扁你。
回复 支持 反对

使用道具 举报

发表于 2004-9-2 06:46:00 | 显示全部楼层
好东西,顶一下~
回复 支持 反对

使用道具 举报

发表于 2004-9-2 19:40:00 | 显示全部楼层

还可以

不错啊
回复 支持 反对

使用道具 举报

发表于 2004-9-2 20:16:00 | 显示全部楼层
楼主可否分享一下源代码啊,谢谢!!!
回复 支持 反对

使用道具 举报

发表于 2004-9-2 23:49:00 | 显示全部楼层
楼上的真好玩。

代码就在源文件里了还要问?看来是习惯了。
回复 支持 反对

使用道具 举报

发表于 2004-9-5 10:36:00 | 显示全部楼层
哇,拿这里来啦~
你的演示地址有效么,或者是你的程序不支持FireFox。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-5 12:49:00 | 显示全部楼层
我晕,居然是你。FireFox是什么?我的演示正常啊,panliu888,zm,洛林,帅青蛙他们都看过的啊。
回复 支持 反对

使用道具 举报

发表于 2004-9-6 03:25:00 | 显示全部楼层
http://www.w3cn.org/resource/down/2004/87.html

htc需要IE5+
VML需要IE5.5+
这些在firefox上都不跑,而且firefox不支持以直接ID名引用作为对象。。

我觉得这种程序支持不支持firefox 问题不大。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-6 07:38:00 | 显示全部楼层
……,是个浏览器啊,我感觉没有HTC还可以做,要是没有VML,那棋盘就只能拿图片做?哎呀,这个,还是只支持IE算了。
回复 支持 反对

使用道具 举报

发表于 2004-9-6 20:53:00 | 显示全部楼层
支持打谱就好了

可以读谱,存谱,甚至有点智能可以人机对战就好了
回复 支持 反对

使用道具 举报

发表于 2004-9-6 23:26:00 | 显示全部楼层
http://www.chinagamedev.net/cgd/develop/ai/200111/MultiProbCut.htm

岛主拿去看看。给你1个月的时间吧。够兄弟吧。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-7 08:32:00 | 显示全部楼层
唉唉,我早就用C++实现了Alpha-Beta剪枝算法,可以有不错的智能,但是要移植到js要费很大很大的功夫,我现在哪里能找到一个月的空闲啊,以后再说吧。
回复 支持 反对

使用道具 举报

发表于 2004-9-8 02:57:00 | 显示全部楼层
演示有错误! 将帅可以露脸!~
回复 支持 反对

使用道具 举报

发表于 2004-9-9 11:19:00 | 显示全部楼层
共享一下代码?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-9 15:15:00 | 显示全部楼层
liuhuasen在上个帖子中说
共享一下代码?


……,无语了。直接查看代码,下载那几个文件。最简单的方法,直接保存页面。这样够直接了吧。
回复 支持 反对

使用道具 举报

发表于 2004-9-11 16:44:00 | 显示全部楼层
两个问题:1、怎么可以悔棋啊?2、为什么明明有一个人输了,游戏还是不结束,还可以继续走棋呢?
回复 支持 反对

使用道具 举报

发表于 2004-9-11 17:34:00 | 显示全部楼层
岛主好像对vml很感兴趣呢。偶个人觉得棋盘还是用图片的好,那样效果可以更丰富。
下面是偶的正弦波,vml的部份是 [拿 word 搞定 的] 。贴在这里凑个热闹!

 提示:您可以先修改部分代码再运行

回复 支持 反对

使用道具 举报

发表于 2004-9-11 22:29:00 | 显示全部楼层
呵呵 好像在做物理课件 想法很不错啊 建议中学物理老师都换vml做课件^_^
不过vml画图也挺讨厌 好多代码 用js生成能简洁一些吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-9-12 11:09:00 | 显示全部楼层
irenezh在上个帖子中说
两个问题:1、怎么可以悔棋啊?2、为什么明明有一个人输了,游戏还是不结束,还可以继续走棋呢?


关于这个问题:
1.我没有保存棋局,所以现在是没法悔棋的。
2.是否能够说一下你是怎么走的?也许我程序在哪里疏漏了。
回复 支持 反对

使用道具 举报

发表于 2004-9-14 16:58:00 | 显示全部楼层
太复杂了,不会
回复 支持 反对

使用道具 举报

发表于 2004-9-17 16:56:00 | 显示全部楼层
桃花岛主在上个帖子中说
irenezh在上个帖子中说
[quote] 两个问题:1、怎么可以悔棋啊?2、为什么明明有一个人输了,游戏还是不结束,还可以继续走棋呢?


关于这个问题:
1.我没有保存棋局,所以现在是没法悔棋的。
2.是否能够说一下你是怎么走的?也许我程序在哪里疏漏了。 [/quote]
5555555,我胡乱走的,所以现在想不起来了。我想想啊,最后的过程好象是,由于我自己移开一个棋子,使得对方的炮可以打我的将了,但之后我和对方都还可以继续走。
回复 支持 反对

使用道具 举报

发表于 2004-9-19 20:22:00 | 显示全部楼层
不懂啊!
这也太过时了吧!!!
回复 支持 反对

使用道具 举报

发表于 2004-9-20 15:44:00 | 显示全部楼层
桃花岛主在上个帖子中说
本程序实现的功能为本地二人对弈中国象棋,实现语言为javascript+VML,在windows 2000 pro+IE 6sp1的环境下测试通过。
程序默认的起始颜色为红色,只有执红色一方可以先走棋,双方轮流下棋,老将被吃则认为输棋,棋局结束,可以通过刷新页面重新开始。
下棋的时候,点击要走的棋子,将显示当前可走位置(小矩形)和可吃位置(加上红色框标记),然后点击对应位置即可走棋。如果要改选其他棋子,直接点击即可。

程序的演示地址:
http://island.vip51.dig86.com/chess/chess.htm


设计概述:
在一个复杂的、有界面、有交互的程序中,将控制模块与表现模块区分,分别编写是很有效的做法。这样能够使对界面、运算等的操作集中统一,便于修改与测试。
在整体设计上,本程序采用了将判断可行位置算法下放的做法。传统的象棋程序一般先取得欲移动棋子类型,然后由统一的算法判断目标位置是否可行。本程序把判断目标位置是否合法的方法下放到棋子,控制模块在判断当前走法合法性的时候,取得这个棋子对象,并且调用此对象的canGo方法来判断目标位置是否可行,这种做法比较有利于让程序充分体现面向对象特性。
棋盘单独作为一个模块实现,它具有一定规模,且实现了一个针对性比较强的功能,因此将它与其他模块隔离,单独编写。这个模块的主要事件集中在图形化效果的表现,同时也应当主意结构的层次性和合理性,并且应当向外界提供所生成棋盘的引用,让控制模块可以将棋子挂接在这个根元素上。
棋子本质为div对象,包含了一个图标文件,并且具有附加属性,如:颜色、种类、位置等。各种棋子有不少相似属性,但是具体差别还是不小,比如各棋子的判断可行位置走法。因此,先编写一个具有普遍性的棋子模块,拥有棋子的基本属性:坐标、图标、当前是否被攻击等情况,然后分别对于每种棋子,创建单独的模块。这个过程中采用了一种“伪继承”技术:在单独的棋子模块中,创建了一个通用的棋子变量,并且对它附加了一个canGo方法,然后,把这个棋子变量作为自己的创建结果返回出去。
为什么称这个为“伪继承”呢?很明显,js并不支持继承,而且,继承的实现方法并非如此。但是,我们做了继承所做的事情,即为父类型的对象添加了属性、方法,因此扩展了它的属性和方法,并且,最后将扩展完成的对象当作自己构造出来的对象返回出去,使得结果对象除了具有父对象的属性、方法,还拥有自己特有的属性及方法,因此,我们可以说这是某种形式的继承。
在程序中建立了一个全局二维数组situation用于保存棋子列表,各棋子对象存放其自身坐标等信息,还定义了各常量用于标记棋子颜色、种类等通用信息。
程序中所使用的资源文件有棋子图标及标记可走位置的图标。棋盘为VML代码绘制,各棋子分别置于单个div中,由一个外部的HTC文件控制其行为。这个HTC做了这样的事情:在点击当前棋子所在的div时,HTC中的check函数对当前点击对象进行处理,决定应当走棋或者其他操作。
在点击棋子时,将根据遍历棋盘坐标代入该棋子canGo方法的结果,取得可以移动的位置。如果这些位置当前没有棋子,则认为是可走位置,在对应位置产生一个Blank对象,放置一个提示图标。Blank对象同样是棋子模块的伪继承,它没有canGo方法,只保存了基本属性,专门用于标志可走位置。如果这些位置当前存在棋子,并且棋子的颜色与自身不同,则认为是可吃位置,将对应棋子加上红色边框标记,同时将其beAttack属性设为真。这样,走棋的时候即可据此判断。
走棋后,程序需要清除以前那些过期的标记,这是通过一个遍历实现的,从棋盘中检索到灰色对象,即认为它是标记,直接清除。另外,吃子的实现比较复杂,反复尝试replaceChild方法以后放弃了,因为遇到意想不到的问题,所以通过遍历检索来取代被吃棋子。这个步骤似乎可能有比较简便的实现方法,希望高手指教。

附记:很久以前,在51js论坛看见幻宇前辈的js版星际,就产生做这个象棋的念头,然后花一个小时参考美洲豹的VML教程写了棋盘,却因为各种原因搁置了。这次重新捡起来,花了一天半时间写了其他所有部分,测试了一会,没发现bug,先发布出来,给大家玩玩。有兴趣的朋友可以继续做,做成能够联机的版本,不是很难。此外,我暂时有一个部分没有设计,就是老将见面的判断,有空补上,hoho。基本的说明就先写这么多,以后慢慢把各部分代码加上注释,发在这里,大家不要着急啊。




qiang!!!!!
回复 支持 反对

使用道具 举报

发表于 2004-9-22 09:01:00 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2004-10-5 09:53:00 | 显示全部楼层
xvlv2004在上个帖子中说

这个界面更好  我喜欢 可否分析一下
回复 支持 反对

使用道具 举报

发表于 2004-10-16 08:57:00 | 显示全部楼层
桃花岛主大哥,你好,你说的美洲豹的VML教程哪里有的下啊?我想要,可以给我吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2004-10-16 10:47:00 | 显示全部楼层
搜索:美洲豹 教程
回复 支持 反对

使用道具 举报

发表于 2004-11-4 22:34:00 | 显示全部楼层
3Q,
谢谢!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|Archiver|手机版|blueidea.com ( 湘ICP备19000417号-2 )

GMT+8, 2021-10-25 06:05 , Processed in 0.075386 second(s), 9 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表