Alpha-beta 算法

Alpha-beta 算法是棋类游戏中最常用的,也是最基础的剪枝方法,

要说Alpha-beta 算法 就得先说下max_min博弈树 算法,就是模拟电脑下子,要下在对电脑最优的地方,模拟人下子就要下在对人最优的地方,对电脑来说最差的地方

Alpha-beta 算法_第1张图片

此图中甲是电脑,乙是玩家,那么在甲层的时候,总是选其中值最大的节点,乙层的时候,总是选其中最小的节点。

而每一个节点的分数,都是由子节点决定的,因此我们对博弈树只能进行深度优先搜索而无法进行广度优先搜索。深度优先搜索用递归非常容易实现,然后主要工作其实是完成一个评估函数,这个函数需要对当前局势给出一个比较准确的评分。



  1. 在MAX层,假设当前层已经搜索到一个最大值 X, 如果发现下一个节点的下一层(也就是MIN层)会产生一个比X还小的值,那么就直接剪掉此节点。

解释一下,也就是在MAX层的时候会把当前层已经搜索到的最大值X存起来,如果下一个节点的下一层会产生一个比X还小的值Y,那么之前说过玩家总是会选择最小值的。也就是说这个节点玩家的分数不会超过Y,那么这个节点显然没有必要进行计算了。

通俗点来讲就是,AI发现这一步是对玩家更有利的,那么当然不会走这一步。

  1. 在MIN层,假设当前层已经搜索到一个最小值 Y, 如果发现下一个节点的下一层(也就是MIN层)会产生一个比Y还大的值,那么就直接剪掉此节点。


int alphaBeta2(int chess, int depth, int alpha, int beta,int i,int j) //alphaBeta剪枝;极大极小博弈树,人工智能第一步 模拟五步下子
{
    int best;
   if( getQuan(i,j,chess%2+1)>=Q5)
    {
	  return getComputerQuan()-getPeopleQuan();
    }
   else if(depth==0)
    {
    		//System.out.println(getComputerQuan()-getPeopleQuan());
    	return getComputerQuan()-getPeopleQuan();	
    }
    else {
    	if(chess==2)
    	{
    		int now;
    		for( i = 0;i<= 14;i++)
	  for(j = 0;j<=14;j++)
	  {
		  if(num[i][j]==0)
		  {
			  if(alpha>=beta)return alpha;
			  else if(generator( i,j)==true){	
				  num[i][j]=2;
				  now=alphaBeta2(1,depth-1,alpha,beta,i,j);
				  num[i][j]=0;			
				  if(now>alpha)alpha=now;
			  }
		  }
	  }
    		
    	best=alpha;	
    	}
    	else {
    		int now;
    		for( i = 0;i<= 14;i++)
	  for(j = 0;j<=14;j++)
	  {
		  if(num[i][j]==0)
		  {
			  if(alpha>=beta)return beta;
			  else if(generator(i,j)==true){
				  num[i][j]=1;
				  now=alphaBeta2(2,depth-1,alpha,beta,i,j);
				  num[i][j]=0;
				  if(now

可以看出搜索的复杂度是m^n 所以要想多搜几步减少m的值是必要的,m的值怎么减少呢?启发式搜索就是找最优的点有了打分之后,我们就可以按照分数高低进行排序了。具体实现的时候,是根据按照成五,活四,双三,活三,其他 的顺序来排序的这个难度也比较高,我就按着这个顺序排序,取最优的五个进行下一步循环,大大减少了基数m可以搜索到第六步,多搜索了2步而且时间是几乎相同的,关键代码如下:

if(chess==2)//电脑下子

     {

     int now;//一个记录当前值的数,

     for( i = 0;i<= 14;i++)

  for(j = 0;j<=14;j++)

  {

  if(num[i][j]==0)

  {

  if(alpha>=beta)return alpha;//alpha剪枝

  else if(generator(i,j)==true){//相邻剪枝

  num[i][j]=2;

 // now=getQuan(i,j,chess);

  now=getQuan(i,j,1)+getQuan(i,j,2);

  num[i][j]=0;

  bestson[cnt]=new struct();//入队

  bestson[cnt].i=i;

  bestson[cnt].j=j;

  bestson[cnt++].value=now;

  }

  }

  }

     struct t=new struct();

     for(i=0;i<cnt;i++)//冒泡排序

     for(j=i+1;j<cnt;j++)

     if(bestson[i].value<bestson[j].value)

     {

     t=bestson[i];

     bestson[i]=bestson[j];

     bestson[j]=t;

     }

     cnt=cnt<5?cnt:5;

     for(i=0;i<cnt;i++)//启发式搜索,取前五

     {

     num[bestson[i].i][bestson[i].j]=2;

  now=alphaBeta(1,depth-1,alpha,beta,bestson[i].i,bestson[i].j);

  if(now>alpha)alpha=now;

  num[bestson[i].i][bestson[i].j]=0;

     }

     best=alpha;

     }


现在的棋力已经很厉害了。

开始我也一点没接触过五子棋的算法,经过一周课余的努力也能做的不错了,好开心。。



你可能感兴趣的:(Java,五子棋)