C++ AI解珠玑妙算(mastermind)算法
Posted 传说C罗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ AI解珠玑妙算(mastermind)算法相关的知识,希望对你有一定的参考价值。
珠玑妙算这个游戏大家都不陌生,规则就不多说了,直接进主题:
需要破译的密码由四位组成,每位可以是0~9中的任意数字。eg. (1544,4301,0918,...)
此算法可在20步内猜测出结果。
算法大致步骤分为两步:
第一步:求出这串密码是由哪四个数字组成。从0000迭代到9999就行,第一步最多需要十次猜测。
第二步:将由第一步得出的四个数字全排列,把全排列结果存在一个集合里。然后依次返回集合里的猜测并通过猜测结果做简单的划分。对集合进行进一步的消除从而减少猜测次数。
划分规则如下:
当结果猜中数为0时:因为0位猜中,所以四个位的数字都是错的。从而我们可以直接消除集合里所有与此猜测有相同位的元素。举例:假设猜测为“1234”并且猜中数为0,我们就可以把集合里所有第一位为1,第二位为2,第三位为3,第四位为4 的元素全部消除掉。
当结果猜中数为2时:这种情况稍微复杂点,具体操作如下:把该猜测和之前猜中数为2的猜测做比对,若二者中有且仅有一位数字同位,那么该数字在密码中就属于该位。举例:假设“1234”的猜中数为2,“4132”猜中数也为2,通过比对这两串数字得知它们的第三位是相同的,都为3,所以可以得知真正密码的第三位就是3。然后回到我们的集合把第三位不为3的元素全部消除。
当结果猜中数为1,3,4时,不予任何操作。
整体算法如上所述。我的算法是以一个函数的形式运行的:string mastermindAI(int rr, int rw)
这个函数每次被呼叫都会返回一个猜测(string),然后主程序将会以参数形式将猜测结果传给函数(rr为真猜中数量,rw为伪猜中数量)。第一次被呼叫时rr和rw为0。
珠玑妙算的主程序会在下一篇博客中。
学习编程一年一来的第一篇博客,不足之处请赐教。
程序:
string mastermindAI(int rr,int rw){
static const int SIZE=10000;//How many guesses to save
static string gHistory[SIZE];//guess history
static int rHistory[SIZE];//result history
static int hisCount=0;// history counter
static string sGuess="0000"; //Size the guest string
static int guessNum=0;
static char bit[4];
static int bitSize=4;
static int bitNum=0;
static vector<string> guessBase;
static bool once=true;
static bool beforeSecondStep=false;
//第一步:迭代返回0-9,求出四位数字
if(bitNum<4)
{
if(rr>0)
{
for(int i=0;i<rr;i++)
{
bit[bitNum]=sGuess[1];
bitNum++;
}
}
if(bitNum<4)
{
for(int i=0;i<4;i++)
{
sGuess[i]=guessNum+'0';
}
}
}
//当四位数字都找到时,进入第二步:
if(bitNum>=4)
{
vector<string>::iterator it;
if(once) //进入第二步后,首先把四位数字全排列,所有排列组合将被存入名为guessbase的容器中
{ //由此到156行为全排列算法
for(int i=0;i<4;i++)
{
for(int j=i+1;j<4;j++)
{
if(bit[i]==bit[j])
{
bitSize--;
}
}
}
for(int i=0;i<4;i++)
{
for(int j=0;j<3;j++)
{
if(bit[j]>bit[j+1])
{
char temp;
temp=bit[j];
bit[j]=bit[j+1];
bit[j+1]=temp;
}
}
}
string stemp=bit;
guessBase.push_back(stemp);
for(int i=3;i>0;i--) //permutation the bit[]
{
if(bit[i-1]<bit[i])
{
char minIdx=i;
for(int j=i;j<4;j++)
{
if(bit[j]>bit[i-1])
{
if(bit[j]<=bit[minIdx])
{
minIdx=j;
}
}
}
char temp;
temp=bit[minIdx];
bit[minIdx]=bit[i-1];
bit[i-1]=temp;
for(int j=i,k=3;j<k;j++,k--)
{
temp=bit[j];
bit[j]=bit[k];
bit[k]=temp;
}
stemp=bit;
guessBase.push_back(stemp);
i=4;
}
}
once=false;
}
//全排列结束,返回guessbase容器里的第一个元素,然后擦除
if(beforeSecondStep==false)
{
sGuess=guessBase[0];
it=guessBase.begin();
it=guessBase.erase(it);
beforeSecondStep=true;
}
else //下面进入到划分环节
{
gHistory[hisCount]=sGuess;
rHistory[hisCount]=rr;
hisCount++;
switch(rr) //当真猜中数为0和2时进行划分,其他猜中数不划分
{
case 0:
for(it=guessBase.begin();it!=guessBase.end();)
{
string temp=*it;
if(temp[0]==sGuess[0]||temp[1]==sGuess[1]||temp[2]==sGuess[2]||temp[3]==sGuess[3])
{
it=guessBase.erase(it);
}
else
{
it++;
}
}
break;
case 2:
if(bitSize==4||bitSize==3)
{
for(int i=0;i<hisCount;i++)
{
int rNum=0;
int idx=0;
if(rHistory[i]==2)
{
for(int j=0;j<4;j++)
{
if(gHistory[i][j]==sGuess[j])
{
rNum++;
idx=j;
}
}
if(rNum==1)
{
for(it=guessBase.begin();it!=guessBase.end();)
{
string temp=*it;
if(temp[idx]!=sGuess[idx])
{
it=guessBase.erase(it);
}
else
{
it++;
}
}
}
}
}
}
break;
default:
break;
}
sGuess=guessBase[0];
it=guessBase.begin();
it=guessBase.erase(it);
}
}
guessNum++;
//Return the result
return sGuess;
}
以上是关于C++ AI解珠玑妙算(mastermind)算法的主要内容,如果未能解决你的问题,请参考以下文章