c语言编程一个象棋游戏,急求:C语言编写的中国象棋游戏一个

急求:C语言编写的中国象棋游戏一个

來源:互聯網  2009-09-08 12:30:35  評論

分類: 電腦/網絡 >> 程序設計 >> 其他編程語言

問題描述:

由于学习需要......热烈欢迎个位大侠,高手相助!小生在此道谢了!!! 希望留下您的邮箱或者QQ以遍交流。20分哦

參考答案:

先弄明白数据的结构:

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

{

算出子结点局面;

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算法与标准的α-β剪枝搜索并没有什么不同, 只不过加了排序和剪枝而已。

[b]分类:[/b] 电脑/网络 >> 程序设计 >> 其他编程语言[br][b]问题描述:[/b][br]由于学习需要......热烈欢迎个位大侠,高手相助!小生在此道谢了!!! 希望留下您的邮箱或者QQ以遍交流。20分哦[br][b]参考答案:[/b][br]先弄明白数据的结构:

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

{

算出子结点局面;

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算法与标准的α-β剪枝搜索并没有什么不同, 只不过加了排序和剪枝而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

grunt 前端开发环境搭建

1.找管理员开通gitlab权限 2.下载并安装git工具 3.下载并安装nodejs 4.安装cnpm 5.安装kulor&#xff0d;cli cnpm install -g kulor-cli cnpm install -g grunt-cli cnpm install 6.安装nginx并运行 7.进入到工作目录 运行 grunt 补充如何从远程拉代码&#xff0c;在本地配…

获取referer中的请求参数_Servlet获取AJAX POST请求中参数以form data和request payload形式传输的方法...

本文实例讲述了Servlet获取AJAX POST请求中参数以form data和request payload形式传输的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;HTTP请求中&#xff0c;如果是get请求&#xff0c;那么表单参数以namevalue&name1value1的形式附到url的后面&#xff0c…

prim求最短路径C语言,[图论]Prim算法求最小支撑树和最短路径

这个是以前所学&#xff0c;现在总结成博文一篇。对于图论中的求解最小支撑树问题和最短路径问题都有比较经典的算法&#xff0c;比如最小支撑树可以采用“破圈法”&#xff0c;求解最短路径可以用“Dijkstra算法”。这里笔者将回顾下求解最小支撑树的Prim算法和最短路径算法。…

后台服务器端技术点(前沿了解)

1. OpenResty nginx lua 模式解决 高性能与开发效率 平衡。转载于:https://www.cnblogs.com/jhj117/p/5520250.html

pycharm镜像源_pycharm安装第三方库

点击蓝字关注我们hello&#xff0c;大家好&#xff0c;我是你们的小编大飞。小编一直在学习编程语言&#xff0c;挑选了很久之后决定入了python的坑(bushi)。而python之所以火&#xff0c;是因为它专注于如何解决问题、自由开放的社区环境以及丰富的第三方库。几乎可以这么说&a…

c语言实验指导,C语言实验指导

c语言实验用说,分享快乐!!!!《C语言程序设计》实验指导一、教师指导的实验实验1 (1)C语言上机指南和Visual C 6.0 的基本用法1. 实验目的了解VC开发环境。熟练掌握程序的基本开发过程。 掌握简单程序的设计。2. 实验内容和步骤 2.1. 进入C工作环境建立个人子目录&#xff1a;第…

JAVA并发七(多线程环境中安全使用集合API)

在集合API中&#xff0c;最初设计的Vector和Hashtable是多线程安全的。例如&#xff1a;对于Vector来说&#xff0c;用来添加和删除元素的方法是同步的。如果只有一个线程与Vector的实例交互&#xff0c;那么&#xff0c;要求获取和释放对象锁便是一种浪费&#xff0c;另外在不…

iptables nat表含义_十(4)iptables语法、iptables filter表小案例、iptables nat表应用

iptables语法filter表&#xff1a;INPUT链&#xff1a;作用于进入本机的包OUTPUT链&#xff1a;作用于送出本机的包FORWARD链&#xff1a;作用于和本机无关的包nat表&#xff1a;PREROUTING链&#xff1a;作用是包在刚刚到达防火墙时改变包的目标地址OUTPUT链&#xff1a;改变本…

c语言Max错误,C语言编程常见错误.pdf

C 语言常见错误版权声明&#xff1a;以下内容来自互联网C 语言的最大特点是&#xff1a;功能强、使 方便灵活。C 编译的程序对语法检查并不象其它高级语言那么严格&#xff0c;这就给编程人员留下 “灵活的余地”&#xff0c;但还是由于这个灵活给程序的调试带来了许多不便&…

算法训练 连续正整数的和

问题描述78这个数可以表示为连续正整数的和&#xff0c;123&#xff0c;18192021&#xff0c;252627。输入描述输入一个正整数 n(<10000)输出描述输出 m 行(n有m种表示法)&#xff0c;每行是两个正整数a&#xff0c;b&#xff0c;表示a(a1)...bn。对于多种表示法&#xff0c…

android libev 编译,libev-4.20编译安装及简单使用

1.源码下载地址:链接&#xff1a;https://pan.baidu.com/s/1fxotILo3oTMC65z4qFAh9Q 密码&#xff1a;oc312.库的编译与安装解压文件&#xff0c;进入文件目录编译的时候需要首先切换为管理员(root)账户&#xff0c;然后执行以下命令&#xff1a;./configuremakemake install编…

android系统源码的环境下用make来编译,Android源码编译系统入门

做过 Android 平台开发的朋友对make&#xff0c;mm或make clean命令应该很熟悉&#xff0c;但也许大家只是熟知这些命令的作用却不知道这些命令底下有些什么原理&#xff1f;那么今天我就带着大家推开Android编译系统的大门&#xff0c;探索一下这片未知的恐怖之森(问啥要用恐怖…

bootsrap 外边距_Bootstrap CSS 概览

Bootstrap CSS 概览在这一章中&#xff0c;我们将讲解 Bootstrap 底层结构的关键部分&#xff0c;包括我们让 web 开发变得更好、更快、更强壮的最佳实践。HTML 5 文档类型(Doctype)Bootstrap 使用了一些 HTML5 元素和 CSS 属性。为了让这些正常工作&#xff0c;您需要使用 HTM…

jstl表达式替换某些字符

转自:http://www.yiibai.com/jsp/jstl_function_replace.html fn:replace() 函数替换一个字符串与另一个字符串的所有匹配。 语法 fn:replace () 函数语法如下&#xff1a; boolean replace(java.lang.String, java.lang.String, java.lang.String) 例子&#xff1a; 下面是一个…

android socket 闪退,android客户端闪退

老师&#xff0c;我把客户端的代码放在android程序里&#xff0c;给一个button监听事件&#xff0c;就是调用这个socket方法&#xff0c;但是一点button就闪退了&#xff0c;没连接上~protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState)…

(mac)阿里云ECS服务器配置过程

-----首先本人是半只脚入门的iOS开发者&#xff0c;弄这个只是单纯想多学点东西。 -----阿里云服务器的配置选择&#xff1a;既然是学习用的&#xff0c;最最基础的配置就行了。1M带宽&#xff0c;1核1G...这就不详述了。没啥可选的&#xff0c;&#xff08;其中有个创建实例&a…

android 换到iphone,从安卓换到苹果到底是什么感受?最后一个让我彻底放弃了iPhone!...

原标题&#xff1a;从安卓换到苹果到底是什么感受&#xff1f;最后一个让我彻底放弃了iPhone&#xff01;iPhone X是近几年来苹果最具创新力的iPhone&#xff0c;然而高昂的售价让很多消费者望而却步。随着今年苹果秋季新品发布会的临近&#xff0c;苹果即将发布价格更低廉&…

mac谷歌浏览器怎么登陆账户_mac怎么下chrome浏览器

mac怎么下chrome浏览器&#xff1f;首先打开Safari浏览器百度搜一下谷歌浏览器官网&#xff0c;进入官网页面下载或者也可以直接打开下面的网址进入官网https://www.google.cn/intl/zh-CN/chrome/点击网页上的”下载Chrome“弹出提示&#xff0c;选择”接受并安装“等待软件下载…

php 5.5 xhprof for windows

今天看到一个好的性能优软件xhprof&#xff08;有facebook开发的类库)在国内找了很多网站都没有找到相关php5.5的扩展&#xff0c;只好FQ还是外面的世界精彩一下就找到了link (http://windows.php.net/downloads/pecl/releases/xhprof/0.10.6/)如果不能FQ的小伙伴可以到我的百度…

鸿蒙分布式体验,一张图看懂鸿蒙OS 2.0 分布式能力升级构筑全场景体验

原标题&#xff1a;一张图看懂鸿蒙OS 2.0 分布式能力升级构筑全场景体验【手机中国新闻】9月10日下午&#xff0c;华为召开HDC2020大会&#xff0c;全新的HarmonyOS 2.0正式发布。新系统的分布式能力全面升级&#xff0c;同时还为开发者提供了完整分布式设备与应用开发生态&…