ITPub博客

首页 > IT职业 > IT生活 > 五子棋人机交互 (转)

五子棋人机交互 (转)

原创 IT生活 作者:amyz 时间:2007-11-16 16:05:10 0 删除 编辑
五子棋人机交互 (转)[@more@]

五子棋人机交互

程序分两部分: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&&yMAX_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=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  {
  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;iGetMax(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)即可。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752019/viewspace-982619/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    3984
  • 访问量
    7364190