/***************************************************************************************\
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();
}
评论