问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

象棋对弈软件是如何编制出来的

发布网友 发布时间:2022-04-22 14:21

我来回答

3个回答

热心网友 时间:2023-04-29 06:15

呵呵,开始我也觉得没有破绽,后来发现了软件也会出昏招。原来原理很简单,只是把基本的开局定式以及常见的对弈拆解局面转换成数据库函数,当出现数据库招数,便调出同类型的宏功能。说到底,只是电脑软件做到了更多的对弈棋局收集,把相关的招数进行了数码汇编。比如:仙人指路开局,软件就会自动把存储在数据库中的符合这一定式类型的所有函数自动调出,选择基本应招(根据用户选手游戏难度不同,软件也会选择相应招数致胜比率和复杂程度)。所以按一般局面和软件玩,就等于和一个熟读兵法的谋士作战,很难赢。你会有看不透,想不到的时候,软件按步就班,数据库就是它的眼睛和脑袋。但是编制软件的并不是一流大师,他们手头上有的都是找得到的棋局,但是棋盘千变万化,有很多招式不可能存在软件中,所以软件也会碰到出昏招的时候。我们可以做一个小实验,两台电脑玩相同的象棋游戏,如果以A电脑进行先手,B电脑进行后手,以B电脑的招式来和A电脑下。百分之九十九的机率是和棋。如果我们用自己的方式操作B电脑和A电脑进行至中局(有一方有多子优势),然后再让两台电脑自己下,肯定有一台电脑是输的。你就会发现输的电脑下的棋局很一般,因为它还是在以应对的形式开展,试问没有优势的情况下,那台数据库一样的电脑软件会出现奇招嘛?也就是说软件也是会输的。我记得国际象棋那个深蓝也输给过卡斯帕罗夫,然后那个更深的蓝赢了卡斯帕罗夫。还是赢在数据采集啊。

热心网友 时间:2023-04-29 06:16

编写方法:

先弄明白数据的结构:
MantisChessDef.h里的东西一定要先看一下, 否则会摸不到头脑的。
还有棋盘坐标:
象棋棋盘大小9x10,为了便于编程,规定棋盘每条边留有一个元素的边界。
这样棋盘大小(包括边界)变成11x12。棋盘x坐标轴向右,y轴向下。
黑棋永远在上方,在标准开局时左上角的黑车坐标是(1,1)。

局面用这三个变量表示:

static POINT g_pointChessman[32]; //棋子坐标
static int g_iChessmanMap[11][12]; //棋位状态
static int g_iSide; //轮到哪方走

智能部分有几个函数的前三个参数就是这个东西, 应该不难理解吧?

---------------------------------------------------------------------------------------
search函数:

先说明一下, 经常有朋友问我要原理, 但我公开源代码是给大家一个参考, 而不是什么教程,所以我不想说那些理论的东西。
基本原理是α-β搜索, 很多人工智能的教科书上都有讲到, 没看过的的赶快去找一本来啃一啃;
虽然这些书上的文字大多晦涩难懂,但毕竟讲得明明白白。
没有书的朋友请发挥一下主观能动性, 去找一找,不要来问我要, 因为我也没有。

我在这里只分析一下search函数:

弄懂α-β搜索后来看看这个博弈树, 看怎么编程实现它。

先规定一下, 我们用一个整数表示局面的好坏.
这个数越大说明局面对 "走棋方" 越有利,0表示双方实力相等。

1a( 1) ┬ 2a(-1) ┬ 3a(-1)
│ └ 3b( 1)
└ 2b(-5) ┬ 3c( 2)
├ 3d(-4)
└ 3e( 5)

分析一下这棵树,有这么个特点: 父结点的值 = -MAX(子结点的值)

我们还知道1、每个结点对应一个局面。2、底层的结点的值是"估"出来的。

于是我们可以写出伪代码了:

伪代码: 搜索一个结点下的分支, 得到这个结点的值。

参数: 局面,搜索深度

返回值:结点的值

