一.游戏规则
猜数字游戏是令程序随机生成目标数字,玩家通过提示调整猜测,最终猜出正确的数字。而在编写这个程序的时候我们可以加入一些元素让这个游戏更丰富,比如限定猜数字次数,或在第几次猜中时会跳出恭喜语句。而接下来我会具体讲该如何编写出这样一个猜数字程序。
要完成猜数字游戏,首先得产生随机数,那怎么产生随机数呢?
1.随机数生成
11.rand函数
C语言提供了一个函数叫rand,这函数是可以生成随机数的,函数原型如所示:
int rand(void);
rand函数会返回一个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是大部分编译器上是32767.
rand函数的使用需要包含头文件:stdlib.h
接下来我们测试一下rand函数,这里多调用几次,产生5个随机数
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
我们运行几次看看结果
我们可以看到虽然一次运行中产生的5个数字是相对随机的,但是第二次运行程序生成的结果和上一次一模一样,这就说明这么写其实是有问题的。
如果再深入了解一下,我们可以发现,其实rand函数生成的随机数是伪随机的,伪随机数不是真的随机数,是通过某种算法生成的随机数。真正的随机数是无法预测下一个值是多少的。而rand函数是对一个叫“种子”的基准值进行运算生成的随机数。
之前前面每次运行程序产生的随机数序列是一样的,那是因为rand函数生成的随机数的默认种子是1。如果要生成不同的随机数,就要让种子是变化的。
1.2srand函数
C语言中有提供一个函数叫srand,用来初始化随机数的生成器(种子)的,srand的原型如下:
void srand(unsigned int seed);
程序中在调用rand函数之前先调用srand函数,通过srand函数的参数seed来设置rand函数生成随机数的时候的种子,只要种子在变化,在每次生成的随机数序列也就变化起来了。
那也就是说给只要srand的种子是随机的,rand就能生成随机数;在生成随机数的时候又需要一个随机数,这就矛盾了。于是我们引入了time函数。
1.3time函数
在程序中我们一般是使用运行的时间作为种子的,因为时间是时刻在发生变化的。
在C语言中有一个函数叫time,可以获得时间,time函数原型如下:
time_t time(time_t* timer);
time函数会返回当前的日历时间,它其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位为秒。返回的类型是time_t类型的,time_t类型本质上其实就是32位或则64位的整形类型。
time函数的参数timer如果是NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
如果timer是NULL,就只返回这个时间的差值。time函数返回的这个时间差也叫做:时间戳。
time函数的使用需要包含头文件:<time.h>
如果只是让time函数返回时间戳,我们就可以这么写:
time(NULL);//调用time函数返回时间戳,这里没有接受返回值
那我们就可以让生成随机数的代码改写成如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
//使用time函数的返回值设置种子
//因为srand函数的参数是unsigned int类型,我们将time函数的返回值强制类型转换
srand((unsigned int)time(NULL));
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
多运行几次看看,这次运行的就有差异了。
(注:截图只是当时程序运行的结果,你的运行结果不一定和这个一样)
srand函数是不需要频繁调用的,一次运行的程序中调用一次就够了。
2.设置随机数的范围
如果我们要生成0~99之间的随机数,方法如下:
rand()%100;//余数的范围是0~99
如果要生成1~100之间的随机数,方法如下:
rand()%100+1;//%100的余数是0~99,0~99的数字+1,范围是1~100,加100后就是100~200
所以如果要生成a~b的随机数,方法如下:
a+rand()%(b-a+1)
三.游戏设计
1.游戏菜单
我们可以制作一个简易的游戏菜单,用来开始或退出游戏。
以下为参考代码:
void menu()
{
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
menu()函数的作用是在控制台中输出一个文本格式的菜单界面,供玩家选择操作。星号(*)用于装饰菜单边框,增强可读性。
2.实现游戏功能的函数
先使用使用rand生成1~100之间的随机数,再设置循环,允许玩家最多猜测5次,在每次猜测后使用条件语句来判断玩家输入的数字与目标数字的关系来给出相应提示。
以下为参考代码:
void game()
{
int r = rand() % 100 + 1;
int guess = 0;
int count = 5;
while (count)
{
printf("\n你还有%d次机会\n", count);
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
count--;
}
if (count == 0)
{
printf("你失败了,正确值是:%d\n", r);
}
}
四.完整代码
参考代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int r = rand() % 100 + 1; // 生成随机数
int guess = 0;
int count = 5; // 总共有5次机会
while (count > 0)
{
printf("\n你还有 %d 次机会\n", count);
printf("请猜数字:> ");
// 检查输入是否为整数
if (scanf("%d", &guess) != 1) {
// 输入的不是数字,清空缓冲区
while (getchar() != '\n'); // 清除所有残留字符
printf("输入错误,请输入数字!\n");
continue; // 跳过后续逻辑,重新循环(不减少count)
}
// 正常判断数字大小
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf(" 恭喜你,猜对了!\n");
break; // 猜对后退出循环
}
count--; // 只有输入有效时才会减少次数
}
// 次数用完后的处理
if (count == 0) {
printf("你失败了,正确数字是:%d\n", r);
}
}
void menu()
{
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请选择:> ");
// 检查输入是否为整数
int result = scanf("%d", &input);
if (result != 1) {
// 输入非数字时清空缓冲区
while (getchar() != '\n');
input = -1; // 强制进入 default 分支
}
switch (input) {
case 1:
game();
break;
case 0:
printf("游戏结束\n");
break;
default:
// 处理非 0/1 的数字或非数字输入
printf("输入错误,请输入 0 或 1!\n");
break;
}
// 清空输入缓冲区残留(避免换行符影响下次循环)
while (getchar() != '\n');
} while (input != 0); // 只有输入 0 时退出循环
return 0;
}
总结:
感谢大家的阅读,希望这个小游戏能够激发你对编程学习的兴趣。若是你发现本篇文章的错误或者有什么改进建议,欢迎在评论区提出。