码迷,mamicode.com
首页 > 编程语言 > 详细

算法学习---一个博弈问题

时间:2015-06-03 23:20:53      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

引用自matrix67的博客。

 
 让我们来玩一个游戏。下面有五行石子,白色的石子都是我的,黑色的石子都是你的。我们轮流拿走一个自己的石子,并且规定如果一个石子被拿走了,它后面的所有石子都要被扔掉。谁先没有拿的了,谁就输了。

○●●○●●○●●○
●○○●○●●○●
○○○○
●●●○●●●


..比如说,如果你先走的话,你可以把第四行的第三个石子拿走,按规定第四行将会只剩下前面两个石子:

 

○●●○●●○●●○

●○○●○●●○●

○○○○

●●

 

现在轮到我走了。我可以拿走第二行倒数第二个石子,于是整个棋局变成了这样:

 

○●●○●●○●●○

●○○●○●●

○○○○

●●

 

现在,假如说你拿走了第二行中的第一个石子(于是第二行就没了),那么我就赢定了。我可以拿走第一行中的第一个石子,从而让整个棋局只剩下后面三行:

 

○○○○

●●


 

要求给出一种最合理的走法。


如果是残局
○○○○
●● 

把每个白色石子记作 +1 ,把每个黑色石子记作 -1 。于是 ○○○○ + ●● + ● = 4 – 2 – 1 = 1 ,结果是一个正数(记这个结果为特征值),这就表明该局面下我将必胜,即使此时轮到我先走。

你会发现上面的说法很有道理 如果棋局是这样

○○
●●●●
 
○○ + ●●●● = 2 – 4 = -2 ,是一个负数,这就意味着不管谁先走,你都能必胜,

如果是

○○
●●

如果我先走你后走,你就赢定了;如果你先走我后走,我就赢定了。因为 和为0。


所以正确的走法:只需要走特征值最大的就可以了。

博客原文http://www.matrix67.com/blog/archives/6333

算法:

#include <stdio.h>
#include <stdlib.h>

template <class type>
void inline Swap(type &a,type &b)
{
	type tmp=a;
	a=b;
	b=tmp;
}



class Chess
{
public:
	Chess()
	{
		int i,j;
		int c[5][10]=
		{{0,1,1,0,1,1,0,1,1,0},
		{1,0,0,1,0,1,1,0,1,-1},
		{0,0,0,0,-1,-1,-1,-1,-1,-1},
		{1,1,1,0,1,1,1,-1,-1,-1},
		{1,-1,-1,-1,-1,-1,-1,-1,-1,-1} 	};  

		//1是黑棋 0是白棋

		for(i=0;i<5;i++)
			for(j=0;j<10;j++)
				chess[i][j]=c[i][j];
		rows=5;
		
	}

	Chess(Chess &other)
	{
		int i,j;
		for(i=0;i<other.rows;i++)
		{for(j=0;j<10;j++)	
			chess[i][j]=other.chess[i][j];
		}
		rows=other.rows;

	}


	int isWin(int turn) const  //1该黑棋走,0该白棋走
	{
		if (rows==0) return 1;
				
		int i,j;
		for(i=0;i<rows;i++)
		{
			for(j=0;j<10;j++)
			{
				if(chess[i][j]==!turn) return 0;
			}
		}
		return 1;

		

	}

	void takeout(int k,int l)
	{
	
		int i,j,flag=0;
	

	
		for(j=l;j<10;j++) chess[k][j]=-1;

		for(j=0;j<10;j++) 
		{
			flag=chess[k][j]!=-1;
			if (flag==1) break;
				
		}
		if(flag==0)
		{
				
			for(i=k;i<rows-1;i++)
			{
				for(j=0;j<10;j++)
				{
					Swap(chess[i][j],chess[i+1][j]);
				}
			}

			rows--;
		}

		
	}
	
	int CheckInput(int i,int j)
	{

		if(i<0||i>=rows||j<0||j>=10) 
		{
			printf("该棋子不存在!\n");
			return 0;
		}
		else
		{
			if(chess[i][j]==-1) {
				printf("该棋子不存在!2\n");
				return 0;
			}
			if(chess[i][j]==0) {
				printf("您不能选择白棋!\n");
				return 0;
			}

	
		}
	return 1;

	}


	double EigenValue() const
	{
		double value = 0;
		int i,j;
		for(i=0;i<rows;i++)
		{
			if (chess[i][0] == 0 && chess[i][1] == 0 && chess[i][2] == -1)
			{
				value+= 0.5;
			}
			else
			{
			

				for(j=0;j<10;j++)
				{
				
					switch(chess[i][j])
					{
						case 1:value--;break;
						case 0:value++;break;
		

					}
				}
			}

		}
		return value;

	}

	void print() const 
	{
		int i,j;
		for(i=0;i<rows;i++)
		{
			for(j=0;j<10;j++)
			{
				switch(chess[i][j])
				{
				case 1:printf("●");break;
				case 0:printf("○");break;
		

				}
			}
			printf("\n");
		}


	}
int chess[5][10];
int rows;

};



//AI下棋的程序
void AIPredict(Chess c,int &AIi,int &AIj)
{


	struct v{
		int i,j;
		double value;
		
	} value[50];
	int count=0,i,j;
	
	
	
	for(i=0;i<c.rows;i++)
		{
			for(j=0;j<10;j++)
			{
				if(c.chess[i][j]==0)
				{
					Chess predict=c;
					predict.takeout(i,j);
					value[count].i=i;
					value[count].j=j;
					value[count].value=predict.EigenValue();
					count++;
				}
			}
		}

	v maxvalue=value[0];
	for(i=1;i<count;i++)
	{
		if(value[i].value>maxvalue.value)
		{
			maxvalue=value[i];
		}

	}

	AIi=maxvalue.i;
	AIj=maxvalue.j;



}


int main()
{
	system("color F0");
	printf("游戏规则:\n下面有五行石子,白色空心○的石子都是我的,黑色实心●的石子都是你的。\n我们轮流拿走一个自己的石子,并且规定如果一个石子被拿走了,\n它后面的所有石子都要被扔掉。谁先没有拿的了,谁就输了。\n\n");
	Chess c;
	c.print();
	printf("\n\n");
	
	int i,j,turn;

	printf("你想先手还是后手?1为先手,0为后手:");
	scanf("%d", &turn);


	printf("\n");
	while(!c.isWin(turn))
	{
		
		if (turn==1) {
			
			do{
			
				printf("请输入i j表示你要下的位置:(从0开始)");
				scanf("%d %d",&i,&j);
				
			
			}while(!c.CheckInput(i,j));

				c.takeout(i,j);
				printf("\n\n");
				c.print();
		
		}
		else
		{
			AIPredict(c,i,j);
			printf("电脑下的位置是:<%d,%d>\n",i,j);
			c.takeout(i,j);
			printf("\n\n");
			c.print();

		}

		turn = !turn;
	}

	if(turn)
	{
		printf("你赢了!\n");
	}
	else
	{
		printf("你输了!\n");
	}





	system("pause");
	return 0;

}

  

 

算法学习---一个博弈问题

标签:

原文地址:http://www.cnblogs.com/xcr1234/p/4550385.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!