int search(局面,int depth)
{
if(depth!=0)//不是底层结点
{

枚举出所有子结点(列出所有走法);

int count=子结点数;
int maxvalue= -∞;
for(int i=0;i<count;i++)//遍历所有结点
{
算出子结点局面;

maxvalue=max(maxvalue,search(子结点局面,depth-1));
}
return -maxvalue;
}
else //是底层结点
{
return 估计值;
}
}

这就是搜索算法的框架, 用到了递归。
MantisChess的智能部分函数都在MantisChessThink.cpp里, 其中search是搜索, 跟上面的这个search差不多,我把它copy出来注释一下:

int Search(int tmap[11][12],POINT tmanposition[32],int &tside,int man, POINT point,int upmax,int depth)
{

//前面的三个参数就是局面。
//man 和point 是走法,用来计算本结点的局面。 这里是把计算局面放在函数的开头,跟上面的伪代码不太一样。
//upmax: up - 上一层, max - 最大值, 这是α-β的剪枝用到的东西, 后面再讲。
//depth: 搜索深度

int ate,cur,maxvalue,curvalue,xs,ys;
int count;

//#####################这一段是计算本结点的局面#########################################
ate=32;
//移动棋子:
xs=tmanposition[man].x;ys=tmanposition[man].y; //原坐标
if (SideOfMan[tmap[point.x][point.y]]==!tside) //目标点有对方的棋子
{
ate=tmap[point.x][point.y]; //记录下被吃掉的棋子
if(ate==0 || ate==16)
{
return 9999;
}
tmanposition[ate].x=0; //目标点的棋子被吃掉
}

tmap[point.x][point.y]=man; //这两行是:
tmap[xs][ys]=32; //在map上的移动
tmanposition[man]=point;
tside=!tside;
//####################################################################################

depth--;

if(depth>0) //不是底层结点
{
int chessman[125];
POINT targetpoint[125];
if(EnumList(tmap,tmanposition,tside,chessman,targetpoint,count)) //枚举出所有子结点(列出所有走法)
{
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//这里是剪枝(不是α-β剪枝), 原理是在正式搜索之前先用较浅的搜索来得到误差较大的值
//然后根据这些值来对子结点排序, 只保留最好的S_WIDTH个结点进行正式搜索。
//显然,这个剪枝有一定的风险

if(depth>=2 && count>S_WIDTH+2)
{
int value[125];
cur=0;
maxvalue=-10000;
while(cur< count)
{
curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],-10000,depth-2);
value[cur]=curvalue;
if(curvalue>maxvalue)maxvalue=curvalue;
cur ++;
}
::Mantis_QuickSort(value,chessman,targetpoint,0,count-1); //排序
count=S_WIDTH;//剪枝
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

maxvalue=-10000;
cur=0;
while(cur< count)
{
curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],maxvalue,depth);
if(curvalue>maxvalue)maxvalue=curvalue;
if(curvalue>=-upmax)goto _ENDSUB; //α-β剪枝, 符合剪枝条件的就Cut掉。 这里用了goto语句了, 千万别学我。
cur ++;
}
}
else maxvalue=9800;
}
else //是底层结点
{
maxvalue=Value(tmap,tmanposition,tside); //估值
}

_ENDSUB:

//返回之前要恢复父结点的局面
//####################################################################################
tmanposition[man].x=xs; //这两行是:
tmanposition[man].y=ys; //在face上的恢复
tmap[xs][ys]=man; //在map上的恢复
if(ate!=32)
{
tmanposition[ate]=point;
tmap[point.x][point.y]=ate;
}
else tmap[point.x][point.y]=32;

tside=!tside;
//####################################################################################

return -maxvalue;
}

上面的代码用到了α-β剪枝, 举个例子就明白了:

还是这个博弈树,从上往下遍历。

1a( 1) ┳ 2a(-1) ┳ 3a(-1)
┃ ┗ 3b( 1)
┗ 2b(-5) ┯ 3c( 2)
├ 3d(-4)
└ 3e( 5)

2a遍历完后 upmax=-1, 继续遍历完3c后返回2b, 发现3c=2>-upmax, 这时就不用管3d和3e了, 因为无论他们的值是多少 2b=-max(3c,3d,3e)<2a 一定成立,
也就是说2b可以安全地剪掉。这就是α-β剪枝。

