题目回顾
废话可以不看: 众所周知,小郑是一个学习机器学习方向的大佬,所谓近朱者赤,小郑的电脑也大佬了起来,比起上面简单的猜数字,电脑表示不屑,并表示可以加点难度。小欧因此想了个规则,规则如下:
小欧随机想一个三位数(每位的数字都不重复,且每位都不为0),让电脑猜,电脑输出一个猜测的值,小欧就告诉结果 结果格式为 NRNW,即数值对位置也对的为R,数值对位置不对的计为W
例如 小欧想的是369,而电脑猜的是396,那么数值对位置对的是 3 , 而数值对位置不对的是9和6,,因此结果应该输出:1R2W 而如果猜457则输出为0R0W
通过得到的结果电脑继续猜,直到猜对为止。
看不懂上面的,简化版如下:
写一个程序让电脑猜数字;规则:随机给出一个三位数(每位的数字都不重复,且每位都不为0)让电脑猜,电脑猜测一个值,便会输出结果 结果格式为 NRNW,即数值对位置也对的为R,数值对位置不对的计为W;如给出369,电脑猜396则结果是1R2W,而如果猜457则输出为0R0W,要求经过几轮电脑就能猜对你的数字
提示
如:小欧随机想的数字为632则输出如下:
num is: 632
guess 123
your ans is 0R2W
guess 234
your ans is 1R1W
guess 314
your ans is 0R1W
guess 532
your ans is 2R0W
guess 632
your ans is 3R0W
632
合计猜测次数:5次
要求
本程序按实现功能按点给分:
- 实现想的数字是随机输入的,而不是手动输入的 保证输入的;随机生成的三位数需符合题目要求
- 能够成功的判断出是几R几W,运行全程不需要输入任何东西。
- 电脑能够根据几R几W知道接下来怎么猜,而不是盲目随机
- 在8次内猜出是什么
- 别想着偷鸡百度
事先声明:我只实现了前两个功能
题目思路
1.全程不需要输入任何东西,说明真的要用随机数来搞了。
2.三位数要每位数都不重复,且不为0。所以如果只用随机数rand()%9+1可能会生成相同的数字,要加一些限制条件。
我的具体实现是用两个数组,一个是存放着1-9的val数组,用来提取;另一个是用于判断某个数字是否被提取过的judge数组
然后生成的三位数存放入num(要猜的数字)和guess(电脑猜的)
ps:本身之前我num和guess在main里各写了两个,但感觉两个重复的片段很高,就写成了一个set_hun_num函数,调用两次
3.判断几R几W,我写了两个函数。
R的判断就很简单,位置对数值对直接一个条件就好了
W的判断如果用for嵌套循环判断,会出现重复的情况(因为是3*3),所以要如果这个num的某一位考虑过了就要表明他被判断过了,具体实现方法是加了一个判断数组。数组yyds
具体的函数实现方法不在此繁述,请移步代码后半部分查看
整个程序都会有详细的注释
为了简化程序,大改了两次程序
#include<iostream>
#include<time.h>
#include<stdlib.h>//随机数要用到的两个库
using namespace std;
int isR(char *,char *);//判断数值对位置也对的函数,传入两个数组作判断
int isW(char *,char *);//判断数值对位置不对的函数,传入两个数组作判断
void set_hun_num(char [4]);//生成一个每位都不相同的三位数,存入一个字符数组中
int main()
{
srand(time(NULL));
int i;//for专用
//1.生成数
char num[4];//存放三位数,开4是因为我想从1开始
set_hun_num(num);//存放电脑要猜的数
cout<<"num is:";
for (i = 1; i <= 3; i++)
cout<<num[i];//输出生成的随机数是什么
cout<<endl;
//2.电脑开始猜数
char guess[4];//存放电脑猜的三位数
int cnt = 0;//计数器,到了8次就不给你猜了
//猜对了要输出你总共用了多少次
while (cnt <= 8)//因为要猜很多次,所以开个循环
{
set_hun_num(guess);//电脑猜一个三位数,存入guess中
cout<<"guess ";
for (i = 1; i <= 3; i++)
cout<<guess[i];//输出生成的随机数是什么
cout<<endl;
//接下来要开始输出几R几W了
int R = 0,W = 0;//R是位置对数值也对,W是数值对位置不对
//判断R和W写了两个函数,看起来会比较简洁
R = isR(num,guess);
W = isW(num,guess);
cout<<R<<"R"<<W<<"W"<<endl;//输出几R几W
cnt++;//猜的次数++
if (R == 3 && W == 0)//如果猜中了
{
for (i = 1; i <= 3; i++)
cout<<guess[i];//就输出猜中的数字
cout<<"共计猜测次数:"<<cnt<<"次";
break;
}
}
return 0;
}
int isR(char *num,char *guess)
{
int n = 0;int p;
for ( p = 1; p <= 3; p++)
{
if (num[p] == guess[p]) n++;//位置对数值也对
}
return n;//返回R的个数
}
int isW(char *num,char *guess)
{
int n = 0;
int p,q,i;//for专用
int jud[4];
//由于后面两个for3*3会有重叠,所以再增加一个用于判断的数组
for ( i = 1; i <= 3; i++)
jud[i] = 0;//第i位没有被判断过,0代表没判断过,1代表判断过
for ( p = 1; p <= 3; p++)//num的第p位
{
for ( q = 1; q <= 3; q++)//guess的第q位
{
if ( jud[p] == 0 && num[p] == guess[q] && p!=q)
{//num中第p位数字没有被判断过,且检测到值相同,且位置不同
jud[p] = 1;//将状态改为判断过
n++;//个数+1
break;//停止第p位的检索
}
}
}
return n;
}
void set_hun_num(char num[4])
{
int i;
int val[10];//提取的值
int judge[10];
for ( i = 0; i <= 9; i++)
{//对两个数组进行初始化
val[i] = i;
judge[i] = 0;//1代表被提取过,0代表没有
}
for ( i = 1; i <= 3; i++)
{
int t = rand()%9+1;//此时t是1~9内的随机数
if (judge[t] == 0)//没提取过t这个数
{
num[i] = char(val[t]+'0');//向num存入字符型数字t
judge[t] = 1;//状态改为提取过
}
else if (judge[t] == 1)//如果被提取过就找另外的数
{
int k = rand()%9+1;//再生成一个1~9内的随机数
while (k == t)
{//如果生成了同样的数
k = rand()%9+1;//再求随机数,直到不同
}
num[i] = char(val[k]+'0');
}
}//于是就生成了这样的三位数并存进了传入的字符数组中
}
后两部分感觉跟dp有些关系,没啥思路,放弃。拿完前两部分的分就跑
下面是运行实例截图
本题从构思到放弃大概经历了1天半的时间