最近,佳颖同学给我玩了一个小游戏,一个猜数字的小游戏。就是,先随机产生4个0-9之间不同的数字,然后玩家去猜,对于玩家每次猜的数字,系统会提示玩家XA和YB,其中,XA代表有X个数字和位置都猜对了,YB代表有Y个数字猜对了但位置不对。玩家根据系统的提示思考下一步要猜的数字,然后系统会接着给出提示。直到玩家猜出数字为止!
然后,我就写了一个这个游戏的页面。挂在自己的阿里云服务器上,所以没有域名哈。http://120.78.49.136/Uguess/index.php/Index/index
故事到这里就结束了吗,不是的。我感觉挺难猜的,还要去推理,所以索性就去写了一个C++代码,来提示我下一步应该要猜的数字。
解决这个问题的思路是:
由于答案可能是A(10,4)种排列中的一个,所以,先预处理出这5040个排列,然后假设第一次猜的是"1234",这样系统就会得到一个tip,然后将这个猜的数字和对应的tip保存起来。接着,就可以枚举每一个排列,并与猜过的数字以及相应的tip做匹配,找出与所有猜过的数字以及相应的tip能匹配的第一个排列作为提示。提示下一次用户应该猜什么。然后又获取这个数字相应的提示存储起来。不断进行这个过程,就可以猜出答案,是不是很暴力啊,哈哈哈哈。一般来说,6,7次就可以猜出来了。
下面是解决问题的C++代码。
#include<bits/stdc++.h>
using namespace std;
struct node
{
string num,ans;
}a[15];
int aPos,win=0;
string allNum[50000];
int vis[15],allPos=0;
int judge(string a,string b,string ans)
{
int cnt1=0,cnt2=0;
for(int i=0;i<a.size();i++)
{
if(a[i]==b[i]) cnt1++;
}
for(int i=0;i<a.size();i++)
{
for(int j=0;j<b.size();j++)
{
if(a[i]==b[j]) cnt2++;
}
}
cnt2-=cnt1;
if(ans[0]-'0'==cnt1&&ans[2]-'0'==cnt2) return 1;
return 0;
}
int check(string b)
{
for(int i=0;i<aPos;i++)
{
if(judge(a[i].num,b,a[i].ans)==0) return 0;
}
return 1;
}
string getNext()
{
for(int i=0;i<allPos;i++)
{
string s=allNum[i];
if(check(s.substr(0,4))) return s.substr(0,4);
}
}
void dfs(int d,string s)
{
if(d==4)
{
allNum[allPos++]=s;
return ;
}
for(int i=0;i<10;i++)
{
if(!vis[i])
{
vis[i]=1;
dfs(d+1,s+char(i+'0'));
vis[i]=0;
}
}
}
void init()
{
dfs(0,"");
//for(int i=0;i<allPos;i++) cout<<allNum[i]<<endl;
//cout<<allPos<<endl;
}
int main()
{
init();
string guess="1234",num,ans;
while(!win)
{
cout<<"you can guess :"<<guess<<endl;
//cin>>num;
cout<<"next input a tip :";
cin>>ans;
a[aPos].num=guess;
a[aPos].ans=ans;
aPos++;
guess=getNext();
}
return 0;
}
下面是一组实测