象棋函数库ChessFunctions功能与用法

ChessFunctions是我用VB6开发的动态链接库,目的在于为象棋软件开发者提供便利,降低开发难度。

首先讲述一下象棋编程的基础知识。

象棋软件的功能与构成

一个象棋软件,应该具备如下基本功能:

  • 新建棋局
  • 支持双人对弈、人机对弈
  • 保存棋谱、打开棋谱

从设计的角度,象棋软件向用户提供界面,用户可以在棋盘上点击和移动棋子。程序的后台代码,需要相应的记录用户的操作,同步更新数据。

棋谱的本质

一盘棋,是由初始局面和后续招法形成的。局面(board)和招法(movelist)这两个术语构成了象棋软件的核心内容。只有处理好这两项内容,才能做出合格的软件。

局面

局面是指棋盘上有哪些棋子,这些棋子在什么位置。描述局面主要有如下三种方式:

FEN字符串

FEN字符串采用字母与数字结合的方法,把棋盘上10×9=90个交叉点的棋子进行描述,具体方法是用字母rnbakcp分别代表黑方的车马象士将炮卒,用RNBAKCP分别代表红方的车马相仕帅炮兵。从棋盘左上角从左到右、自上而下,遇到连续的空格,用空格数量代替。换行的时候用斜杠分开,例如:

r2akabr1/9/1cn1b2cn/p3p1p1p/2p6/6P2/P1P1P3P/1CN1C1N2/9/R1BAKABR1 w

上述FEN用来描述下面这个局面,r2akabr1表示 黑车 两个空格 士 将 士 象 黑车 1个空格。以此类推

 

 

需要注意,FEN字符串后面有一个字母w或者b,用于描述当前局面该哪一方走棋,如果红方走棋,结尾是w。否则是b

FEN字符串至关重要,采用一行字符串就描述整个棋盘。在各个象棋软件之间复制粘贴局面非常方便,而且,云库以及引擎也只认识FEN字符串。

加空的FEN字符串

所谓加空的,是指把FEN字符串中的数字,用连续的空格换掉。我习惯用小写字母o表示空格。例如上述FEN字符串加空以后:

rooakabro/ooooooooo/ocnoboocn/pooopopop/oopoooooo/ooooooPoo/PoPoPoooP/oCNoCoNoo/ooooooooo/RoBAKABRo

加空的目的在于,把FEN字符串的长度凑够99个(90个交叉点+9个斜杠),这样方便利用循环转换为数组。

二维数组

象棋软件的程序后台采用二维数组作为局面的数据结构,非常合适,因为二维数组在形式上最接近真实的棋盘。

我喜欢这样声明Dim Matrix(1 To 10, 1 To 9) As String

一维表示10行,二维表示9列。上述FEN字符串对应的二维数组是:

 如果在VBA的本地窗口查看二维数组:

 

招法

招法,指的是红方或黑方走了一步棋,一个招法必然对二维数组的元素进行修改。

如左图所示,假设红方车二进七吃黑炮,形成右图:

  

这样就产生了一个招法,这个招法需要对二维数组Matrix进行如下元素修改:

Matrix(x2,y2) = Matrix(x1,y1)

Matrix(x1,y1) = "o"

其中,x2,y2是棋子行走终点的横纵坐标,x1,y1是起点的横纵坐标。

以上两行,是著名的“象棋公式”,任何一招棋,都这样的。

*需要注意,对于一盘棋,局面数总比招法数多1,因为初始局面没有招法。

中文棋谱

中文棋谱,采用4个字描述一个招法,这种做法指出了发生行走的棋子的名称,但是缺点是起点、终点的坐标不明确,程序设计的时候很不方便。必须转换为具体的行列数才能处理。

东萍movelist

东萍象棋是目前最强大的网络象棋数据库,采用binit描述初始局面,采用movelist描述招法列表。

movelist用4个数字表示招法,具体是x1y1x2y2这种格式。把棋盘左上角的位置定为(0,0)。

例如从全局开始,红方黑方先后走了:

炮二平五 象7进5 马二进三 士4进5

形成如下局面:

东萍象棋的movelist则记为:7747604279673041

云库或引擎的moves

云库是一个能够计算招法的网站,用户只需要把FEN字符串传递给网站,云库就能返回当前局面最佳招法是什么。对于开局阶段,云库还可以返回多个可选招法。

云库或者引擎,把棋盘的左下角定为(a,  0),采用一个字母一个数字的方式描述棋子的位置。 给出的招法是两个字母两个数字,例如上述局面,b0c2表示马八进七,

i0h0表示车一平二。下面是一些可选招法。

引擎,是位于磁盘上的一个可以计算招法的可执行文件,与云库类似,用户把FEN字符串传递进来,就可以给出最佳招法。

综上所述,movelist和moves都是坐标表示法,可以相互转换,写代码的时候非常容易。

象棋软件开发的拦路虎

我相信,很多象棋爱好者或者编程爱好者都曾尝试过编写象棋软件。但是绝大多数人半途而废,完整地开发一个象棋软件的人寥寥无几。究其原因,是因为存在如下三大难题难以解决。

行棋规则判断

