当前位置: 首页 > news >正文

C语言程序设计第7天/猜数字游戏与个人解析

猜数字游戏

  • 电脑自动生成1~100的随机数;
  • 玩家猜数字,猜数字的过程中根据猜的数字大小给出大了或小了的反馈,直到猜对游戏结束。

流程图

代码实现

#include<stdio.h> #include<stdlib.h> //生成随机数函数头文件 #include<time.h> //time时间戳头文件 void game(){ //将游戏逻辑和过程封装进函数game int input_num = 0; //将用户猜的数字储存 int r = rand() % 100 + 1; //随机生成1-100中的一个数 printf("Please type a number\n"); do { int ret = scanf("%d",&input_num); if(ret != 1) { while(getchar() != '\n'); printf("Wrong input! Please enter num\n"); continue; //执行完不退出循环,跳过这一轮重新输入 }if (input_num == 101) { printf("You gave up!\n"); return; // 直接退出 game 函数 }else if (input_num < r){ printf("The entered number is smaller than it\n"); //如果小于生成的随机数则提示小了 }else if (input_num > r){ printf("The entered number is bigger than it\n"); //如果大于生成的随机数则提示大了 } } while (input_num != r); //输入的数字不等于随机数时循环到上面重新输入数字 printf("Congratulations on beating it!\n"); //答对了 printf("Do you want to go again?\n"); } int main(){ srand((unsigned int) time (NULL)); //将time返回的时间戳强制转换为int类型给srand;使srand生成的种子每次都不一样 int input = 0; do { printf("--------------\n"); printf("----1.play----\n"); printf("----0.eixt----\n"); printf("-Please enter-\n"); printf("--------------\n"); scanf("%d",&input); //选择1或0 switch (input) { case 0: printf("Exit Game byebye!\n"); break; case 1: printf("Start Game\n"); game(); //玩游戏的函数 break; default: printf("Error, please choose 1 or 0 again\n"); //用户输入非1或0的数据提示错误,重新输入; break; } } while (input); return 0; }

项目场景1

我发现如果用户按错了输入成其他字符或字母时程序会出现死循环,我试图解决这个情况;

问题描述

问题:当运行时我在猜数字阶段输入非整型后程序自动循环一句话“The entered number is smaller than it”;


原因分析

可能是由于输入非整型后scanf读取失败,a留在缓冲区,返回0后判断为The entered number is smaller than it。小于随机数,同时scanf不会把错误字符从缓冲区移除,导致无法重新输入数据而无限循环,可以加入一段重制scanf的代码;


解决方案

加入了一段判定是否为异常数据的if语句,但其中的语句并没有学过;


项目场景2

我希望在进行猜数字的过程中用户可以随时退出,于是添加新的if判断是否需要退出程序;


问题描述

问题:输入101后无法退出;


原因分析

检查了代码都没有问题,可能是exe文件还是旧版;


解决方案

新建了一个c语言文件将代码复制过去运行发现没问题,判断为exe文件未及时更新,中断所有进程重新编译运行可以使用了;


随机数生成

rand函数

使用C语言中的rand函数可以生成随机数

int rand(void)

使用rand函数与srand函数前需要包含一个头文件:<stdlib.h>

而rand函数生成的随机数其实是一个伪随机数,范围在0~RAND_MAX之间,RAND_MAX的大小依赖编译器,大部分编译器上是32767

printf("rand num:%d",rand()); //带括号为rand生成的随机数;

printf("rand num:%d",rand); //不带括号为rand这个函数在内存中的地址;

之所以运行时,不带括号的每次都不一样看着更像随机数的原因是

  • 现代操作系统使用了"地址空间布局随机化"
  • 每次程序启动时,操作系统故意把函数、变量加载到内存中的不同位置,就像每次搬家时把家具摆在不同房间一样。
  • 这样做是为了安全:防止黑客通过固定地址发起攻击(比如缓冲区溢出攻击)

而带括号的rand生成的就像上面说的,是伪随机数。它是基于“种子”计算得出。

  • 如果你不调用srand()设置种子,C语言默认种子是1

  • 种子相同 → 算法相同 → 生成的随机数序列完全相同

所以每次运行程序时rand()输出的随机数都是一样的。

那么如何让rand()的种子变化,可以使用srand函数


srand函数

为rand()函数设置随机数生成器的“种子”。

