使用方法:
输入二维坐标0~14落子,输入-1 -1可以悔棋
注:输入7 7 即会开始在坐标7 7落子
#include
using namespace std;
#define bas 15
#define Dep_limit 3
#define inf 0x3f3f3f
int score[2][6]={{0,5,25,4000,inf,inf},{0,0,2,50,4000,inf}};///0活,1死
int mo[8][2]={{0,1},{0,-1},{1,-1},{1,0},{1,1},{-1,-1},{-1,0},{-1,1}};
int dir[4][2]={{1,0},{1,1},{0,1},{1,-1}};
struct opmem///操作记录
{
int x,y;
int kind;//黑1,白-1,空0
};
stack<opmem>s;
bool vis[bas][bas];
struct Mat///描述局面
{
short a[bas][bas];
void out()
{
printf(" ");
for(int i=0;i<bas;i++)printf("%2d",i);
printf("\n");
for(int i=0;i<bas;i++)
{
printf("%2d ",i);
for(int j=0;j<bas;j++)
{
if(a[i][j]==0)printf(". ");
else if(a[i][j]==1)printf("* ");
else printf("O ");
}
printf("\n");
}
}
void add(int x,int y,int col,int add)
{
if(add==-1)a[x][y]=0;
else a[x][y]=col;
}
bool in(int x,int y)
{
return x>=0&&y>=0&&x<bas&&y<bas;
}
bool win5(int x,int y)///返回该棋子是否可以组成五子
{
for(int i=0;i<4;i++)
{
int l=0,r=-1;
int mx=dir[i][0],my=dir[i][1];
int lx=x,ly=y,rx=x,ry=y,col=a[x][y];
while(in(lx,ly)&&a[lx][ly]==col)
{
l++;
lx-=mx;ly-=my;
}
while(in(rx,ry)&&a[rx][ry]==col)
{
r++;
rx+=mx;ry+=my;
}
if(l+r>=5)return 1;
}
return 0;
}
int val(int aim)///接下来aim下,计算局面好坏
{
int ret=0;
int num[6][2]={0};
for(int xcx=0;xcx<4;xcx++)
{
memset(vis,0,sizeof(vis));
int col=0;
int mx=dir[xcx][0],my=dir[xcx][1];
for(int i=0;i<bas;i++) for(int j=0;j<bas;j++)
{
if(vis[i][j]||a[i][j]==0)continue;
col=a[i][j];
int p=0,limit=0,x=i,y=j;
if(!in(x-mx,y-my)||a[x-mx][y-my]!=0)limit++;
while( in(x,y) && a[x][y]==col )
{
vis[x][y]=1;
p++;
x+=mx;
y+=my;
}
if(!in(x,y)||a[x][y]!=0)limit++;
if(p>=5)
if(col==aim)return inf;
else return -inf;
if(limit==2)continue;
if(p>=4&&col==aim)return inf;
num[p][limit]+=col;
}
}
for(int j=0;j<2;j++) for(int i=2;i<6;i++)
{
ret+=num[i][j]*score[j][i];
}
return aim*ret;
}
bool colse(int x,int y)
{
for(int i=0;i<8;i++)
{
int tx=x+mo[i][0],ty=y+mo[i][1];
if(in(tx,ty)&&a[tx][ty]!=0)return 1;
}
return 0;
}
}now;
void outlin()
{
for(int i=0;i<30;i++)printf("-");printf("\n");
}
int dfs(int x,int y,int frd,int col,int deep)//下(x,y)点成col色,能得到的最大评分,兄弟节点最大值为frd。
{
if(deep==Dep_limit)
{
return -now.val(-col);
}
int ret=-inf;
for(int i=0;i<bas;i++) for(int j=0;j<bas;j++)
{
if( now.a[i][j]!=0 || !now.colse(i,j) )continue;
now.add(i,j,-col,1);
if(now.win5(i,j))
{
now.add(i,j,-col,-1);
return -inf;
}
ret = max( dfs(i,j,-inf,-col,deep+1), ret);
now.add(i,j,-col,-1);
if(ret>=inf)break;
if(ret<frd){return inf;}///abcd剪枝
frd=ret;
}
return -ret;
}
void work(int &x,int &y,int col)//传入下棋位置,颜色(黑1,白-1),传出决策位置
{
int best=-inf*2;
for(int i=0;i<bas;i++) for(int j=0;j<bas;j++)
{
if(now.a[i][j]==0){x=i;y=j;break;}
}
for(int i=0;i<bas;i++)
{
for(int j=0;j<bas;j++)
{
if( now.a[i][j]!=0 || !now.colse(i,j) )continue;
now.add(i,j,-col,1);
if(now.win5(i,j))
{
now.add(i,j,-col,-1);
x=i,y=j;
return;
}
if(now.val(col)!=inf)
{
int temp= dfs(i,j,-inf,-col,1);
if(temp>best)
{
best=temp;
x=i,y=j;
}
}
now.add(i,j,-col,-1);
}
}
}
void outway()//输出棋局
{
int x[200],y[200],cnt=0;
while(!s.empty())
{
x[cnt]=s.top().x;
y[cnt]=s.top().y;
cnt++;
s.pop();
if(!s.empty())s.pop();
}
for(int i=cnt-1;i>=0;i--)
{
printf("%d %d\n",x[i],y[i]);
}
}
int main()
{
//test();
int x,y;
memset(now.a,0,sizeof(now.a));
while(scanf("%d%d",&x,&y)!=EOF)
{
opmem temp;
if(x==-2&&y==-2)break;
if(x==-1&&y==-1)
{
printf("back:\n");
//scanf("%d%d",&x,&y);
now.add(s.top().x,s.top().y,s.top().kind,-1);
s.pop();
now.add(s.top().x,s.top().y,s.top().kind,-1);
s.pop();
now.out();
continue;
}
if(!now.in(x,y)||now.a[x][y]!=0)
{
printf("error %d %d\n",x,y);continue;
}
now.add(x,y,1,1);
now.out();outlin();
temp.kind=1; temp.x=x; temp.y=y;
s.push(temp);
if(now.win5(x,y)){printf("you win\n");break;}
work(x,y,1);
now.add(x,y,-1,1);
now.out();outlin();
temp.kind=-1; temp.x=x; temp.y=y;
s.push(temp);
printf("%d %d\n",x,y);
if(now.win5(x,y)){printf("ai win\n");}
}
outway();
return 0;
}