电脑产生一个随机数(1-100)
猜数字
反馈猜大了还是猜小了
直到才对了,结束
我希望这个游戏,我猜数字的时候玩一把,玩完一把之后觉得玩的不过瘾还可以继续玩,这个时候就可以提供一个菜单,玩完之后呢,来决定继续玩还是结束。所以这个地方最好设计一个菜单。
那这个菜单呢最开始就要打印,而且循环过程中也要打印。所以最开始就给一个do ... while循环,这个do...while循环的特点,不管什么上来就要先执行语句,然后接下来是循环。
那do这里进来的时候我们首先要打印一个菜单,菜单就简单封装一个函数,叫menu。
那这个时候,有了这个菜单的打印,那么这个地方让你选择
然后这个时候就可以选了,可以选0,选1,也有可能不小按其他值,那这个时候就要从键盘输入你的选择,用input来接收
那这个地方当我们有了这个值之后,我就知道你到底输入的是几啊,你输的是1,我们接着玩游戏,输的是0,我们这个地方退出游戏,如果你输入的是其他值呢,我就告诉你选错了。那这个地方就switch,我根据你输入的这个input的值,来进行判断,如果走了case 1,那这里就是猜数字的逻辑,先写的简单点,就写个猜数字。如果是case 0,我们这就提示一下退出游戏,而如果选的是其他的值,走default子句,那这个地方就得输出一句话,选择错误,重新选择。
那当这选择了之后呢,这个do ... while循环要不要继续,如果这里选了0,退出了游戏,那这个循环就不要再继续循环下去了,那怎么让他不循环了呢,这里虽然有break,但这个break只是跳出这个switch语句,他不会跳出外层这个循环的,那怎么办呢。 如果你选了0,这个input是0,所以走了case 0,退出游戏,那我干脆把这个input放到while循环条件里面好了。
input往这放的时候,因为input是0,while循环这判断的时候input=0,0为假啊,那他就不循环了,那这个退出游戏的逻辑对了,其他逻辑呢,比如说,如果选了1,猜数字,这猜完之后break跳出来了,跳到了while这里,然后判断这个input,input是1,所以他继续上来走,这个逻辑也对,如果有人选错了,那选的肯定不是0也不是1,选了其他值,那这个时候input放while这,也让这个while循环为真,再上来重新选择,整体逻辑没有问题。先用猜数字三个字代替了这个猜数字逻辑,先不管他。 那这个时候测试一下:
#include<stdio.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("猜数字\n");
break;
case 0:
rintf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
结果:
在写代码时,要养成一个良好的习惯,就是写一部分测一部分。那这样你前面写的时候有bug就改一下,不会到最后一堆bug难改,不会积累到后面去。
那现在最重要的不是说case 1这就是打印猜数字,是要真正完成猜数字逻辑,就再封装一个函数game,这里面才是猜数字的整个逻辑。
那怎么做呢,把game函数放到前面,返回类型是void,这里面才是猜数字逻辑的过程,
猜数字的步骤:
1、电脑产生一个随机数(1-100)
那这个rand函数怎么用,注意,使用这个函数的时候要添加头文件 #include<stdlib.h>
也是就说,这个rand函数会返回一个值,就是这个随机值,再把这个返回的值存起来,用ret接收
而他返回的这个值打印的话也是可以打印出来的。
注意,他生成的随机数的范围是0 到 RAND_MAX。。那这个 RAND_MAX 是多少呢。
0~RAND_MAX(32767)
那现在测试一下 ,测试两次结果:
发现两次结果一样。 这个rand函数的介绍后面还有这句话。
大概意思就是,每一次这个rand函数被调用,就会通过返回一个明显不相关的数的算法产生一个数。这个算法使用一个方法去产生一个应该被srand函数初始化一些特定值的序列。
就是在使用rand函数之前要先使用srand函数初始化一些特定值。
在rand之前调用srand,这个srand函数需要传个数字,那我先传个100.
发现又出问题了,为什么一直是365呢,因为这个srand的100这个数值没变,那我把他改成200呢
变了,也就是说,只要这个srand函数的这个数在变化,rand函数生成的随机数就在变化。
那我就往这个srand函数里面传个随机数进去,只要这个随机数在发生变化,那这个rand函数就能生成随机数了,那问题来了,我们想要一个随机数结果需要一个随机数,那怎么整呢,所以这个想法是不现实的。
那我们srand函数这里需要传一个值,这个值时时刻刻都在发生变化,那什么在发生变化呢?时间!!时间在一分一秒的发生变化,只要这个时间在变,那生成的随机数就在变,那这个时候怎么获得时间呢?
这个时候就有了时间戳的概念
那所谓的时间戳是什么呢,就像我们的邮戳一样,当我今天要给你写一封信的时候,那我就在这个信封上戳一个邮戳,那这上面就会记录我今天什么时间点,我发出的这封信,上面会有一个时间。那在这个地方时间戳是什么意思呢?就是在这个时间2024-05-10 20:12:04这个时间点,相对于计算机的起始时间之间的一个差值,单位是s,而只要时间在一分一秒地往后走,这个时间戳就在发生变化,时间在变,时间戳就在变。
而这个时间轴就是个整数,传给这个srand函数,就合适,那我们在这个地方如何生成一个时间戳呢,在C语言中有一个叫time的函数,头文件是time.h。 time这个函数,他返回的就是时间戳
如果不想用这个参数的话,可以给他传一个空指针,这个参数用也可以,不用也可以,不用的时候就给他传一个空指针进去,他会返回一个time_t的值,这个值就是时间戳。
time_t是C语言给的一个类型,会发现其实是一个__time64_t,是一个整数
他其实是一个long long 的typedef,所以本质上这个 time_t 是个整数。
所以把这个time函数的返回值传给srand函数也没有问题,这个time函数的参数我不想用,我给他传个空指针(NULL),然后这个time(NULL)函数的返回值类型是time_t,而我这srand函数期望得到的是unsigned int,而time(NULL)返回的本质上也是整型,只是类型叫time_t而已,所以这可以强制类型转换一下,就把他转换成unsigned int这个类型。
这个时候就把随机数生成器就设置好了,注意要添加头文件。
使用time函数返回的时间戳作为这个随机数的生成(srand函数)起点的设置 ,然后再用rand函数来调用生成随机数。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
//0~RAND_MAX(32767)
void game()
{
srand((unsigned int)time(NULL));
//1、生成随机数
int ret=rand();//生成随机数的函数
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
结果:
都不一样,但这个时候会发现如果输入的比较快,会有几次随机数是相同的
生成的随机数有可能是相同的,这有点问题,实际上呢,确实要在rand函数上调用这个srand,但不是每次生成随机数的时候我都设置这个起点,而是应该在整个工程里面只要设置一次就可以了,所以应该把srand((unsigned int)time(NULL));这串代码放到主函数里面,程序运行起来的时候,把随机数的生成起点设置一次就可以了,以后生成随机数的时候直接生成就可以了,不用再设置这个起点。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
//0~RAND_MAX(32767)
void game()
{
//1、生成随机数
int ret=rand();//生成随机数的函数
printf("%d\n", ret);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
这样生成的随机数就非常随机了,哪怕你按的快一点,也不会有两个一样的。这样才是一个正确的使用方法。
那这个空指针(NULL)代表什么
比如这里一个指针变量,int *p= ,这里要给他赋个值,原来定义一个变量的时候习惯性的给他赋一个值,比如int a=0;这是初始化,指针呢在给他初始化的时候,也可以给他初始化一个NULL,
int *p=NULL; NULL这个叫空指针的意思,这个空指针其实就是0的意思,就相当于0
对0的强制类型转换成了void*,但他本质上就是0.那就跟这个变量的创建赋值为0 int a=0; ,是一个道理。
注意srand((unsigned int)time(NULL));time这里传了个NULL,就意味着我暂时不需要这个参数。
这个时候想使用time的参数就不能使用了。更具体还没学。
但这个时候还是不完整的,最开始希望生成的随机数的范围是1到100,那怎么让他生成的随机数范围在1到100呢?
让这里模上100
rand函数生成的这个随机数在0到32767之间任何一个数,任何一个数模上100,得到的数字都是0到99,因为得到的数是余数,而0到99这个数字给他加个一,这个时候就会变成1到100之间的数
这样一处理,生成的随机数肯定是1到100了
到这一步的正确代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
//0~RAND_MAX(32767)
void game()
{
//1、生成随机数
int ret=rand()%100+1;//生成随机数的函数
printf("%d\n", ret);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
结果:
然后接下来猜的数字不能看,屏蔽这个语句
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
//0~RAND_MAX(32767)
void game()
{
//1、生成随机数
int ret=rand()%100+1;//生成随机数的函数
//printf("%d\n", ret);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
接下来就是开始猜数字
2、猜数字
反馈猜大了还是猜小了
直到才对了,结束
全部代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("***************************\n");
printf("******* 1、play *********\n");
printf("******* 0、exit *********\n");
printf("***************************\n");
}
//0~RAND_MAX(32767)
void game()
{
//1、生成随机数
int ret=rand()%100+1;//生成随机数的函数
//printf("%d\n", ret);
//2、猜数字
int guess = 0;
while (1)
{
printf("请猜数字:>");
sacnf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,才对了!\n");
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
结果: