猜数字项目最简算法,比谁的程序猜测总次数最少

林心诚丶 2017-08-29 03:20:33
本人新的不能再新的小萌新一只,恳请各位大佬帮我解决下这个问题,感激涕零;
以下为原题:
猜数字,计算机随机生成1个3或4位的十进制整数,各个数位上的数字各不相同,用户给出猜测,计算机回答XAYB(X个位置和数字猜中,Y个数字猜中但位置错误),重复用户猜计算机回答的过程,直到猜中为止(3A0B,4A0B)。
现给出原码,要求计算机随机生成1个3或4位的十进制整数,各个数位上的数字各不相同,由计算机来猜测,比谁的程序猜测的总次数最少。
以下为原码 (需要完成的是函数int guess(int A,int B))
#include <stdio.h>
#include <stdlib.h>
#define M 4 //猜几个数字
//交换
void swap(int*a,int*b)
{
int t=*a;
*a=*b;
*b=t;
}
//将数组随机打乱
void random_shuffle(int* a,int n)
{
int i;
for(i=0;i<n;i++)
{
int x=rand()%n;
int y=rand()%n;
if(x!=y) swap(a+x,a+y);
}
}
//生成数位不重复的M位全部数据,存在数组a中,并打乱,备用
int gen(int* a)
{
int count=0,i,j;
int max=1;
for(i=0;i<M;++i,max*=10);
for(i=0;i<max;++i)
{
_Bool flag[10]={0};
int t=i;
for(j=0;j<M;++j)
if(flag[t%10]) break;
else flag[t%10]=1,t/=10;
if(j==M)
a[count++]=i;
}
random_shuffle(a,count);
return count;
}
void test(int answer,int player,int* A,int* B)
{
int i=0,j;
int answer_a[M]={0},player_a[M]={0};
*A=*B=0;

while(answer||player)
{
answer_a[i]=answer%10;
player_a[i++]=player%10;
answer/=10;
player/=10;
}
for(i=0;i<M;++i)
for(j=0;j<M;++j)
if(player_a[i]==answer_a[j])
if(i==j) ++*A;
else ++*B;

}
//参数AB是上一轮猜测的反馈,
//如果得到猜中的信息表示下一把的开始
int guess(int A,int B)
{
//你的工作在这个函数
int x;
scanf("%d",&x);
return x;
}
int main()
{
srand(2);
int i;
//初始生成数据
int len;
for(len=1,i=0;i<M;++i)
len*=10-i;
int a[len];
gen(a);
//开玩
int n=1;//玩n把
int count=0;//总猜测次数
while(n--)
{
//每把从猜中开始,例如玩4个数,4A0B为猜中,
//此时进入下一把,会有新的数供猜测
//printf("%d\n",a[n]);
int A=M,B=0;
int count_cur=0;
do
{
int player=guess(A,B);
++count_cur;
test(a[n],player,&A,&B);
printf("%d:%0*d,%dA%dB\n",count_cur,M,player,A,B);
}while(A!=M||B);
count+=count_cur;
}
return 0;
}
...全文
613 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
cain-won 2017-08-30
  • 打赏
  • 举报
回复
你这个难度有点大啊
林心诚丶 2017-08-30
  • 打赏
  • 举报
