/***************************************************************************************\ modify at 2006.3.28\***************************************************************************************/#include <graphics.h>#include <stdio.h>#include <malloc.h>#include <time.h>#include <math.h>#include <stdlib.h> #include <mousea1.h> #define MAX 15#define OFFSET 8 /* 14*14=196<2^8-1=255 偏移8位足够,而优先级最大也是16 */#define PAN_X 125 /*棋盘初始位置,左上角坐标(125,75) */#define PAN_Y 75 #define COMPUTER 1 /*计算机棋子 */#define PLAYER 2 /*玩家棋子 */int qp[MAX][MAX]; /*定义棋盘 */int iswin; /*输赢标记,1=计算机胜,2=玩家胜,0=未分胜负;*/int key; struct LIST { int id; struct LIST *next;}*PList=NULL,*CList=NULL; /*定义链表,Plist为玩家棋局链表指针,用于阻击,Clist为计算机棋局链表指针,用于攻击 */ void * mouse_buf;MOUSE mouse;void ResumeGraphics(int x,int y,void *p);bool GetBuf(int x,int y,int xx,int yy,void *p);void qizi(int px,int py,int color);void kuang(int px,int py,int color); static int black_x=MAX,black_y=MAX; /* 预先置初始位置,在画框外 */ static int AddList(struct LIST **List,int add){ struct LIST *tmp=*List, **temp=List; int atemp=add>>OFFSET; int id; struct LIST *newlist=malloc(sizeof(*newlist)); if(!newlist) return 1; while(tmp) { id=(tmp->id)>>OFFSET; 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>>OFFSET); return 0; } static int GetLast(struct LIST **List) /*函数获得指定链中的链首数据 */{ if(*List) { int ret; struct LIST *temp; ret=((*List)->id& 0xff); /* 取低字节棋盘位置数据 , 0xff与OFFSET位数一致 */ temp=*List; /* 记住需要销毁的结点,使用的结点销毁 */ *List=(*List)->next; free(temp); return ret; } return 0;}#define DestroyList(L) while(GetLast(&L)) /*宏——销毁链表 *//*函数探测参数tmp指定的棋盘位置的优先级并加入相应的链表中 *//*凡进入该函数扫描的点,皆为棋盘上的空位置。我们将在此处分析该位置在棋局中的地位。*/ static int AddTo_List(int tmp){ int temp,py,px; py=tmp/MAX; px=tmp%MAX; /*探测计算机在此位置的优先级 ,tmp=y*MAX+x */ qp[py][px]=COMPUTER; temp=scan(px,py,0); /*最后一个参数必须为0,否则将进入死循环。 */ AddList(&CList,(temp<<OFFSET)+tmp); /*探测玩家在此位置的优先级 */ qp[py][px]=PLAYER; temp=scan(px,py,0); /*同上。 */ AddList(&PList,(temp<<OFFSET)+tmp); qp[py][px]=0; /*恢复空子状态。 */ return 0;} 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=random(8); /* 生成随机数,使用不同的起点,使棋局具有一定的随机性 */ for(i=0;i<8;i++) /*对该棋子八个方向进行扫描 */ { int x=px,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) side=1 ; else { x+=2 ; /*沿该方向向前,跳过第一个与play相等的位置,对前方四个位置进行纪录 */ for(j=0;j<4;j++) { temp[j]=(MAX*y+x); x++; } /*将棋盘位置合成整型数据保存 */ } break ; } case 1 :{ /*x--;y--; */ do { x--; y--; } while(x>=0&&y>=0&&qp[y][x]==play); if(x+5>MAX||y+5>MAX) side=1 ; else { x+=2 ; y+=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); x++; y++; } } break ; } case 2 :{ /*y--; */ do {y--; } while(y>=0&&qp[y][x]==play); if(y+5>MAX) side=1 ; else { y+=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); y++; } } break ; } case 3 :{ /*x--;y++; */ do { x--; y++; } while(x>=0&&y<MAX&&qp[y][x]==play); if(x+5>MAX||y-5<0)side=1 ; else { x+=2 ; y-=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); x++; y--; } } break ; } case 4 :{ /*x++; */ do { x++; } while(x<MAX&&qp[y][x]==play); if(x-5<0)side=1 ; else { x-=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); x--; } } break ; } case 5 :{ /*x++;y--; */ do { x++; y--; } while(x<MAX&&y>=0&&qp[y][x]==play); if(x-5<0||y+5>MAX)side=1 ; else { x-=2 ; y+=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); x--; y++; } } break ; } case 6 :{ /*x++;y++; */ do { x++; y++; } while(x<MAX&&y<MAX&&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*y+x); x--; y--; } } break ; } case 7 : { /*y++; */ do { y++; } while(y<MAX&&qp[y][x]==play); if(y-5<0)side=1 ; else { y-=2 ; for(j=0;j<4;j++) { temp[j]=(MAX*y+x); y--; } } break ; } } if(!side) { /*该部分是决定优先级的关键部分,本例只使用了简单的优先级决定方案,可以通过修改该部分使程序具有更高的智能。*/ int t=0 ; int k[4]= { 8,4,2,1 }; /* 可以把mode=0,1两种情况分开讨论kt[mode][16]*/ int kt[16]= { 1,2,4,3,5,6,7,13,9,10,11,12,8,14,15,16} ;/* 关键顺序此顺序,对不同情况着子顺序 */ for(j=0;j<4;j++) /*对纪录的棋盘位置进行检测 */ { int jx=temp[j]%MAX,jy=temp[j]/MAX ; int p=qp[jy][jx]; if(p==play) t += k[j]; else if(p==0) { /* 可利用位置 */ if(mode) AddTo_List(temp[j]); /*对可利用位置进行探测纪录 */ } /* scan(px,py,0)时可能取道t=15 */ else { t=0;break ; } /*存在阻隔,则不能连成五子 t=t>0?--t:0 */ } if(t==0x0f && mode) return 0 ; /* 若五子连成一线,返回零 */ if(ret<kt[t]) { ret=kt[t]; if(ret>rtemp) { int t=ret ; ret=rtemp ; rtemp=t ; } /* rtemp记录八向中最大的权 */ } } }/* 对mode= 1此返回植无意义 */ return(rtemp); /*当前局势, 返回0就成一下 return(ret+rtemp),加ret为增加随机性?? */}void initqp(void) /*初始化棋盘 */{ register int i, j; for(i=0;i<MAX;i++) for(j=0;j<MAX;j++) qp[i][j]=0; iswin=0; randomize(); /* 初始化随机生成器 */}int five(int px,int py) /* 主函数,检测玩家所走位置及附近的权值,返回计算机所走位置 */{ struct LIST **list; int tmp; if(qp[py][px]!=0) return -1; /*该位置已存在棋子, px,py代表玩家棋子位置? */ qp[py][px]=PLAYER; /*对玩家所走棋子进行扫描 */ ResumeGraphics(mouse.oldx, mouse.oldy, mouse_buf); qizi(px,py,RED); kuang(px,py,BLACK); /*重新画一次,使框图象完整*/ GetBuf(mouse.x, mouse.y, mouse.x + 10, mouse.y + 16, mouse_buf); 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; py=tmp/MAX; if(qp[py][px]!=0) /* 该位置不为空则继续循环 */ { if(GetMax(PList)>GetMax(CList)) list=&PList; /* 重新确定攻击性 */ else list=&CList; continue; } break; } if(!tmp){ /*在链表中未找到数据,tmp=0 则生成随机数据 */ do { px=random(MAX); py=random(MAX); } while(qp[py][px]!=0); tmp=0; } qp[py][px]=COMPUTER; /*计算机走子 */ qizi(px,py,YELLOW); if(!scan(px,py,1)) { DestroyList(PList); DestroyList(CList); iswin=COMPUTER; return 0; } /*计算机胜 */ return ((py*MAX)+px); /*返回走子位置 */}void kongpan(){ int i,j ; setbkcolor(BLACK); bar3d(PAN_X-30,PAN_Y-30,PAN_X+380,PAN_Y+380,7,5); setpalette(WHITE,GREEN); setcolor(YELLOW); for(i=0;i<MAX;i++) { line(PAN_X+25*i,PAN_Y,PAN_X+25*i,PAN_Y+(MAX-1)*25); line(PAN_X,PAN_Y+25*i,PAN_X+(MAX-1)*25,PAN_Y+25*i); } for(i=0;i<4;i++) { circle(PAN_X+175,PAN_Y+175,i); circle(PAN_X+75,PAN_Y+75,i); circle(PAN_X+275,PAN_Y+275,i); circle(PAN_X+75,PAN_Y+275,i); circle(PAN_X+275,PAN_Y+75,i); }} void qizi(int px,int py,int color){ unsigned char p; setcolor(color); for(p=0;p<12;p++) circle(PAN_X+px*25,PAN_Y+py*25,p);}void kuang(int px,int py,int color){ setcolor(color); rectangle((PAN_X+px*25)-12,(PAN_Y+py*25)-12,(PAN_X+px*25)+12,(PAN_Y+py*25)+12);} void ResumeGraphics(int x,int y,void *p){ putimage(x,y,p,COPY_PUT);}bool GetBuf(int x,int y,int xx,int yy,void *p) /*给图形指针赋值*/{ if(!p) return 0; getimage(x,y,xx,yy,p); return 1;}void Limit(int *x,int *y){ if((*x)>PAN_X-25&(*y)>PAN_Y-25&(*x)<PAN_X+(MAX-1)*25&(*y)<PAN_Y+(MAX-1)*25) return ; /* 在范围之内*/ if((*x)<PAN_X-25) (*x)=PAN_X-25 ; if((*y)<PAN_Y-25) (*y)=PAN_Y-25 ; if((*x)>PAN_X+(MAX-1)*25) (*x)=PAN_X+(MAX-1)*25 ; if((*y)>PAN_Y+(MAX-1)*25) (*y)=PAN_Y+(MAX-1)*25 ;}bool MouseControl(){ static int FIRST = 0; if(!FIRST) { Get_xy(&mouse); mouse.oldx = mouse.x; mouse.oldy = mouse.y; GetBuf(mouse.oldx,mouse.oldy,mouse.oldx+10,mouse.oldy+16,mouse_buf); Shape[0].Draw(mouse.x, mouse.y); FIRST = 1; } mouse.but = Which_pressed(); /* 无此句鼠标无反应 */ if( !mouse.but) /* 没有点鼠标时 */ { Get_xy(&mouse); Limit(&mouse.x,&mouse.y);/* 使在框中运动 */ if(mouse.x != mouse.oldx | mouse.y != mouse.oldy) { ResumeGraphics(mouse.oldx, mouse.oldy, mouse_buf); mouse.oldx = mouse.x; mouse.oldy = mouse.y; GetBuf(mouse.x, mouse.y, mouse.x + 10, mouse.y + 16, mouse_buf); Shape[0].Draw(mouse.x, mouse.y); return 1; } else return 0; } else { if(FIRST==1) { kuang(MAX/2,MAX/2,WHITE); FIRST = 2; } SetMouseXY(mouse.oldx,mouse.oldy); kuang(black_x,black_y,WHITE); black_x=(mouse.oldx-PAN_X+12)/25; black_y= (mouse.oldy-PAN_Y+12)/25; kuang(black_x,black_y,BLACK); return 1; }} void xiangying(){ kuang(MAX/2,MAX/2,BLACK); while(bioskey(1)==0) { MouseControl(); delay(20); if(pow(mouse.oldx-PAN_X-black_x*25,2)+pow(mouse.oldy-PAN_Y-black_y*25,2) <146 ) if(!five(black_x,black_y)) { qizi(black_x,black_y,RED); GetBuf(mouse.oldx, mouse.oldy, mouse.oldx + 10, mouse.oldy + 16, mouse_buf); return; } }}void InitGraphicsBuf(int x,int y,int xx,int yy,void **p){ *p=malloc(imagesize(x,y,xx,yy));}bool init(){ int driver = VGA, drivermode = VGAHI; initgraph(&driver, &drivermode, ""); if(graphresult() != 0) { printf("can't initgraph"); return FALSE; } InitGraphicsBuf(0,0,10,16,&mouse_buf); cleardevice(); return TRUE;}main(){ init(); settextstyle(DEFAULT_FONT,HORIZ_DIR,2); initqp(); kongpan(); xiangying(); printf("came over \nwinner:%d(COMPUTER:1,PLAYER:2)",iswin); getch(); closegraph();}

评论