“JavaScript中国拇峨镅贪象棋程序” 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序。这篇经验是教程的第1节。这一系列共有9个部分。0、JavaScript中国象棋程序(0)- 前言1、JavaScript中国象棋程序(1)- 界面设计2、JavaScript中国象棋程序(2)- 校验棋子走法3、JavaScript中国象棋程序(3)- 电脑自动走棋4、JavaScript中国象棋程序(4)- 极大极小搜索算法5、JavaScript中国象棋程序(5)- Alpha-Beta搜索6、JavaScript中国象棋程序(6)- 克服水平线效应、检查重复局面7、JavaScript中国象棋程序(7)- 置换表8、JavaScript中国象棋程序(8)- 进一步优化
工具/原料
计算机
JavaScript中国象棋程序(1)
1.1、棋盘表示
1、这一节我们设计图形界面,显示初始化棋局。当点击某棋子时,弹窗提示所点击的具体棋子。效果如下:
2、中国象棋有10行9列,很自然地想到可以用10×9矩阵表示棋盘。事实上,我们使用16×16矩阵来表示一个扩充了的虚拟棋盘。如图所示,灰色部分为真实棋盘,置于虚拟棋盘之中。这么做可以快速判断棋子是否走出边界。例如象沿田字走,如果走到真实棋盘之外的虚拟棋盘中,说明走法不合法。
3、容易想到使用二维数组表示16×16矩阵,这样棋盘上的一个位置需要两个变量表示。一个走法包括起点和终点,就需要四个变量。如果使用长度为256的一维数组表示,一个位置只需一个变量,这就可以减少计算量。因此用一维数组表示16×16矩阵。一维矩阵和二维矩阵之间的转换也很简单:其中,sq & 15是通过位运算取余,与sq % 16结果相同。
4、再使用一个辅助数组,标识虚拟棋盘中,哪些位置属于真实棋盘:
5、要判断某位置是否在真实棋盘,可使用函数:
1.2、棋子表示
1、使用整数表示棋子:
2、棋子这样表示,可以快速判断某棋子属于红方还是黑方,如下表所示:可以看出:红方棋子 & 8 = 1黑方棋子 & 16 = 1
1.3、字符串表示局面
1、使用数组表示局面,程序处理起来很方便,但是再网上传递棋局很不方便。我们可以用一行字符串表示一个局面,这就是FEN格式串,一种使用ASC朐袁噙岿II码字符描述国际象棋局面的标准,当然也可应用于中国象棋。中国象棋的初始局面可表示为:rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1(1)、红色区域,表示棋盘布局,小写表示黑方,大写表示红方。一个字母表示一个棋子,对应关系如下。
2、至于为什么马不用H(horse),象不用E(elephant),这是为了与国际象棋相对应。如果没有棋子,则用数字表示出相邻连续的空位数。中国象棋共有十行,每行都用一个字符串表示,行间使用正斜杠分割。例如: rnbakabnr表示:
3、 1c5c1表示:
4、(2)、绿色区域,釉涑杵抑表示轮到哪一方走子,“w”表示红方,“b”表示黑方。(没有用r表示红方,我想也是为了与国际象棋对应吧,毕竟国际象棋是黑白两色。)叵萤茆暴(3)、深紫色区域,在中国象棋中没有意义,始终用“-”表示。(4)、紫红色区域,在中国象棋中没有意义,始终用“-”表示。(5)、蓝色区域,表示双方没有吃子的走棋步数(半回合数),通常该值达到120就要判和(六十回合自然限着),一旦形成局面的上一步是吃子,这里就标记“0”。(6)、棕色区域,表示当前的回合数。我们的程序就是使用FEN串初始化棋局的,这就涉及到了将FEN串转化为一维棋局数组。暂时不考虑哪方走子,只解析红色部分,伪代码如下:
1.4、棋盘前端设计思路
1、由于棋盘有90个交叉点,我们把棋盘划分为的90个小正方形区域,交叉点是小正方形的中心。每个区域都会定义一个img标签。
2、上图使用红色方框,标识出了4个小正方形区域。这些img标签有两个作用:(1)、显示棋子图片如果某个区域存在棋子,就会显示相应的棋子图片;否则,显示一张透明图片(也就是oo.gif)。(2)、响应点击事件每个img标签都会绑定onmousedown事件。点击不同的img标签时,会传递不同的参数给响应函数,这样就知道点击的具体是哪个区域了。
1.5、核心代码说明
1、本节的代码可以在 Github 下载,也可以直接clonegit clone -b step-1 https://github.com/Ro烤恤鹇灭yhoo/write-a-chinesechess-program程序中定义了两个对象:Board和Position。Board表示一个棋盘,主要功能是初始化棋局,显示棋盘、棋子,响应棋盘上的点击事件。Position存储了一维棋局数组,并定义了很多对该数组进行操作的方法。Board对象实例化的代码位于index.html中。通过prototype属性,我们为这两个对象添加了很多的属性和方法。
2、Board的主要属性和方法:(1)、pos这是Position对象的一个实例。(2)、flushBoard()刷新棋盘,也就是重新显示棋盘上的棋子。(3)、drawSquare(sq)显示sq位置的棋子图片。如果该位置没棋子,则显示一张透明的图片。(4)、clickSquare(sq_)点击棋盘的响应函数。点击棋盘(棋子或者空位置),就会调用该函数。sq_是点击的位置。
3、Position的主要属性和方法:(1)、squares这就是一维棋局数组。(2)、fromFen(fen)通过FEN串初始化棋局,也就是将参数fen表示的棋局,转化为一维棋局数组squares表示的棋局。(3)、addPiece(sq, pc)将棋子pc添加进棋局中的sp位置。