回复
引用 3 楼 kugeniha 的回复:
参考下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define M 4 //猜几个数字 
 //交换
 void swap(int*a,int*b)
 {
	int t=*a;
	 *a=*b;
	*b=t;
 }
 //将数组随机打乱 
 void random_shuffle(int* a,int n)
 {
	int i;
	 for(i=0;i<n;i++)
	{
		int x=rand()%n;
		int y=rand()%n;
		if(x!=y) swap(a+x,a+y);
	}
 } 
 //生成数位不重复的M位全部数据,存在数组a中,并打乱,备用 
 int  gen(int* a)
 {
	int count=0,i,j;
	int max=1;
	for(i=0;i<M;++i,max*=10); 
		for(i=0;i<max;++i)
		{
			int flag[10]={0};
			int t=i;
			for(j=0;j<M;++j)
				if(flag[t%10]) break;
				else flag[t%10]=1,t/=10;
	if(j==M)
		a[count++]=i; 
	}
	random_shuffle(a,count);
	return count;
}
 void test(int answer,int player,int* A,int* B)
 {
	int i=0,j; 
	int answer_a[M]={0},player_a[M]={0};
	*A=*B=0;
	while(answer||player)
	{
		answer_a[i]=answer%10;
		player_a[i++]=player%10;
		answer/=10;
		player/=10;
	 }
	for(i=0;i<M;++i)
	for(j=0;j<M;++j)
		if(player_a[i]==answer_a[j])
			if(i==j) ++*A;
			else ++*B;
}
 //参数AB是上一轮猜测的反馈,
 //如果得到猜中的信息表示下一把的开始
 int guess(int *a,int n)
 {
 //你的工作在这个函数 
		int A=M,B=0,OA;
		int count_cur=0;
		int i,j,num,p;
		char arr[5],new_arr[5],ch;
		int flag[4]={0};
		printf("The answer is %d\n",a[n]);//先给出答案,用以验证
		for(i=0,j=0;i<10;i++,++count_cur)
		{
			if(4==M)
				num=i*1111;
			else 
				num=i*111;
			test(a[n],num,&A,&B);
			printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
			if(A==1) arr[j++]=i+48;
			if(M==j) break;
		}//经此for循环,得出要猜的数由哪些数字组成
		arr[M]=0;//尾0
		num=atoi(arr);
		//printf("%d",numA);
		test(a[n],num,&A,&B);
		count_cur++;
		printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
		OA=A;//标记上一次猜测的数的位置与数都正确的个数
		if(A==M&&B==0)
		{
			printf("答案是%s\n",arr);
			return count_cur;
		}//如果猜测与答案一样,显示答案,返回猜测步数
		p=0;
		for(i=0;i<M;i=p)
		{
			strncpy(new_arr,arr,M);
			new_arr[M]=0;
			if(0==flag[i])//定义数组flag初始为0,表示对应下标的位置不正确,正确了后置1
			{
				for(j=i+1;j<M;j++)
				{
					if(0==flag[j])
					{
						new_arr[j]=arr[i];
						num=atoi(new_arr);
						//printf("num=%d\n",num);
						count_cur++;
						test(a[n],num,&A,&B);
						printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
						if(A>OA) //arr[i]在此次j位上,交换
						{
							flag[j]=1;
							ch=arr[j];
							arr[j]=arr[i];
							arr[i]=ch;
							num=atoi(arr);
							count_cur++;
							test(a[n],num,&A,&B);//交换之后0A有可能在原基础上加1,也可能加二,所以直接调用test算出准确OA
							printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
							OA=A;
							p=i;
							break;
						}
						else if(A<OA) //说明此位置原本数对应正确的位置,不可改变,对应下标置1
						{	
							flag[j]=1;
							new_arr[j]=arr[j];
						}
					}
				}//找正确位置
				if(M==j) 
				{
					flag[i]=1;
					p=i+1;
				}//一轮for循环,没找到正确位置,说明本身所在的位置是正确的。
			}
			else p=i+1;
			//printf("p=%d\n",p);
		}
		printf("答案是%s\n",arr);
		return count_cur;
 }
 int main()
 {
    int i;
 //初始生成数据 
    int len;
	int *a;
	int  n=3,nn=n;//玩n把
    int count=0;//总猜测次数
    for(len=1,i=0;i<M;++i)
    len*=10-i;
    a=(int *)malloc(sizeof(int)*len);	
	srand((unsigned)time(NULL));
	//srand(2);
    gen(a);
 //开玩
    while(n--)
    {
		int count_cur=0;
     //每把从猜中开始,例如玩4个数,4A0B为猜中,
//此时进入下一把,会有新的数供猜测 
 //printf("%d\n",a[n]);
		count_cur=guess(a,n);
		printf("此轮共%d步完成\n",count_cur);
		count+=count_cur;
    }
	printf("游戏结束,共计%d轮游戏,总消耗%d步\n",nn,count);
	system("pause");
    return 0;
 } 


老哥 还能再优化一下吗,步数能减少一点就减少一点,注释再稍微详细一点,我是萌新看不懂现在就可以把分给你。
林心诚丶 2017-08-30
  • 打赏
  • 举报
回复
老哥这还能再优化一下吗,步数能减少一点就减少一点,注释再稍微详细一点,我是萌新看不懂现在就可以把分给你。
kugeniha 2017-08-30
  • 打赏
  • 举报