从上面的代码来看MantisChess算法与标准的α-β剪枝搜索并没有什么不同, 只不过加了排序和剪枝而已。

热心网友 时间:2023-04-29 06:16

人工智能下棋软件通常主要包括:
1、棋书棋谱、对局记录。
2、按规则穷举优劣。完全这样的话出招理论上是最佳方案,但这样时间太长,计算机难以招架,而且如果真是这样,结局可能是先手必胜、或必和、或必输。
3、模拟人类思考,至少短时间有优势,例如,在目前没有危险的情况下,多吃对方一个子是有利的等等。
4、根据实际局面紧迫程度,综合适当结合上述方式计算结果出招。但不一定是最优。

热心网友 时间:2023-04-29 06:15

呵呵,开始我也觉得没有破绽,后来发现了软件也会出昏招。原来原理很简单,只是把基本的开局定式以及常见的对弈拆解局面转换成数据库函数,当出现数据库招数,便调出同类型的宏功能。说到底,只是电脑软件做到了更多的对弈棋局收集,把相关的招数进行了数码汇编。比如:仙人指路开局,软件就会自动把存储在数据库中的符合这一定式类型的所有函数自动调出,选择基本应招(根据用户选手游戏难度不同,软件也会选择相应招数致胜比率和复杂程度)。所以按一般局面和软件玩,就等于和一个熟读兵法的谋士作战,很难赢。你会有看不透,想不到的时候,软件按步就班,数据库就是它的眼睛和脑袋。但是编制软件的并不是一流大师,他们手头上有的都是找得到的棋局,但是棋盘千变万化,有很多招式不可能存在软件中,所以软件也会碰到出昏招的时候。我们可以做一个小实验,两台电脑玩相同的象棋游戏,如果以A电脑进行先手,B电脑进行后手,以B电脑的招式来和A电脑下。百分之九十九的机率是和棋。如果我们用自己的方式操作B电脑和A电脑进行至中局(有一方有多子优势),然后再让两台电脑自己下,肯定有一台电脑是输的。你就会发现输的电脑下的棋局很一般,因为它还是在以应对的形式开展,试问没有优势的情况下,那台数据库一样的电脑软件会出现奇招嘛?也就是说软件也是会输的。我记得国际象棋那个深蓝也输给过卡斯帕罗夫,然后那个更深的蓝赢了卡斯帕罗夫。还是赢在数据采集啊。

热心网友 时间:2023-04-29 06:16

编写方法:

先弄明白数据的结构:
MantisChessDef.h里的东西一定要先看一下, 否则会摸不到头脑的。
还有棋盘坐标:
象棋棋盘大小9x10,为了便于编程,规定棋盘每条边留有一个元素的边界。
这样棋盘大小(包括边界)变成11x12。棋盘x坐标轴向右,y轴向下。
黑棋永远在上方,在标准开局时左上角的黑车坐标是(1,1)。

局面用这三个变量表示:

static POINT g_pointChessman[32]; //棋子坐标
static int g_iChessmanMap[11][12]; //棋位状态
static int g_iSide; //轮到哪方走

智能部分有几个函数的前三个参数就是这个东西, 应该不难理解吧?

---------------------------------------------------------------------------------------
search函数:

先说明一下, 经常有朋友问我要原理, 但我公开源代码是给大家一个参考, 而不是什么教程,所以我不想说那些理论的东西。
基本原理是α-β搜索, 很多人工智能的教科书上都有讲到, 没看过的的赶快去找一本来啃一啃;
虽然这些书上的文字大多晦涩难懂,但毕竟讲得明明白白。
没有书的朋友请发挥一下主观能动性, 去找一找,不要来问我要, 因为我也没有。

我在这里只分析一下search函数:

弄懂α-β搜索后来看看这个博弈树, 看怎么编程实现它。

先规定一下, 我们用一个整数表示局面的好坏.
这个数越大说明局面对 "走棋方" 越有利,0表示双方实力相等。

