C语言围棋对弈程序设计.docx
- 文档编号:24837283
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:47
- 大小:174.02KB
C语言围棋对弈程序设计.docx
《C语言围棋对弈程序设计.docx》由会员分享,可在线阅读,更多相关《C语言围棋对弈程序设计.docx(47页珍藏版)》请在冰豆网上搜索。
C语言围棋对弈程序设计
C语言围棋对弈程序设计
用C语言编写一个围棋对弈棋室的程序,模仿两人对弈的过程,其中包括自动提子功能,和自动点目功能。
1、围棋的一些基本常识:
(1)围棋棋子的“气”
见右图1所示黑棋1有4“气”,分别是水平方向上的左右
各有一气,垂直方向上的上下各有一气,对角上的不是它的气。
图1棋子外“气”
(2)提子(吃子),当下在棋盘上的棋子没有外气时便被提掉(死棋)。
图2、打吃状态图3、提子
图2中黑1和白2都只有一口外气,图3黑先下7位白2没有外气被提掉。
图4、倒扑提子过程图5死穴
图4演示了倒扑提子全过程,图中左上为原型,左下黑先黑41扑,右上白64提,右下黑93反提把白棋全吃掉。
(3)死穴:
上图5黑1、3、5、7四颗黑子中间交差点对白棋来说是死穴,白棋下不进处,但对黑棋不影响可下见图下方。
2、自动提子功能实现
下在棋盘上的棋子同类别的在某一方位上可能是一颗或是一片(纵横连续的),要实现自动提子首要的是计算清楚这些同类棋子的所有外气是多少,如果已经没有外气提掉。
一颗棋子下在棋盘上最多有4口外气(见图1),在边上有3气,在角上只有2气。
在程序中对于每一颗棋子检测外气描述如下:
检测棋子可能有的方向上(上、下、左、右)是否有棋子,
如果有,那么在该方向上没有外气。
如果在所有的方向上都有棋子,那么它在棋盘上是无外
气的。
如果在它所有方向上没有同类棋子而且又无外气,那么该颗棋子可以提掉(见图3)。
如果在某一方向上有同类棋子,必须计算完连在一起同类的所有外气。
如果整片无外气,该
片可以提掉(见图4)。
为了方便操作,在程序中对棋子定义了数据结构:
typedefstruct
{
intr;//行号
intc;//列号
ints;//棋类别
intf;//棋子存活期
intq;//棋子外气数
intl;//棋子队列号
intn;//有无棋子
}QZ;
QZQiZiBF[400];
QZBOXBF[19][19];
检测棋盘上某一位置的外气实现函数:
intGet_QI(intr,intc)
{
intt=0;
if(r>0)
if(BOXBF[r-1][c].n==0)
t++;
if(r<18)
if(BOXBF[r+1][c].n==0)
t++;
if(c>0)
if(BOXBF[r][c-1].n==0)
t++;
if(c<18)
if(BOXBF[r][c+1].n==0)
t++;
returnt;
}
为了更好的计算棋子的外气,把同类连在一起的棋子(纵横方向相连)编成一个列队,
就是用一个统一的代号表示它们。
这是实现自动提子的关键所在,因为只要找到其中一颗棋
子,根据代号就能找到全部。
在程序中用下函数描述:
voidSelectLists(intr,intc){
inti,j,k;
if(r>0)
if(BOXBF[r-1][c].n==1&&BOXBF[r-1][c].s==BOXBF[r][c].s)
BOXBF[r][c].l=BOXBF[r-1][c].l;
if(r<18)
{
if(BOXBF[r+1][c].n==1&&BOXBF[r+1][c].s==BOXBF[r][c].s)
{
if(BOXBF[r][c].l { k=BOXBF[r+1][c].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r][c].l; } else { k=BOXBF[r][c].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r+1][c].l; } } } if(c>0) { if(BOXBF[r][c-1].n==1&&BOXBF[r][c-1].s==BOXBF[r][c].s) { if(BOXBF[r][c].l { k=BOXBF[r][c-1].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r][c].l; } else { k=BOXBF[r][c].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r][c-1].l; } } } if(c<18) { if(BOXBF[r][c+1].n==1&&BOXBF[r][c+1].s==BOXBF[r][c].s) { if(BOXBF[r][c].l { k=BOXBF[r][c+1].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r][c].l; } else { k=BOXBF[r][c].l; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].l==k) BOXBF[i][j].l=BOXBF[r][c+1].l; } } } } 检测每颗棋子外气的函数: voidDetectQi() { inti,j; for(i=0;i<19;i++) for(j=0;j<19;j++) if(BOXBF[i][j].n==1) BOXBF[i][j].q=Get_QI(i,j);} 计算整个列队的外气函数: intGetListsQI(intr,intc,inttq){ inti,j,k,mq=0; for(i=0;i<19;i++) for(j=0;j<19;j++) { if(BOXBF[i][j].l==BOXBF[r][c].l&&BOXBF[i][j].s==tq) mq+=BOXBF[i][j].q; } returnmq; } 3、自动点目功能的实现 当棋局收完官子,把所有可下的地方下完,把双方盘面上的死子清除后逐行扫描棋盘。 如果行开始无棋子,当遇到棋子时前面的空为该类棋子的实空。 如果行末无棋子,该行最大行号减空地数为何棋子实空为它所有。 各方实空加同类在棋盘上有效棋子数为各方总棋子数。 黑棋数减白棋数乘以2减贴目数为该局的最后结果。 voidOutScore() { inti,j,ws=0,bs=0,k; floats; charcn[10]; for(i=0;i<19;i++) { k=0; for(j=0;j<19;j++) { if(BOXBF[i][j].n==0) k++; if(BOXBF[i][j].n==1&&BOXBF[i][j].s==BLACKQI) { bs+=k+1; k=0; } if(BOXBF[i][j].n==1&&BOXBF[i][j].s==WHITEQI) { ws+=k+1; k=0; } if(j==18&&BOXBF[i][18].n==0) { if(BOXBF[i][18-k].s==BLACKQI) bs+=k; if(BOXBF[i][18-k].s==WHITEQI) ws+=k; } } } k=bs-ws; s=2*k-6.5; setfillstyle(1,9); Bar(470,250,615,310,4); setcolor(4); if(s<0) { s=-s; sprintf(cn,"%.1f",s); OutCh(mat[1],12,480,280,15); OutCh(mat[18],12,493,280,15); outtextxy(530,280,cn); OutCh(mat[5],12,570,280,15); } else { sprintf(cn,"%.1f",s); OutCh(mat[0],12,480,280,15); OutCh(mat[18],12,493,280,15); outtextxy(530,280,cn); OutCh(mat[5],12,570,280,15); } } 4、棋子能下在棋盘上某一位置的条件 首先当前准备下子的位置没有棋子存在。 其次是当前准备下子的位置如果有外气能下子,如果没有外气,那么分为两种情况。 一是当前准备下子位置在能有的方向上的棋子种类一样并且与准备下的棋子种类不一样,得该位置不能下子,如图5所示黑棋1、3、5、7中间的位置白棋不能下。 二是当前准备下子位置在能有的方向上棋子种类不一样,此时又分几种情况: 一检测在能有方向上同类除了当前位置的外气外是否还有外气,如果有此处能下子,如果没有此处暂时不能下子,同时检测在能有的方向上不同类棋子除了当前位置外气外是否另有外气,如果有此处不能下子,如果无,那么此处能下子并且把没有外气的不同类棋子提掉(吃掉)。 实现函数: intSelect(intr,intc,inttq,inthq){ BOXBF[r][c].n=1; DetectQi(); if(r>0) { if(BOXBF[r-1][c].s==tq) { if(GetListsQI(r-1,c,tq)>0) { ShowCircle(r,c,tq); return0; } } else { if(GetListsQI(r-1,c,hq)==0) { HideCircle(r-1,c,hq); ShowCircle(r,c,tq); return0; } } } if(r<18) { if(BOXBF[r+1][c].s==tq) { if(GetListsQI(r+1,c,tq)>0) { ShowCircle(r,c,tq); return0; } } else { if(GetListsQI(r+1,c,hq)==0) { HideCircle(r+1,c,hq); ShowCircle(r,c,tq); return0; } } } if(c>0) { if(BOXBF[r][c-1].s==tq) { if(GetListsQI(r,c-1,tq)>0) { ShowCircle(r,c,tq); return0; } } else { if(GetListsQI(r,c-1,hq)==0) { HideCircle(r,c-1,hq); ShowCircle(r,c,tq); return0; } } } if(c<18) { if(BOXBF[r][c+1].s==tq) { if(GetListsQI(r,c+1,tq)>0) { ShowCircle(r,c,tq); return0; } } else { if(GetListsQI(r,c+1,hq)==0) { HideCircle(r,c+1,hq); ShowCircle(r,c,tq); return0; } } } BOXBF[r][c].n=0; DetectQi(); return0; } voidMakeQi(intr,intc){ inttq,hq,color; if(Rear<0) tq=BLACKQI; else { if(Rear%2==0) { hq=BLACKQI; tq=WHITEQI; } else { hq=WHITEQI; tq=BLACKQI; } } if(BOXBF[r][c].n==0) { if(Get_QI(r,c)) ShowCircle(r,c,tq); else Select(r,c,tq,hq); } } 以上两个函数很重要,在程序中是核心部分,对自动提子功能起到决定条件之一。 程序用Win-TC(1.9)编译器编写编译完成,整个过程用鼠标完成操作。 下图为围棋对弈室操作界面。 程序可在液晶显示器上正常显示图形 图6、程序操作界面 图6为程序中设计的围棋对弈室操作界面,界面中共有4个按钮,各功能如下所示: 关闭――――――退出返回操作系统 点目――――――收完官后计算结果 确定死子――――点击此处后可用鼠标左键选定死子并点击该子 完成――――――点击此处完成确定死子整个过程 图7、自动点目(白胜,贴目6.5目,共253手) 图8、白胜(共168手)以上图片均由该程序生成的屏幕截图。 附程序全部源码: #include"graphics.h" #include"dos.h" #include"math.h" #include"stdio.h" #defineBLACKQI1 #defineWHITEQI2 intPos[19]={70,90,110,130,150,170,190,210,230,250,270,290,310,330,350,370,390,410,430}; typedefstruct { intmx; intmy; intmkey; intbf[16][16]; }MOUSEH; MOUSEH*hw; typedefstruct { intr;//行号 intc;//列号 ints;//棋类别 intf;//棋子存活期 intq;//棋子外气数 intl;//棋子队列号 intn;//有无棋子 }QZ; QZQiZiBF[400]; QZBOXBF[19][19]; intMz[2]={0,0}; intRear=-1; intRm[3]; intGMove=0; charNb[][8]={ 0xf0,0x90,0x90,0x90,0xf0,0x00,0x00,0x00, 0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 0xf0,0x10,0xf0,0x80,0xf0,0x00,0x00,0x00, 0xf0,0x10,0xf0,0x10,0xf0,0x00,0x00,0x00, 0x90,0x90,0xf0,0x10,0x10,0x00,0x00,0x00, 0xf0,0x80,0xf0,0x10,0xf0,0x00,0x00,0x00, 0xf0,0x80,0xf0,0x90,0xf0,0x00,0x00,0x00, 0xf0,0x10,0x10,0x10,0x10,0x00,0x00,0x00, 0xf0,0x90,0xf0,0x90,0xf0,0x00,0x00,0x00, 0xf0,0x90,0xf0,0x10,0xf0,0x00,0x00,0x00,}; charN100[]={ 0x17,0xbc,0x14,0xa4,0x14,0xa4,0x14,0xa4, 0x17,0xbc,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; charmat[][24]={ 0x7F,0xC0,0x44,0x40,0x55,0x40,0x4E,0x40, 0x7F,0xC0,0x04,0x00,0x7F,0xC0,0x04,0x00, 0xFF,0xE0,0x52,0x40,0x89,0x20,0x00,0x00, 0x04,0x00,0x08,0x00,0x7F,0xC0,0x40,0x40, 0x40,0x40,0x40,0x40,0x7F,0xC0,0x40,0x40, 0x40,0x40,0x40,0x40,0x7F,0xC0,0x00,0x00, 0x00,0x40,0xF8,0x40,0x08,0x40,0x4F,0xE0, 0x28,0x40,0x12,0x40,0x11,0x40,0x29,0x40, 0x48,0x40,0x88,0x40,0x01,0xC0,0x00,0x00, 0x04,0x00,0xFF,0xE0,0x29,0x80,0x49,0x40, 0x91,0x20,0x67,0x00,0x11,0x00,0xFF,0xE0, 0x11,0x00,0x21,0x00,0xC1,0x00,0x00,0x00, 0xF9,0x00,0x89,0x00,0xA9,0xE0,0xA9,0x00, 0xA9,0x00,0xAB,0xE0,0xAA,0x20,0xAA,0x20, 0x52,0x20,0x4B,0xE0,0x82,0x20,0x00,0x00, 0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80, 0x20,0x80,0x20,0x80,0x3F,0x80,0x20,0x80, 0x20,0x80,0x3F,0x80,0x20,0x80,0x00,0x00, 0x03,0xC0,0xFC,0x00,0x04,0x00,0x7F,0xC0, 0x04,0x00,0x04,0x00,0xFF,0xE0,0x04,0x00, 0x04,0x00,0x04,0x00,0x1C,0x00,0x00,0x00, 0x95,0x00,0x59,0x00,0xFD,0xE0,0x32,0x40, 0x5A,0x40,0x95,0x40,0x21,0x40,0xFC,0x80, 0x48,0x80,0x39,0x40,0xC6,0x20,0x00,0x00, 0x27,0xC0,0x24,0x40,0xF7,0xC0,0x24,0x40, 0x37,0xC0,0x60,0x00,0xAF,0xE0,0x25,0x00, 0x25,0xC0,0x2B,0x00,0xF1,0xE0,0x00,0x00, 0x7F,0xC0,0x00,0x80,0x01,0x00,0x06,0x00, 0x04,0x40,0xFF,0xE0,0x04,0x00,0x04,0x00, 0x04,0x00,0x04,0x00,0x1C,0x00,0x00,0x00, 0x04,0x00,0x07,0xC0,0x04,0x00,0x04,0x00, 0x3F,0x80,0x20,0x80,0x20,0x80,0x3F,0x80, 0x00,0x00,0x49,0x40,0xC9,0x20,0x00,0x00, 0x02,0x00,0xFB,0xC0,0x24,0x80,0x4F,0xE0, 0x75,0x20,0xD7,0xE0,0x55,0x20,0x57,0xE0, 0x75,0x20,0x55,0x20,0x09,0x60,0x00,0x00, 0x04,0x00,0x7F,0xE0,0xC0,0x20,0x00,0x00, 0x7F,0xC0,0x04,0x00,0x24,0x00,0x27,0xC0, 0x34,0x00,0x4C,0x00,0x83,0xE0,0x00,0x00, 0x00,0x40,0xFF,0xE0,0x22,0x00,0x22,0x00, 0x3A,0x60,0x4B,0x80,0xAA,0x00,0x12,0x00, 0x22,0x20,0x42,0x20,0x81,0xE0,0x00,0x00, 0x04,0x00,0xFF,0xE0,0x80,0x20,0x3F,0x80, 0x00,0x00,0x00,0x00,0xFF,0xE0,0x12,0x00, 0x12,0x20,0x22,0x20,0xC3,0xE0,0x00,0x00, 0x02,0x80,0x02,0x40,0x7F,0xE0,0x42,0x00, 0x42,0x40,0x7A,0x40,0x4A,0x80,0x49,0x00, 0x69,0x20,0x52,0xA0,0x84,0x60,0x00,0x00, 0x10,0x80,0x09,0x00,0x7F,0xC0,0x04,0x00, 0x04,0x00,0x04,0x00,0xFF,0xE0,0x0A,0x00, 0x11,0x00,0x20,0x80,0xC0,0x60,0x00,0x00, 0x27,0xE0,0x10,0x20,0x42,0x20,0x42,0x20, 0x7F,0xA0,0x46,0x20,0x4A,0x20,0x52,0x20, 0x62,0x20,0x4E,0x20,0x40,0xE0,0x00,0x00, 0x71,0x00,0x55,0x00,0x55,0x00,0x77,0xE0, 0x59,0x00,0x51,0x00,0x77,0xE0,0x51,0x00, 0x51,0x00,0x91,0x00,0xBF,0xE0,0x00,0x00, 0x04,0x00,0x0A,0x00,0x11,0x00,0x24,0x80, 0xC4,0x60,0x04,0x00,0x04,0x00,0x04,0x00, 0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,}; voidLine(intx1,inty1,intx2,inty2,intcolor){ intdr; floatr,c,k; r=y2-y1;c=x2-x1; if(abs(r)>abs(c)) { if(r! =0) { k=c/r; if(r>0) for(dr=0;dr<=r;dr+=1) putpixel(x1+dr*k+0.5,y1+dr,color); if(r<0) for(dr=0;dr<=-r;dr+=1) putpixel(x2+dr*k+0.5,y2+dr,color); } else { if(c>
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 围棋 对弈 程序设计
![提示](https://static.bdocx.com/images/bang_tan.gif)