标签:
引用自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