前言
棋盘识别部分已经在上一篇博客讲过了,这篇主要讲如何进行决策。
决策,即让程序、机器人自行决策下一步走什么棋,我这边想到的方法有三种。第一,使用强化学习,消耗的资源较多;第二,手动编程,对于这样娱乐、没有工资的项目,妥妥的不可能;第三,直接调用中国象棋云库,这也是我要介绍的方法。
工程代码:https://github.com/darkfan-cheese/Chinese-chess-robot
一、中国象棋云库
先放地址:中国象棋云库
https://www.chessdb.cn/query/
其实这网页不仅仅能够玩中国象棋,国际象棋也可以,基本操作都差不多。
我们的目的是使用代码,让这个云库帮助我们进行决策。
二、网页URL程序编写
1.引入库
在python中,使用的库是requests,直接导入
import requests
2.代码实现
网页api使用的格式为:
http://www.chessdb.cn/chessdb.php?action=[ACTION]{&[OPTION1]=[VALUE1]…&[OPTIONn]=[VALUEn]}
具体的见官方网页:中国象棋云库接口说明
但是,在我多次尝试下发现,这个api使用有点问题,当然,也可能是我的打开方式不对。我发现,这个api不能在棋局编码(FEN码)后面直接添加多个行棋信息(moves 后面的是行棋信息),这样:
rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w moves g3g4 h7g7 b2e2 g9e7 f0e1
一步两步还行,但是多了之后就有bug或者计算不出来,实在是无奈。
不过我们可以通过每次的行棋信息,来更新我们的棋局编码,这样我们每次传入的api只有一步行棋,例如:
rnbakabnr/9/1c4c2/p1p1p3p/9/2P3p2/P3P3P/1CN4CB/9/R1BAKA1NR b moves h9i7
这样在每次使用api获得结果后对棋局编码和行棋编码进行解码,解码完成后,机器人走棋,再更新了棋局,对棋局重新编码,识别了玩家(人类)的行棋信息后,再向云库传输完整的api,获取下一步行棋方法。
发送api命令代码如下:
def sendw(api_open):
api_0 = "http://www.chessdb.cn/chessdb.php?action=querybest&board="
url = api_0 + api_open + ' w'
print(url+'\n')
ret = requests.post(url=url)
a = ret.content.decode('utf-8')
if 'search' in a:
d = a.split('|')
c = d[-1]
b = c[7:11]
print(b)
else:
b = (a[5:])
print(b)
return b
url变量就是向网页输出的命令,字符串的组合而已,在云库的说明里面有解释,之后就是使用post发送命令,ret接受,再解码,解码之后,使用判断来提取我们需要的返回数据,存在b中。
而这段代码的上级如下:
def compute_walk(api_open='9/9/3k5/9/2b6/4N4/9/1c2B4/4K4/3A5'):
result = sendw(api_open=api_open)
org = result[:2]
tar = result[2:4]
dictorg[tar]=dictorg[org]
dictorg[org] = '0'
return result
这段代码就是对上个函数结果的处理,解析行棋信息(起点与终点)。dictorg是一个棋盘映射字典,存储的棋局信息。
此外,还有对棋局编码(FEN)的解码(fen转python字典)代码,由于是我同门完成的,这里只贴代码。
def inver_list_to_fen(self, ax_i_new):
self.stri = ''
count = 0
inti = 0
count_i = []
for i in ax_i_new:
count += 1
inti += 1
if i.isdigit():
count_i.append(i)
else:
count_i.append(i)
if count_i[inti - 2].isdigit():
self.stri += str(count - 1)
self.stri += i
else:
self.stri += i
count = 0
self.stri += str(count)
if self.stri[-1] == '0':
self.stri = self.stri[:-1]
return self.stri
另外还有棋局编码转化为python字典的代码:
def fen_to_the_dict(self, org_gen):
self.ax_9, self.ax_8, self.ax_7, self.ax_6, self.ax_5, self.ax_4, self.ax_3, self.ax_2, self.ax_1, self.ax_0 = org_gen.split(
'/')
self.ax_list_key = ['ax_9', 'ax_8', 'ax_7', 'ax_6',
'ax_5', 'ax_4', 'ax_3', 'ax_2', 'ax_1', 'ax_0']
self.ax_list_value = [self.ax_9, self.ax_8, self.ax_7, self.ax_6,
self.ax_5, self.ax_4, self.ax_3, self.ax_2, self.ax_1, self.ax_0]
self.ax_dict = dict(zip(self.ax_list_key, self.ax_list_value))
dict_key = []
non = '0'
for j in self.latter_table:
for i in range(10):
dict_key.append(j + str(i))
dictvalue = [non for i in range(0, 90)]
self.dictorg = dict(zip(dict_key, dictvalue))
self.cal_chess('self.ax_9')
self.cal_chess('self.ax_8')
self.cal_chess('self.ax_7')
self.cal_chess('self.ax_6')
self.cal_chess('self.ax_5')
self.cal_chess('self.ax_4')
self.cal_chess('self.ax_3')
self.cal_chess('self.ax_2')
self.cal_chess('self.ax_1')
self.cal_chess('self.ax_0')
return self.dictorg
总结
总的来说,实现决策的步骤就是:
1.解析棋局信息,转换成FEN码。
2.学习中国象棋云库api的使用方法
3.将棋局编码填入api命令,获取返回值
4.根据返回值操纵机械臂行棋落子
5.更新棋局信息,等待下一步行棋