#include <stdlib.h>
void srand(unsigned int seed);

  • void:这个函数什么都不返回,不会像scanf一样返回0和非0;
  • srand:函数名,全称是“seed Rand”(设置随机的种子);
  • unsigned int:意为调用这个函数时必须要传一个unsigned int类型的数字(非负整数)
  • seed:表示你传进来的数字会被当做种子使用
  • 可以传任何的unsigned int 值如:0、100、99999、time(NULL)返回的时间戳、123等

在rand函数中的用法:

srand((unsigned)time(NULL));

可以理解为

time(NULL)

返回当前时间戳(如 1698765432,类型 time_t)

(unsigned)强制转换

转成 unsigned int(如 1698765432,可能截断)

srand(1698765432)

种子被存入内部全局变量

之后每次调用 rand(),都从这个种子开始推算

在用srand设置好种子后,rand函数不需要做任何修改或接收额外参数。每次运行程序时调用rand()的时候就会根据srand的种子自动计算好。


time函数

使用time函数前需要添加<time.t>头文件

在学习过程中通常是使用程序运行的时间作为种子,因为时间是时刻在变化的。那么可以使用time函数:

#include <time.h>
time_t time(time_t *timer);

  • time_t:返回值类型:时间戳(从1970年1月1日到现在的秒数)
  • time:函数名
  • time_t*timer:参数:一个指向time_t的指针(可以传NULL(只取返回值))

time函数的参数timer 如果是非NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
如果timer是 NuLL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。

时间戳:从某个固定的时间点开始,到现在一共经过了多少秒(或毫秒)


题外理解:getchar

在项目场景1中我使用了while(getchar() != '\n');来进行进一步的程序完善

while(getchar() != '\n');

这句话的意思当getchar读取的字符不是回车符时就执行循环。


while((c = getchar()) != '\n');

给这段代码加上变量的话就可以保存读到的字符

图解:

执行代码后

getchar的特性是读取并返回字符,是否存储取决于自己有没有添加变量存储读取的字符;scanf的特性是根据格式读取并存储,失败的会留在缓冲区;这两个函数刚好可以补齐短板。

http://www.jsqmd.com/news/1240732/

相关文章:

  • 告别Origin、Visio熬夜肝图!Okbiye科研绘图实测[特殊字符]期刊级图表一键搞定
  • 大模型提示工程:核心基元与高效交互设计
  • 2026 年 7 月国内塑料制品工厂测评,环保降解包装源头厂盘点 - 热点速览
  • TMS570安全MCU内存保护与错误管理:MPU与ESM实战配置指南
  • 儿童眼部护理怎么选?中医舒缓护理与物理冷敷方式实测对比
  • 六万 star TypeScript 大神开源 skills /grill-me 好用,但国产 spec-superflow 更狠
  • 硬件测试内容之四:EVT/DVT/PVT/MP
  • OpenCV 5 DNN模块:独立推理引擎与边缘AI部署优化指南
  • 实时协同编辑方案深度对比:OT 与 CRDT 的工程实践与架构选型
  • TI Tiva C系列MCU HIB休眠模块实战:RTC、BBRAM与低功耗管理详解
  • 2026年合规模式推三回本系统开发
  • Agent 开发的新数理基石:基于“距离奇异参数 (↑JQ)”的二维投影代数
  • 匠心焕新|北京伯爵2026售后网络升级,全新热线守护时计 - 伯爵官方售后服务中心
  • 欧米茄佛山维修网点汇总|最新**热线及地址全新启用(2026年7月最新) - 欧米茄中国服务中心
  • 展锐相机DreamCamera2模式精简
  • 安卓模拟器性能对比与《金铲铲之战》优化指南
  • SPD-Conv技术解析:提升YOLOv8小目标检测性能
  • AI陪伴产品的伦理设计框架:透明度、可控性与退出机制的工程实现
  • AI大模型人才转型:核心能力与实战路线
  • 看好啦,新用户打开千问输入口令:新用户645,领取福利!
  • CNN-BiLSTM-KDE混合模型在多变量时间序列预测中的应用
  • Tiva™ ADC高级采样模式:并发与交错采样的寄存器级实现
  • 6N136SDM高速光耦芯片
  • AI反作弊的数据存储方案:实时特征计算与离线模型训练的数据管道设计
  • Cursor AI编程工具:提升开发效率的实战评测
  • 佛山哪家形象片制作团队实力更强? - 广州影画邦
  • Tiva TM4C129 GPTM定时器PWM模式配置详解与实战
  • 三种主流非接触除尘技术对比:脉冲龙卷风 vs USC 干式超声 vs 等离子除尘
  • 正规的工业重型链条制造商 - 热点速览
  • 西安健身管理软件定制开发,IoT设备心跳监测代码实现