目录摘要一程序的要求二函数介绍1rand函数2srand函数3time函数4易混淆点三代码编写1菜单函数2主体函数3游戏函数4总代码四游玩效果五限制猜测次数摘要本文从零开始实现猜数字游戏程序从程序的具体需求出发详细介绍了rand、srand及time等关键函数的用法并逐步讲解了菜单、主体及游戏核心逻辑的代码编写。最后展示游戏的实际运行效果以及如何通过代码限制猜测次数来增加游戏挑战性。一程序的要求程序会先生成一个随机数字然后让玩家进入循环反复猜根据玩家猜测的结果进行提示(猜大了或小了)然后并继续猜直到猜对时显示“恭喜你猜对了”并结束本轮游戏。每轮结束后会询问玩家是否继续玩若选择是则生成新的随机数开始下一轮否则退出整个程序。二函数介绍要想实现猜数字游戏⾸先得产⽣随机数那怎么产⽣随机数呢随机数必然会涉及到三个函数randsrandtime。这是C语言设计的三者一起使用即可在每次程序启动后都能生成不同的随机数1rand函数intrand(void);解释rand函数会返回⼀个伪随机数这个随机数的范围是在0~RAND_MAX之间这个RAND_MAX的大小是依赖编译器上实现的但是大部分编译器上是32767。而为什么是伪随机数是因为单独的使用rand函数是有缺陷的如下进行两次测试每次测试都是连续调用5次rand函数#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; }多次运行结果如下图单次运行中不断的rand的确生成了不同的随机数但是第二次重启程序发现生成的5个随机数和上一次程序是相同的这就是单独使用rand函数的缺陷原因是rand 函数是对⼀个叫种子的基准值进⾏运算⽣成的随机数。之所以每次运⾏程序产生的随机数序列是⼀样的那是因为每次rand函数生成随机数的默认种子都是1。所以导致每次程序启动得到的随机数序列都是一样则用户玩猜数字游戏只需记住这几个数字就可以一次猜中所以单独的使用rand函数是不对的而要想要rand的种子值改变而rand函数又没有参数那怎么办呢不必担心C语言给我们提供了srand函数去间接的修改rand函数的种子值2srand函数voidsrand(unsigned intseed);解释程序中在调⽤ rand 函数之前先调⽤ srand 函数通过 srand 函数的参数seed来间接设置rand函数的种子值然后rand再根据此种子值去生成随机数序列❓️想要每次游戏程序启动rand都能生成不同的随机数序列则需要保证每次的种子值不同所以每次srand的参数都要不同但我们不可能每次启动游戏前都手动的去代码中改变一下srand的参数把所以需要借助time函数3time函数time_ttime(time_t* timer);注返回的类型是time_t类型的time_t 类型本质上其实就是32位或者64位的整型类型time 函数会返回当前的日历时间返回1970年1月1日0时0分0秒到现在程序运⾏时间之间的差值单位是秒。所以time的返回值是动态改变的time函数返回的这个时间差也被叫做时间戳time函数的参数 timer指针 如果是非NULL的指针的话函数会将这个返回的差值放在timer指针指向的内存中。 如果 timer 是 NULL就只返回这个时间的差值。所以我们这里只需给time传递NULL参数然后把time的返回值作为srand的参数(强转即可)即可获得动态的种子值无需再在每次程序运行前都手动修改代码所以写法如下srand((unsigned int)time(NULL));//调用srand其根据time函数给rand函数一个初始种子值三种函数结合使用则可以确保在每次启动的游戏中都生成不同的随机数序列4易混淆点正确调用逻辑一次srand 多次 rand解释一次srand代表确定了游戏在本次启动的种子值而多次rand就是从这个种子值获取随机数序列然后下一次游戏启动srand的种子值会因为时间而改变则多次rand的值也会改变~错误调用逻辑每次rand前都srand一次解释这必然是错的首先srand的作用是重置起点(重置种子值)而不是“生成随机数”、你完全没必要重复的调用其次这种写法在同一秒内连续运行则会生成相同的数字因为你在同一秒内进行就代表此时的时间戳一样就代表种子值一样就代表srand会把起点重置到相同的值那么你此时在这一秒内rand值必然是一样的验证错误的代码如下#include stdio.h #include stdlib.h #include time.h int main() { for (int i 0; i 5; i) { srand(time(NULL)); // 每次循环都重新设置种子 printf(%d , rand() % 100); // 每次都是该种子的第一个数 } return 0; }解释srand的调用不仅仅是设置一下rand的种子值并且会重置该种子值所对应的随机数序列的起点此时你在同一秒内rand由于种子值相同所以当然会生成相同的数字啦所以srand只需要调用一次而rand可以重复调用在这个随机数序列中不断的往后取随机数即使是正确的代码逻辑你如果能在一秒之内猜出数字并重启程序进行下一把游戏则下一把游戏的随机数也是和上一把一样的因为一秒内时间戳相同种子值相同随机数都是序列的第一个但是一秒内完成这么多操作不太现实~三代码编写1菜单函数任何游戏上来肯定都是一个菜单让玩家选择玩还是退出所以我们制作一个简单的菜单函数。//菜单的打印 方便用户操作 void menu() { printf(*********************************\n); printf(*****1-玩游戏***0-退出游戏*****\n); printf(*********************************\n); }打印效果如下2主体函数玩家进来看见显示的菜单后可能输入0或1或其他的数字。所以我们用一个switch语句来对玩家的输入进行分类管理。switch语句选择1玩游戏选择0退出游戏选择其他选择错误。再综合我们玩完一把可以不关闭程序再次游玩的目的所以这个switch语句应该放在一个循环中那么循环的判断条件是什么呢当然是用户输入0了这就是为什么我们设置0是退出游戏的原因0为假刚好可以用来结束循环。所以玩家输入的1或者0或者输入错的其他非0的数字既用于switch语句中case的选择又用于了循环的条件判断代码int main() { srand((unsigned int)time(NULL));//调用srand其根据time函数给rand函数一个初始种子值 int input 0; do { menu();//打印菜单 printf(请选择:); scanf(%d, input); switch (input) { case 1://1代表玩游戏 game();//启动游戏 break; case 0://0代表退出游戏 printf(游戏已退出\n); break; default://其他输入不合规 printf(选择错误重新选择\n); break; } } while (input); return 0; }3游戏函数我们游戏函数主题内部对于猜数字一定是循环的玩家一般不可能一下子就猜对所以是一个循环整体代码//game函数的实现 void game() { int ret rand() % 100;//控制随机数的范围为0~99 int guess 0;//初始化猜测值为0 while (1) { printf(请猜数字\n); scanf(%d, guess); if (guess ret) { printf(恭喜你猜对了\n); break; } else if (guess ret) { printf(猜大了\n); } else { printf(猜小了\n); } } }解释其中的%100可以让随机数的范围为0~99利用了模的性质rand() %100;//余数的范围是0~99rand()%1001;//%100的余数是0~99,0~99的数字1,范围是1~100100 rand()%(200-1001)//余数的范围是0~100加100后就是100~2004总代码#define _CRT_SECURE_NO_WARNINGS 1 #includestdio.h #includetime.h #includestdlib.h //菜单的打印 方便用户操作 void menu() { printf(*********************************\n); printf(*****1-玩游戏***0-退出游戏*****\n); printf(*********************************\n); } //game函数的实现 void game() { int ret rand() % 100;//控制随机数的范围为0~99 int guess 0;//初始化猜测值为0 while (1) { printf(请猜数字\n); scanf(%d, guess); if (guess ret) { printf(恭喜你猜对了\n); break; } else if (guess ret) { printf(猜大了\n); } else { printf(猜小了\n); } } } int main() { srand((unsigned int)time(NULL));//调用srand其根据time函数给rand函数一个初始种子值 int input 0; do { menu();//打印菜单 printf(请选择:); scanf(%d, input); switch (input) { case 1://1代表玩游戏 game();//启动游戏 break; case 0://0代表退出游戏 printf(游戏已退出\n); break; default://其他输入不合规 printf(选择错误重新选择\n); break; } } while (input); return 0; }四游玩效果五限制猜测次数#include stdio.h #include stdlib.h #include time.h 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); } } 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(请选择:); scanf(%d, input); switch (input) { case 1: game(); break; case 0: printf(游戏结束\n); break; default: printf(选择错误重新选择\n); break; } } while (input); return 0; }解释本质就是用一个变量count作为循环的判断条件当其为0代表猜测次数用完❓️为什么C语言要设计srand函数去间接改变rand的种子值而不是让rand自己进行改变其实设计一个能自己管理种子的rand函数在技术上是完全可行的。但C语言的设计者选择了当前这种“职责分离”的更优设计哲学也就是“低耦合”原则。在这个设计下srand(seed)专门负责设置或重置随机数生成器的“起点”种子。rand()则专注于从当前起点开始推进状态并返回下一个随机数。这样拆分后两个函数各司其职互不干扰。如果某一部分的逻辑需要修改比如更换更复杂的随机数算法另一部分完全不受影响极大地方便了程序的维护和调试。这种清晰、解耦的设计是C语言系统级编程哲学的典型体现。 [ 作者 ] shylyly [ 首次发布 ] 2024.1.11❌ [ 最新修改 ] 2026.10.11 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教。