分享
 
 
 

五子棋人机交互

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

五子棋人机交互 程序分两部分:1。核心程序 2。windows图形界面程序

此处只介绍核心程序部分。下面,我们边看边侃。

//========定义文件部分=============================

#define MAX_LENGTH 19 //棋盘格数

#define COMPUTER 1 //计算机棋子

#define PLAYER 2 //玩家棋子

int qp[MAX_LENGTH][MAX_LENGTH]; //定义棋盘

int iswin; //输赢标记,1=计算机胜,2=玩家胜,0=未分胜负;

#define RandInt(n) (rand()%n) //随机数宏

struct LIST

{

int id;

struct LIST *next;

}*PList=NULL,*CList=NULL; //定义链表,Plist为玩家棋局链表指针,用于阻击,Clist为计算机棋局链表指针,用于攻击

//=========核心程序代码部分=========================

//本函数将数据add添加到链表中,并将数据按从大到小排序

//add低位为棋盘位置,高位代表该位置在当前棋局中的优先级

static int AddList(struct LIST **List,int add)

{

struct LIST *tmp=*List;

struct LIST **temp=List;

int atemp=add>>16;

int id;

struct LIST *newlist=malloc(sizeof(*newlist));

if(!newlist)

return 1;

while(tmp)

{

id=(tmp->id)>>16;

if(id<=atemp)

break;

if(id>atemp)

{

temp=&(tmp->next);

tmp=tmp->next;

}

}

newlist->id=add;

newlist->next=tmp;

*temp=newlist;

return 0;

}

//函数获得指定链中最大优先级的值

static int GetMax(struct LIST *List)

{

if(List)

return (List->id>>16);

return 0;

}

//函数获得指定链中的链首数据

static int GetLast(struct LIST **List)

{

if(*List)

{

int ret;

struct LIST *temp;

ret=((*List)->id&0xffff);//取低字节棋盘位置数据

temp=*List;

*List=(*List)->next;

free(temp);

return ret;

}

return 0;

}

#define DestroyList(l) while(GetLast(&l)) //宏——销毁链表

//函数探测参数tmp指定的棋盘位置的优先级并加入相应的链表中

//凡进入该函数扫描的点,皆为棋盘上的空位置。我们将在此处分析该位置在棋局中的地位。

//tmp=y*MAX_LENGTH+x

static int AddTo_List(int tmp)

{

int temp;

int py,px;

py=tmp/MAX_LENGTH;

px=tmp%MAX_LENGTH;

//探测计算机在此位置的优先级

qp[py][px]=COMPUTER;

temp=scan(px,py,0);//最后一个参数必须为0,否则将进入死循环。

AddList(&CList,(temp<<16)+tmp);

//探测玩家在此位置的优先级

qp[py][px]=PLAYER;

temp=scan(px,py,0);//同上。

AddList(&PList,(temp<<16)+tmp);

qp[py][px]=0;//恢复空子状态。

return 0;

}

//函数对指定的棋盘位置进行格式化全方位扫描,并返回该位置在棋局中的优先级

//进行格式化扫描,可以减少扫描的冗余度,提高扫描效率。这对于大棋盘,如本例的19*19

尤为适用。

//mode控制扫描方式,0=试验性扫描,不将扫描结果加入链表。1=实战性扫描,将扫描结

果加入链表。程序可利用链表中的数据,进行下一步棋的决策。

//px,py在循环中反复使用,我们为其加上const标记,防止不必要的麻烦。

static int scan(const int px,const int py,int mode)

{

register int i;

int play=qp[py][px];//获得该位置棋子

int ret=0;rtemp=0;//返回值

int temp[4];

int base;

base=RandInt(8);//生成随机数,使用不同的起点,使棋局具有一定的随机性

//对该棋子八个方向进行扫描

for(i=0;i<8;i++)

{

int x=px;

int y=py;

int side=0;//边界标记

register j;

switch((base+i)%8)

{

case 0://x--

{

//格式化,首先定位到第一个不与play相同的位置。

//这样,在此方向上,我们便可以只考虑四格棋盘位置,大大减少了不必要的开销。

do

{

x--;

}while(x>=0&&qp[y][x]==play);

//该方向前面没有充足的位置,置标记位为1。这样,我们可以略去无效探测。

if(x+5>MAX_LENGTH)

{

side=1;

}

else

{

x+=2;//沿该方向向前,跳过第一个与play相等的位置,对前方四个位置进行纪录

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);//将棋盘位置合成整型数据保存

x++;

}

}

break;

}

case 1://x--;y--;

{

do

{

x--;

y--;

}while(x>=0&&y>=0&&qp[y][x]==play);

if(x+5>MAX_LENGTH||y+5>MAX_LENGTH)

{

side=1;

}

else

{

x+=2;

y+=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

x++;

y++;

}

}

break;

}