回复
参考下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define M 4 //猜几个数字 
 //交换
 void swap(int*a,int*b)
 {
	int t=*a;
	 *a=*b;
	*b=t;
 }
 //将数组随机打乱 
 void random_shuffle(int* a,int n)
 {
	int i;
	 for(i=0;i<n;i++)
	{
		int x=rand()%n;
		int y=rand()%n;
		if(x!=y) swap(a+x,a+y);
	}
 } 
 //生成数位不重复的M位全部数据,存在数组a中,并打乱,备用 
 int  gen(int* a)
 {
	int count=0,i,j;
	int max=1;
	for(i=0;i<M;++i,max*=10); 
		for(i=0;i<max;++i)
		{
			int flag[10]={0};
			int t=i;
			for(j=0;j<M;++j)
				if(flag[t%10]) break;
				else flag[t%10]=1,t/=10;
	if(j==M)
		a[count++]=i; 
	}
	random_shuffle(a,count);
	return count;
}
 void test(int answer,int player,int* A,int* B)
 {
	int i=0,j; 
	int answer_a[M]={0},player_a[M]={0};
	*A=*B=0;
	while(answer||player)
	{
		answer_a[i]=answer%10;
		player_a[i++]=player%10;
		answer/=10;
		player/=10;
	 }
	for(i=0;i<M;++i)
	for(j=0;j<M;++j)
		if(player_a[i]==answer_a[j])
			if(i==j) ++*A;
			else ++*B;
}
 //参数AB是上一轮猜测的反馈,
 //如果得到猜中的信息表示下一把的开始
 int guess(int *a,int n)
 {
 //你的工作在这个函数 
		int A=M,B=0,OA;
		int count_cur=0;
		int i,j,num,p;
		char arr[5],new_arr[5],ch;
		int flag[4]={0};
		printf("The answer is %d\n",a[n]);//先给出答案,用以验证
		for(i=0,j=0;i<10;i++,++count_cur)
		{
			if(4==M)
				num=i*1111;
			else 
				num=i*111;
			test(a[n],num,&A,&B);
			printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
			if(A==1) arr[j++]=i+48;
			if(M==j) break;
		}//经此for循环,得出要猜的数由哪些数字组成
		arr[M]=0;//尾0
		num=atoi(arr);
		//printf("%d",numA);
		test(a[n],num,&A,&B);
		count_cur++;
		printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
		OA=A;//标记上一次猜测的数的位置与数都正确的个数
		if(A==M&&B==0)
		{
			printf("答案是%s\n",arr);
			return count_cur;
		}//如果猜测与答案一样,显示答案,返回猜测步数
		p=0;
		for(i=0;i<M;i=p)
		{
			strncpy(new_arr,arr,M);
			new_arr[M]=0;
			if(0==flag[i])//定义数组flag初始为0,表示对应下标的位置不正确,正确了后置1
			{
				for(j=i+1;j<M;j++)
				{
					if(0==flag[j])
					{
						new_arr[j]=arr[i];
						num=atoi(new_arr);
						//printf("num=%d\n",num);
						count_cur++;
						test(a[n],num,&A,&B);
						printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
						if(A>OA) //arr[i]在此次j位上,交换
						{
							flag[j]=1;
							ch=arr[j];
							arr[j]=arr[i];
							arr[i]=ch;
							num=atoi(arr);
							count_cur++;
							test(a[n],num,&A,&B);//交换之后0A有可能在原基础上加1,也可能加二,所以直接调用test算出准确OA
							printf("%d:%0*d,%dA%dB\n",count_cur,M,num,A,B);
							OA=A;
							p=i;
							break;
						}
						else if(A<OA) //说明此位置原本数对应正确的位置,不可改变,对应下标置1
						{	
							flag[j]=1;
							new_arr[j]=arr[j];
						}
					}
				}//找正确位置
				if(M==j) 
				{
					flag[i]=1;
					p=i+1;
				}//一轮for循环,没找到正确位置,说明本身所在的位置是正确的。
			}
			else p=i+1;
			//printf("p=%d\n",p);
		}
		printf("答案是%s\n",arr);
		return count_cur;
 }
 int main()
 {
    int i;
 //初始生成数据 
    int len;
	int *a;
	int  n=3,nn=n;//玩n把
    int count=0;//总猜测次数
    for(len=1,i=0;i<M;++i)
    len*=10-i;
    a=(int *)malloc(sizeof(int)*len);	
	srand((unsigned)time(NULL));
	//srand(2);
    gen(a);
 //开玩
    while(n--)
    {
		int count_cur=0;
     //每把从猜中开始,例如玩4个数,4A0B为猜中,
//此时进入下一把,会有新的数供猜测 
 //printf("%d\n",a[n]);
		count_cur=guess(a,n);
		printf("此轮共%d步完成\n",count_cur);
		count+=count_cur;
    }
	printf("游戏结束,共计%d轮游戏,总消耗%d步\n",nn,count);
	system("pause");
    return 0;
 } 


赵4老师 2017-08-29
  • 打赏
  • 举报
回复
百度搜相关关键字。

70,022

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