正文
游戏要求:
- 电脑自动生成1-100的随机数。
- 玩家猜数字,猜数字的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束。
一、随机数生成
想要完成猜数字游戏,首先得产生随机数,那怎么产生随机数呢?
1.1 rand
C语言提供了一个函数叫rand(rand是没有参数的,参数是void,即不需要参数,会产生一个随机值并返回),这个函数可以生成随机数,函数原型如下所示:
1 int rand(void)
rand函数会返回一个伪随机数(即假的随机数,根据算法生成的随机数,看似随机实则不是真正的随机),这个随机数的范围是0~RAND_MAX,这个RAND_MAX的大小是依赖编译器上实现的,但是大部分编译器上是32767。
rand函数的使用需要包含一个头文件是:stdlib.h
这里展示一下rand函数的效果:
我们可以看到虽然一次运行中产生的5个数字是相对随机的,但是如果多试几次的话,下一次运行程序生成的结果和上一次一摸一样,这就说明问题了。
真正的随机数是无法预测下一个值是多少的,而rand函数是对一个叫种子的基准值进行运算生成的随机数。
之所以前面每次运行程序产生的随机数序列是一样的,那是因为rand函数生成随机数的默认种子是1。
如果要生成不同的随机数,就要让种子是变化的。
1.2 srand
C语言又提供了一个函数叫srand,用来初始化随机数的生成器的(随机数生成器就是种子),srand的原型如下:
1 void srand(unsigned int seed);
程序中在调用rand函数之前先调用srand函数,通过srand函数的参数seed来设置rand函数生成随机数的时候的种子,只要种子在变化,每次生成的随机数序列也就变化起来了。
那也就是说给srand的种子如果是随机的,rand就能生成随机数,在生成随机数的时候有需要一个随机数,这就有点像先有鸡还是先有蛋的问题了哈哈。
1.3 time
在程序中我们一般是使用程序运行的时间作为种子的,因为时间时刻在发生变化的。
在C语言中有一个函数叫time,就可以获得这个时间,time函数原型如下:
1 time_t time(time_t* timer);
time函数会返回当前的日历时间,其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位是秒。返回的类型是time_t类型的(time只有一个参数就是time_t*,这里不需要它的参数只要它的返回值)。time_t类型本质上其实就是32位或者64位的整型类型。
time函数的参数timer如果是非NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
如果timer是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳(时间戳就是一个秒数,可以换算成一个时间,反之也可以)。
time函数的使用需要包含头文件:time.h
如果只是让time函数返回时间戳,我们就可以这样写:
1 time(NULL);//调用time函数返回时间戳,这里没有接受返回值
那我们就可以让生成随机数的代码改写如下:
第一次运行:
第二次运行:
这样子每次生成的随机数就有差异了。
注:srand函数是不需要频繁调用的,依次运行的程序中调用一次就够了。频繁调用的话,程序运行的速度是非常快的,一秒钟计算几千万次,极短的内time可能没有发生变化,两次调用就有可能生成一样的随机数,我是这么理解的。
1.4 设置随机数的范围
这里就发现,前面生成的随机数很大,没有什么可玩性呀,如果我们要生成0~99之间的随机数,代码如下:
1 rand()%100;//余数的范围是0~99
如果要生成1~100之间的随机数:
1 rand()%100+1;//%100的余数是0~99,0~99的数字+1,范围是1~100
如果要生成100~200的随机数:
1 100+rand()%(200-100+1)
2 //余数的范围是0~100,加100后就是100~200
所以如果要生成a~b的随机数,代码如下:
1 a+rand()%(b-a+1)
二、猜数字游戏的实现
游戏要求:
- 电脑自动生成1~100的随机数。
- 玩家猜数字,猜数字的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束。
在这里我们就开始写我们这个游戏的代码了,但是在这之前,我们还想实现一个功能,玩一把不过瘾,可以继续玩。那么怎么实现这样的效果呢?
一般我们玩游戏不都有一个菜单,选1继续玩,选0退出游戏,玩完一把之后呢,弹出一个菜单,选1继续玩。所以我们如果要设置一个选1还是0的界面的话,这个界面至少要打印一次。
#include<stdio.h>
int main()
{
int input = 0;
do
{
printf("*****************************\n");
printf("********* 1. play *******\n");
printf("********* 0. exit *******\n");
printf("*****************************\n");
printf("请选择:>");
scanf("%d", &input);//1 0 ...
} while ();
return 0;
}
这里就是一个简单的菜单页面了,接下来我们就要看用户输入的是什么了,怎么来响应,通过判断input值来实现,这里我们用switch语句。
#include<stdio.h>
int main()
{
int input = 0;
do
{
printf("*****************************\n");
printf("********* 1. play *******\n");
printf("********* 0. exit *******\n");
printf("*****************************\n");
printf("请选择:>");
scanf("%d", &input);//1 0 ...
switch (input)
{
case 1:
printf("猜数字\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
//
} while (input);
return 0;
}
这里无论选择1,0还是选择错误,都会来到//这里,然后while进行判断,当选择1和选择错误的时候,都会再打印一次菜单让你重新选择,只有选择0的时候会退出循环退出游戏,而把input放进去就可以达到这样的效果,可以用自己的电脑试一下。
注意这里的break是跳出switch的,不是跳出do while循环。
这里是不是有些人觉得总把这个菜单放这里不好看呢,我们能不能单独把这个菜单封装起来呢,当然是可以的,这里我们封装一个函数,这个函数的名字我们用menu(菜单)
void menu()
{
printf("*****************************\n");
printf("********* 1. play *******\n");
printf("********* 0. exit *******\n");
printf("*****************************\n");
}
这个函数没有参数,不需要参数,所以这里用空括号就可以了,这个函数的返回类型我也不需要,就写一个void就可以,这样就封装好了,以后要打印一个菜单,就直接调用它就可以了。
接下来还需要进一步写的就是猜数字这一块的具体内容了,为了美观,我们依旧用一个函数来封装,这里我们用game。
在这个函数内,我们就目标就是完成两步:
- 生成随机数
- 猜数字
根据前面所写随机值内容,我们就写出这样一串代码:
void game()
{
srand((unsigned int)time(NULL));
//1.生成随机值
int r = rand() % 100 + 1;
}
但其实这样是不对的,srand函数是不需要频繁调用的,一次运行的程序中调用一次就够了,而把它封装在函数里的话,每次调用一次game,就会调用一次srand,显然是不可以的,所以我们把它放到主函数里就可以了。
这里我们就开始猜数字了,因为不知道要猜多少次,所以我们就用while循环就可以了:
void game()
{
//1. 生成随机值
int r = rand() % 100 + 1;
//2. 猜数字
int g = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &g);
if (g < r)
{
printf("猜小了\n");
}
else if(g > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了,数字是:%d\n", r);
break;
}
}
}
这个库函数就封装好了,最后我们把前面所有写的代码组装到一起,就有了下面这串猜游戏的代码了:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <time.h>
#include <stdlib.h>
void menu()
{
printf("*****************************\n");
printf("********* 1. play *******\n");
printf("********* 0. exit *******\n");
printf("*****************************\n");
}
void game()
{
//1. 生成随机值
int r = rand() % 100 + 1;
//2. 猜数字
int g = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &g);
if (g < r)
{
printf("猜小了\n");
}
else if(g > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了,数字是:%d\n", r);
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL)); //保证调用一次就行
do
{
menu();
printf("请选择:>");
scanf("%d", &input);//1 0 ...
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
//
}while(input);
return 0;
}
下面是运行示意图,已经达到了我们想要的效果
而且这个写好的代码已经保存为一个exe文件了,我们想玩的时候,直接找到相对应的路径打开进行玩游戏就可以了。
还有一点就是这里如果你想把这个游戏拷给别人玩,这里建议保存为Release文件,这里正常在VS上走一下代码,再打开之前的路径,你就可以在Debug这里看到一个Release文件。
打开程序也可以正常玩。
我们还可以再加上猜数字的次数限制,如果5次猜不出来,就算失败。
void game()
{
//1. 生成随机值
int r = rand() % 100 + 1;
//2. 猜数字
int g = 0;
int count = 5;
while (count)
{
printf("还剩下%d次机会\n", count);
printf("请猜数字:>");
scanf("%d", &g);
if (g < r)
{
printf("猜小了\n");
}
else if (g > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了,数字是:%d\n", r);
break;
}
count--;
}
//
}
我们可以初始化一个count的值为5,5次之内猜不到,就count–,当五次机会都用完的时候,count变为0就跳到了//这里,如果五次之内猜对了,break也是跳到//这里,所以在//这里就可以给一个判断:
if (count == 0)
printf("次数用完,很遗憾游戏失败\n");
其余代码内容不变,只改变game这里的内容就可以有这样的效果了:
void game()
{
//1. 生成随机值
int r = rand() % 100 + 1;
//2. 猜数字
int g = 0;
int count = 5;
while (count)
{
printf("还剩下%d次机会\n", count);
printf("请猜数字:>");
scanf("%d", &g);
if (g < r)
{
printf("猜小了\n");
}
else if (g > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了,数字是:%d\n", r);
break;
}
count--;
}
if (count == 0)
printf("次数用完,很遗憾游戏失败\n");
}
好了,这就是猜数字游戏的全部内容了,后面小编的更新速度应该就会慢很多了,因为快期末考了,哎真的对主科目提不起兴趣呀,不过还是不能挂科,喜欢小编内容的读者给小编三连支持一下呀