赞
踩
使用方法:
输入二维坐标0~14落子,输入-1 -1可以悔棋
注:输入7 7 即会开始在坐标7 7落子
#include<bits/stdc++.h> 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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。