js实现单机双人象棋设计分析

作者:桃花岛主 来源:蓝色理想 时间:2008-05-20 12:57:00 

本游戏程序实现的功能为本地二人对弈中国象棋,实现语言为javascript+VML,在windows 2000 pro+IE 6sp1的环境下测试通过。

程序默认的起始颜色为红色,只有执红色一方可以先走棋,双方轮流下棋,老将被吃则认为输棋,棋局结束,可以通过刷新页面重新开始。

下棋的时候,点击要走的棋子,将显示当前可走位置(小矩形)和可吃位置(加上红色框标记),然后点击对应位置即可走棋。如果要改选其他棋子,直接点击即可。

程序的演示地址:

http://island.vip14.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。基本的说明就先写这么多,以后慢慢把各部分代码加上注释,发在这里,大家不要着急啊。

标签:象棋,游戏,设计,js
0
投稿

猜你喜欢

  • 详解CSS的优先权

    2008-05-11 18:57:00
  • js中位数不足自动补位扩展padLeft、padRight实现代码

    2024-04-19 10:46:42
  • python pandas中DataFrame类型数据操作函数的方法

    2022-10-22 09:33:12
  • 实际应用:MySQL5存储过程编写

    2008-11-11 12:25:00
  • 基于Python实现千图成像工具的示例代码

    2022-03-14 12:19:21
  • 实现SQL Server 原生数据从XML生成JSON数据的实例代码

    2024-01-16 01:46:03
  • vue转react useEffect的全过程

    2024-05-02 16:32:22
  • mysql 正确清理binlog日志的两种方法

    2024-01-21 14:11:02
  • 解析SQLServer获取Excel中所有Sheet的方法

    2024-01-18 15:11:26
  • python+selenium实现QQ邮箱自动发送功能

    2021-11-11 22:03:58
  • Pytorch平均池化nn.AvgPool2d()使用方法实例

    2023-09-30 02:49:35
  • Python类的动态绑定实现原理

    2022-05-02 00:52:03
  • python定时器(Timer)用法简单实例

    2021-01-10 15:43:04
  • Zabbix实现监控多个mysql过程解析

    2024-01-25 20:24:53
  • MySQL慢查询之开启慢查询

    2024-01-23 16:16:03
  • openCV提取图像中的矩形区域

    2022-06-11 06:38:55
  • 浅谈Python之Django

    2023-12-13 15:14:43
  • python和mysql交互操作实例详解【基于pymysql库】

    2024-01-16 01:03:47
  • asp 随机字符串函数

    2011-04-04 11:01:00
  • mysql 超大数据/表管理技巧

    2024-01-16 22:14:05
  • asp之家 网络编程 m.aspxhome.com