1a( 1) ┬ 2a(-1) ┬ 3a(-1)
│ └ 3b( 1)
└ 2b(-5) ┬ 3c( 2)
├ 3d(-4)
└ 3e( 5)

分析一下这棵树,有这么个特点: 父结点的值 = -MAX(子结点的值)

我们还知道1、每个结点对应一个局面。2、底层的结点的值是"估"出来的。

于是我们可以写出伪代码了:

伪代码: 搜索一个结点下的分支, 得到这个结点的值。

参数: 局面,搜索深度

返回值:结点的值

int search(局面,int depth)
{
if(depth!=0)//不是底层结点
{

枚举出所有子结点(列出所有走法);

int count=子结点数;
int maxvalue= -∞;
for(int i=0;i<count;i++)//遍历所有结点
{
算出子结点局面;

maxvalue=max(maxvalue,search(子结点局面,depth-1));
}
return -maxvalue;
}
else //是底层结点
{
return 估计值;
}
}

这就是搜索算法的框架, 用到了递归。
MantisChess的智能部分函数都在MantisChessThink.cpp里, 其中search是搜索, 跟上面的这个search差不多,我把它copy出来注释一下:

int Search(int tmap[11][12],POINT tmanposition[32],int &tside,int man, POINT point,int upmax,int depth)
{

//前面的三个参数就是局面。
//man 和point 是走法,用来计算本结点的局面。 这里是把计算局面放在函数的开头,跟上面的伪代码不太一样。
//upmax: up - 上一层, max - 最大值, 这是α-β的剪枝用到的东西, 后面再讲。
//depth: 搜索深度

int ate,cur,maxvalue,curvalue,xs,ys;
int count;

//#####################这一段是计算本结点的局面#########################################
ate=32;
//移动棋子:
xs=tmanposition[man].x;ys=tmanposition[man].y; //原坐标
if (SideOfMan[tmap[point.x][point.y]]==!tside) //目标点有对方的棋子
{
ate=tmap[point.x][point.y]; //记录下被吃掉的棋子
if(ate==0 || ate==16)
{
return 9999;
}
tmanposition[ate].x=0; //目标点的棋子被吃掉
}

tmap[point.x][point.y]=man; //这两行是:
tmap[xs][ys]=32; //在map上的移动
tmanposition[man]=point;
tside=!tside;
//####################################################################################

depth--;

if(depth>0) //不是底层结点
{
int chessman[125];
POINT targetpoint[125];
if(EnumList(tmap,tmanposition,tside,chessman,targetpoint,count)) //枚举出所有子结点(列出所有走法)
{
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//这里是剪枝(不是α-β剪枝), 原理是在正式搜索之前先用较浅的搜索来得到误差较大的值
//然后根据这些值来对子结点排序, 只保留最好的S_WIDTH个结点进行正式搜索。
//显然,这个剪枝有一定的风险

if(depth>=2 && count>S_WIDTH+2)
{
int value[125];
cur=0;
maxvalue=-10000;
while(cur< count)
{
curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],-10000,depth-2);
value[cur]=curvalue;
if(curvalue>maxvalue)maxvalue=curvalue;
cur ++;
}
::Mantis_QuickSort(value,chessman,targetpoint,0,count-1); //排序
count=S_WIDTH;//剪枝
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

maxvalue=-10000;
cur=0;
while(cur< count)
{
curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],maxvalue,depth);
if(curvalue>maxvalue)maxvalue=curvalue;
if(curvalue>=-upmax)goto _ENDSUB; //α-β剪枝, 符合剪枝条件的就Cut掉。 这里用了goto语句了, 千万别学我。
cur ++;
}
}
else maxvalue=9800;
}
else //是底层结点
{
maxvalue=Value(tmap,tmanposition,tside); //估值
}

_ENDSUB:

//返回之前要恢复父结点的局面
//####################################################################################
tmanposition[man].x=xs; //这两行是:
tmanposition[man].y=ys; //在face上的恢复
tmap[xs][ys]=man; //在map上的恢复
if(ate!=32)
{
tmanposition[ate]=point;
tmap[point.x][point.y]=ate;
}
else tmap[point.x][point.y]=32;

