电脑只走杀棋,如果没有杀棋,就走优先级最高的空子。
玩家搜索白子、黑子的所有杀招,根据优先级,可以通过自己走杀招的方式迫使电脑防守,放弃杀招;也可以占电脑杀招的空子,来破解对方杀招。
参考:http://blog.csdn.net/lihongxun945/article/details/50730231
这种解法:在没有杀招的时候,取优先级最高的子了事。有杀招的情况下,针对杀招向后推算,直到防守住、防不住或者推完depth步。这样搜索的分支要少的多。
bool cmp(Node a,Node b)
{
return a.s>b.s;
}
void generatepoint_2(int turn,int scoree,vector<Node> &v)
{
for(int i=0;i<16;++i)
for(int j=0;j<16;++j)
if(pos[i][j]==0&&hasne(i,j))
if(turn==0)//轮到玩家落子,玩家需要找到黑子最有利的空子+白子最有危险的空子,然后攻守随玩家
{
int comscore=evaluate_point(i,j,2);
int humscore=evaluate_point(i,j,1);
if(comscore+humscore>scoree)
{
Node p(i,j,comscore+humscore);
v.push_back(p);
}
}
else//轮到电脑落子,电脑只管找杀招
{
int s=evaluate_point(i,j,turn);
if(s>scoree)
{
Node p(i,j,s);
v.push_back(p);
}
}
sort(v.begin(),v.end(),cmp);//空子按优先级排序
}
vector<Node> min_kill(int turn,int depth,int x,int y,bool &tmp)
{
vector<Node> v;
Chess cc;
cc.chess_isover(x,y,2); //上一步是机器落子,落子的地方才有可能产生输赢
if(isover==2) //电脑赢了
{
isover=0;
tmp=true;
return v;
}
if(depth<0) //depth步内,玩家守的住了
{
tmp=false;
return v;
}
vector<Node> p;
generatepoint_2(0,1000,p);//找出所有大于活三的空子。玩家防守的话,可以是占电脑连成活四的空子,也可以是自己出击先成死四什么的。所以传的是0
int len=p.size();
if(len==0) //如果没有这样的空子,表示玩家到这一步就守住了
{
tmp=false;
return v;
}
vector< vector<Node> > cands;
for(int i=0;i<len;++i) //如果有这样的空子
{
bool tmp=false;
pos[p[i].x][p[i].y]=(turn==1)?2:1;
v.clear();
v=max_kill(turn,depth-1,p[i].x,p[i].y,tmp);
pos[p[i].x][p[i].y]=0;
if(tmp)//这个空子占了,后推几步还是得输
{
vector<Node> kk;
kk.push_back(p[i]);
v.insert(v.begin(),kk.begin(),kk.end());
cands.push_back(v);
continue;//继续找可以防守住的空子
}
else
{
tmp=false;
return v;//这个空子可以防守住,那就直接返回
}
}
int i=rand()%cands.size();
return cands[i];//所有空子挨个占,depth内没一个能防住的,随机抽一个
}
vector<Node> max_kill(int turn,int depth,int x,int y,bool &tmp)
{
vector<Node> v;
Chess cc;
cc.chess_isover(x,y,1);//上一步是玩家落子,落子的地方才有可能产生输赢
if(isover==1)//玩家不仅守住了,还赢了
{
isover=0;
tmp=false;
return v;
}
if(depth<0)//玩家守住了
{
tmp=false;
return v;
}
vector<Node> p;
generatepoint_2(turn,2000,p);//产生所有杀招空子队列
if(p.size()==0)//没有这样的空子,玩家守住了
{
tmp=false;
return v;
}
int len=p.size();
for(int i=0;i<len;++i)
{
bool tmp=false;
pos[p[i].x][p[i].y]=turn;
v.clear();
v=min_kill(turn,depth-1,p[i].x,p[i].y,tmp);
pos[p[i].x][p[i].y]=0;
if(tmp)
{
vector<Node> kk;
kk.push_back(p[i]);
v.insert(v.begin(),kk.begin(),kk.end());
return v;
}
}
tmp=false;
return v;
}
void Chess::chess_ai_killcount(int &x,int &y,int depth)
{
vector< pair<int,int> > v;
generatepoint(v);
int len=v.size();
vector< pair<int,int> > v2;
for(int i=0;i<len;++i)
{
pos[v[i].first][v[i].second]=2;
bool tmp=false;
min_kill(2,depth,v[i].first,v[i].second,tmp);
if(tmp)
v2.push_back(v[i]);
pos[v[i].first][v[i].second]=0;
}
len=v2.size();
if(len==0)//若无杀招,或者杀招都不能在depth内奏效,则取优先级最高的空子
{
x=v[0].first;
y=v[0].second;
return;
}
int i=(int)(rand()%len);
x=v2[i].first;
y=v2[i].second;
}