象棋软件,提供给用户的是一个棋盘,以及用控件制作的一些棋子。用户点击棋子的时候,能够移动到哪儿,不能移动到哪儿,必须加以限制。否则导致马走田字、车炮可以斜着走等情况。

也就是说,在用户试图走一步棋的时候,软件应该判断一下是否为合理招法。

局面计算

局面计算属于人工智能,自己编写算法难度很大。目前最方便的方式就是调用云库,或者调用引擎。

棋谱格式转换

象棋软件的另一个重要功能就是能够保存、打开棋谱。然而,象棋棋谱文件格式非常多,主流的有pgn、东萍棋谱等。程序开发的时候必然需要解释每个棋谱的初始局面是什么,招法列表是什么。中文棋谱、movelist、moves三者之间的转换是必要的。

使用象棋函数库

象棋函数库(ChessFunctions)解决了如上3个难题。开发人员只需要在工程中添加该引用,就可以在代码中调用相应的函数,来轻松开发。

ChessFunctions的构成

ChessFunctions包含如下5个类:

  • Clscdb:国际象棋云库的功能
  • Clschessdb:中国象棋云库的功能
  • ClsChineseChess:中国象棋规则、棋谱转换等
  • ClsInternationalChess:国际象棋规则
  • ClsEngine:引擎方面的功能,中国象棋国际象棋通用

ChessFunctions的用法

ChessFunctions支持32位的Office VBA,以及目标平台是x86的C#程序等。下面演示VBA中使用ChessFunctions的方法。

  • 注册dll

管理员身份启动cmd命令提示符窗口,输入:

regsvr32 xxx\ChessFunctions.dll

按下回车进行注册。xxx是具体路径

  • 添加引用

在VBA工程中添加引用。浏览ChessFunctions.dll

 

  • 调用函数
Private chessdb As ChessFunctions.Clschessdb

Sub Test()
    Dim m As String
    Set chessdb = New ChessFunctions.Clschessdb '必须实例化
    m = chessdb.bestmove(FEN:="3ak1P2/4a4/4b4/C8/2b6/9/9/9/9/4K4 w - - 0 1")
    Debug.Print m
End Sub

上述代码调用了Clschessdb这个类中的bestmove函数,也就是让云库计算最佳招法。最后,m的打印结果是 a6e6(炮九平五)。

继续修改代码:

Sub Test()
Dim a() As String
Set chessdb = New ChessFunctions.Clschessdb '必须实例化
a = chessdb.queryall(FEN:="3ak1P2/4a4/4b4/C8/2b6/9/9/9/9/4K4 w - - 0 1")  'queryall用于计算所有招法,返回数组。
Debug.Print Join(a, vbNewLine)
End Sub

打印结果是:

根据score可以看出,红方只有走a6e6(炮九平五)或者走a6a9(炮九进三)才能赢,其余走法都是和棋。 

其余类库的调用示例,请参考“VBA用户窗体中国象棋.xlsm”文件Test模块里面的代码。

函数名功能
Clscdb bestmove 返回国际象棋指定局面下的最佳招法
queryall 返回国际象棋指定局面下的全部招法
querypv 返回国际象棋指定局面下的思考细节
queryscore 返回国际象棋指定局面下的分数
validation 返回国际象棋指定局面是否合理
     
Clschessdb bestmove 返回中国象棋指定局面下的最佳招法
queryall 返回中国象棋指定局面下的全部招法
querypv 返回中国象棋指定局面下的思考细节
queryrule 返回中国象棋指定局面是否犯规、和棋
queryscore 返回中国象棋指定局面下的分数
validation 返回中国象棋指定局面是否合理
     
ClsChineseChess Array2FEN 二维数组转FEN字符串
binit2FEN 东萍binit转FEN字符串
DisplayBoard 显示文本棋盘
FEN2Array FEN字符串转二维数组
FEN2binit FEN字符串转东萍binit
Fens2movelist 多个FEN字符串转东萍movelist
getMovelistString 根据movelist计算出中文棋谱
GetUBB 返回指定url的东萍UBB
Movable 判断指定局面下某个招法是否可走
movelist2FENs 根据movelist计算出多个连续的FEN字符串
movelist2moves movelist转moves
movelist2Qipu movelist转中文棋谱
moves2movelist moves转movelist
Qipu2movelist 中文棋谱转movelist
SaveUBB 将指定的UBB上传到东萍网站
加空 FEN字符串中的数字用o替换
去空 把字符串中的o替换为数字
     
ClsEngine bestmove 返回国际象棋/中国象棋指定局面下的最佳招法
info 返回国际象棋/中国象棋指定局面下的全部招法
QuitEngine 退出引擎
StartEngine 启动引擎
     
ClsInternationalChess Array2FEN 二维数组转FEN字符串
DisplayBoard 返回文本格式的棋盘
FEN2Array FEN字符串转二维数组
Movable 判断国际象棋指定局面下某个招法是否可走
moves2FENs 根据moves计算出后续FEN字符串
加空 FEN字符串中的数字用o替换
去空 把字符串中的o替换为数字

欢迎大家在评论区留言,如果要下载ChessFunctions,QQ群:

 

posted @ 2024-01-06 08:44  ryueifu  阅读(298)  评论(0编辑  收藏  举报