tside=!tside;
//####################################################################################

return -maxvalue;
}

上面的代码用到了α-β剪枝, 举个例子就明白了:

还是这个博弈树,从上往下遍历。

1a( 1) ┳ 2a(-1) ┳ 3a(-1)
┃ ┗ 3b( 1)
┗ 2b(-5) ┯ 3c( 2)
├ 3d(-4)
└ 3e( 5)

2a遍历完后 upmax=-1, 继续遍历完3c后返回2b, 发现3c=2>-upmax, 这时就不用管3d和3e了, 因为无论他们的值是多少 2b=-max(3c,3d,3e)<2a 一定成立,
也就是说2b可以安全地剪掉。这就是α-β剪枝。

从上面的代码来看MantisChess算法与标准的α-β剪枝搜索并没有什么不同, 只不过加了排序和剪枝而已。

热心网友 时间:2023-04-29 06:16

人工智能下棋软件通常主要包括:
1、棋书棋谱、对局记录。
2、按规则穷举优劣。完全这样的话出招理论上是最佳方案,但这样时间太长,计算机难以招架,而且如果真是这样,结局可能是先手必胜、或必和、或必输。
3、模拟人类思考,至少短时间有优势,例如,在目前没有危险的情况下,多吃对方一个子是有利的等等。
4、根据实际局面紧迫程度,综合适当结合上述方式计算结果出招。但不一定是最优。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
...酸奶一个苹果,一个椪柑,中午一碗燕麦片白味的,一片奥利 冮铃全顺共轨柴油发动机难着车 在大医院测到智商117是真的吗,医生会不会骗人? 杭州解放军117医院的口腔科怎么样?口腔科在总院还是分院?117医院怎么样... 杭州117医院好不好的?我7月份在那里实习?不知道宿舍条件怎么样?谁能告... 在杭州解放军117医院实习怎么样? 安徽沐云实业有限公司怎么样? 安徽宗达建设工程有限公司怎么样? 安徽彩迪商业管理有限公司怎么样? 安徽韦航投资管理有限公司公司简介 两个人工智能下象棋,先手胜还是后手胜? 干煸鱿鱼须做法 鱿鱼须的家常做法大全怎么做好吃视频 干煸鱿鱼须的做法步骤图,干煸鱿鱼须怎么做 怎么做干煸鱿鱼须? 干煸鱿鱼须的家常做法大全怎么做好吃 我的手机微信从昨晚开始打开后一闪一闪的,不能正常使用,是啥原因咋办? 手机掉了.抖音能够用.微信不能用是什么原因? 苹果手机微信显示无法使用怎么办 为什么手机内存不足的时候是用不了微信的? 微信网络连接不可用怎么回事安卓 手机微信网络不可用是什么原因 笔记本电脑能换CPU吗?换个一般的要遭多少钱? 电脑换个主板 CPU大约多少钱 都什么要换 笔记本电脑更换cpu大概多少钱 笔记本换CPU大约要多少钱? 电脑换个处理器多少钱 换CPU要多少钱 涓怎么读音 电脑换一个CPU要多少钱 大家觉得象棋人工智能下得赢象棋特级大师吗 象棋被ai破解了,先走的赢吗 象棋特级大师比赛能赢电脑吗? 人工智能十年前胜了哪位中国象棋大师 中国象棋被ai算尽了吗? 象棋人工智能未来谁最强 中国象棋AI实现? 人类棋手有没有可能战胜AI(围棋,象棋)? 中国象棋暗棋的人工智能如何实现? 人机大战与网络象棋的介绍 用阿尔法狗下中国象棋 iphone11序列号全数字 iphone 11位序列号 iphone11序列号f4开头是哪里产的 冰箱冷藏柜不结冰什么情况?档位都开到5档了 冰箱不结冰怎么办 梦幻西游怎么查看角色转区历史 梦幻西游转区怎么查询 梦幻西游转区多少钱 梦幻西游手游怎么转区 梦幻西游怎么查询自己转区了多少时间了