case 2://y--;

{

do

{

y--;

}while(y>=0&&qp[y][x]==play);

if(y+5>MAX_LENGTH)

{

side=1;

}

else

{

y+=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

y++;

}

}

break;

}

case 3://x--;y++;

{

do

{

x--;

y++;

}while(x>=0&&y<MAX_LENGTH&&qp[y][x]==play);

if(x+5>MAX_LENGTH||y-5<0)

{

side=1;

}

else

{

x+=2;

y-=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

x++;

y--;

}

}

break;

}

case 4://x++;

{

do

{

x++;

}while(x<MAX_LENGTH&&qp[y][x]==play);

if(x-5<0)

{

side=1;

}

else

{

x-=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

x--;

}

}

break;

}

case 5://x++;y--;

{

do

{

x++;

y--;

}while(x<MAX_LENGTH&&y>=0&&qp[y][x]==play);

if(x-5<0||y+5>MAX_LENGTH)

{

side=1;

}

else

{

x-=2;

y+=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

x--;

y++;

}

}

break;

}

case 6://x++;y++;

{

do

{

x++;

y++;

}while(x<MAX_LENGTH&&y<MAX_LENGTH&&qp[y][x]==play);

if(x-5<0||y-5<0)

{

side=1;

}

else

{

x-=2;

y-=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

x--;

y--;

}

}

break;

}

case 7://y++;

{

do

{

y++;

}while(y<MAX_LENGTH&&qp[y][x]==play);

if(y-5<0)

{

side=1;

}

else

{

y-=2;

for(j=0;j<4;j++)

{

temp[j]=(MAX_LENGTH*y+x);

y--;

}

}

break;

}

}

if(!side)

{

//该部分是决定优先级的关键部分,本例只使用了简单的优先级决定方案,可以通过修改该部分使程序具有更高的智能。

int t=0;

int k[4]={8,4,2,1};

int kt[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

//对纪录的棋盘位置进行检测

for(j=0;j<4;j++)

{

int jx=temp[j]%MAX_LENGTH;

int jy=temp[j]/MAX_LENGTH;

int p=qp[jy][jx];

if(p==play)

t+=k[j];

else if(p==0)//可利用位置

{

if(mode)

AddTo_List(temp[j]);//对可利用位置进行探测纪录

}

else//存在阻隔

{

t--;//此处有可能使t=-1,因为t用于数组下标,所以我们必须将其排除。

if(t<0)

t=0;

break;

}

}

if(t==0xf&&mode)//若五子连成一线,返回零

return 0;

if(ret<kt[t])

{

ret=kt[t];

if(ret>rtemp)

{

int t=ret;

ret=rtemp;

rtemp=t;

}

}

}

}

return (ret+rtemp);//当前局势

}

//初始化棋盘

void initqp(void)

{

register int i;

register int j;

for(i=0;i<MAX_LENGTH;i++)

for(j=0;j<MAX_LENGTH;j++)

qp[i][j]=0;

iswin=0;

srand(time(NULL));//初始化随机生成器

}

//主函数,检测玩家所走位置,返回计算机所走位置

//px,py代表玩家棋子位置。

int five(int px,int py)

{

struct LIST **list;

int tmp;

if(qp[py][px]!=0)//该位置已存在棋子

{

return -1;

}

//对玩家所走棋子进行扫描

qp[py][px]=PLAYER;

if(!scan(px,py,1))

{

//玩家胜

DestroyList(PList);

DestroyList(CList);

iswin=PLAYER;

return 0;

}

if(GetMax(PList)>GetMax(CList))//确定攻击性

list=&PList;//防御

else

list=&CList;//攻击

while(tmp=GetLast(list))//获取最大优先级的棋盘位置

{

px=tmp%MAX_LENGTH;

py=tmp/MAX_LENGTH;

if(qp[py][px]!=0)//该位置不为空则继续循环

{

if(GetMax(PList)>GetMax(CList))//重新确定攻击性

list=&PList;

else

list=&CList;

continue;

}

break;

}

if(!tmp) //在链表中未找到数据则生成随机数据

{

do

{

px=RandInt(MAX_LENGTH);

py=RandInt(MAX_LENGTH);

}while(qp[py][px]!=0);

}

//计算机走子

qp[py][px]=COMPUTER;

if(!scan(px,py,1))

{

//计算机胜

DestroyList(PList);

DestroyList(CList);

iswin=COMPUTER;

}

return ((py*MAX_LENGTH)+px);//返回走子位置

}

核心程序部分就这么多,图形界面部分只需调用函数initqp()初始化棋盘,然后不断调用函数five(int px,int py)即可。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有