五子棋(人机)-只算杀棋

电脑只走杀棋,如果没有杀棋,就走优先级最高的空子。

玩家搜索白子、黑子的所有杀招,根据优先级,可以通过自己走杀招的方式迫使电脑防守,放弃杀招;也可以占电脑杀招的空子,来破解对方杀招。

参考: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; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值