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)。
为了方便操作,在程序中对棋子定义了数据结构:
typedef struct
{
int r; //行号
int c; //列号
int s; //棋类别
int f; //棋子存活期
int q; //棋子外气数
int l; //棋子队列号
int n; //有无棋子
}QZ;
QZ QiZiBF[400];
QZ BOXBF[19][19];
检测棋盘上某一位置的外气实现函数:
int Get_QI(int r,int c)
{
int t=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++;
return t;
}
为了更好的计算棋子的外气,把同类连在一起的棋子(纵横方向相连)编成一个列队,
就是用一个统一的代号表示它们。这是实现自动提子的关键所在,因为只要找到其中一颗棋
子,根据代号就能找到全部。在程序中用下函数描述: void SelectLists(int r,int c) {
int i,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)