news 2026/5/25 11:56:01

C语言实战第一篇:简易猜数字游戏实现与拓展

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言实战第一篇:简易猜数字游戏实现与拓展

一.项目需求

实现一个控制台版猜数字游戏,具备以下功能:

1.电脑随机生成一个1 ~ 100之间的整数

2.提供主菜单,支持选择“开始游戏”或“退出游戏”

3.处理玩家非法输入(如字母、符号、非法数字),防止程序卡死

4.每次猜测后给出“猜大了”“猜小了”的提示

5.玩家猜测正确后,游戏回到主菜单界面

二.分步实现代码与思路讲解

那我们正式开始梳理我们的设计思路,首先搭建一个主函数框架

//主函数框架intmain(){return0;}

随后,我们要打印一个简单的主菜单,要让用户“有得选”,这里我们可以选择封装为一个函数,命名为menu,这个函数不需要返回值和参数,只负责打印主菜单

当然printf函数需要头文件<stdio.h>(咱们后续就默认已经有了这个头文件了)

#include<stdio.h>
//打印主菜单voidmenu(){printf("---------------------\n");printf("------猜数字游戏------\n");printf("-------1. play-------\n");printf("-------0. exit-------\n");printf("---------------------\n");}

主菜单有了,用户也就可以开始进行选择了,这里我们可以用printf函数先告诉用户可以选择数字了,随后用scanf函数接收用户输入的值

在用户输入完成后,我们需要用到条件语句去对用户输入的值进行判断,输入1的话,进入游戏(这里我们先拟定一个game函数,后面进行实现);输入0的话,退出游戏;如果输入的是其他值,可以告诉用户输入的值是非法的

这里我选择的是switch语句,当然如果使用if语句也是可以的,这里就不过多做展开了

intmain(){intinput=0;menu();printf("请输入您要选择的数字:");scanf("%d",&input);//判断用户输入switch(input){case1:game();break;case0:printf("退出游戏\n");break;default:printf("输入非法,请输入有效数字!\n");break;}return0;}

这个时候我们可能在想,如果每一次都让break直接跳出的话,那相当于程序的运行是“一次性”的,也就是说这个游戏只能运行一次,那我们的初心“输入0退出游戏”就显得有些多余了,有没有什么办法能让用户如果不输入0,就一直运行下去呢?

使用循环(迭代)去解决问题是相对比较好的,我在这里选择的是do-while循环,因为我们希望程序上来不要管别的,先打印一次主菜单,也就是先运行一次游戏,后续再进行逻辑判断:用户要玩还是退出,do-while循环明显是更合适的

问题在于循环条件是什么呢?根据上述代码,我们发现输入0为“退出”这个设计刚好让while的判断条件为假,而其他任何数字都会被判断为真,所以while的循环条件同样可以使用input进行判断

intmain(){intinput=0;//循环执行逻辑do{menu();printf("请输入您要选择的数字:");scanf("%d",&input);switch(input){case1:game();break;case0:printf("退出游戏\n");break;default:printf("输入非法,请输入有效数字!\n");break;}}while(input);return0;}

当然,这里我们也要考虑到用户可能输入的是字母和符号,也就是字符,那这里我们可以对scanf的返回值进行判断,如果返回值不是正常的1,就用getchar函数清空缓冲区,随后continue回到循环的起始位置

intmain(){intinput=0;do{menu();printf("请输入您要选择的数字:");///合法性判断if(scanf("%d",&input)!=1){while(getchar()!='\n');printf("输入非法,请输入有效数字!\n");continue;}switch(input){case1:game();break;case0:printf("退出游戏\n");break;default:printf("输入非法,请输入有效数字!\n");break;}}while(input);return0;}

主函数的框架我们基本已经完成了,接下来就是对game函数的处理

game函数也同样不需要任何返回值和参数,我们只需要关心函数内部的逻辑是如何实现的
但在那之前,我们首先要做一件事情:生成随机值

这里我们可以使用rand函数来进行随机值的生成,rand函数是可以返回一个随机值的

但rand函数生成的随机值是“伪随机”的,因为它依靠种子(Seed)去生成随机值,这是它的“基准”。且Seed默认都是1,而且rand是无参函数,不能传参,那我们怎么改变这个Seed呢?

这里需要用到srand函数,对Seed进行初始化,但进行传参的时候,我们同样需要一个随机值,那有没有什么值是一直在变化的呢?

对,时间戳!

我们可以调用time函数,对其传一个空指针,就可以对srand的参数进行随机生成了,因为时间戳是一直在变化的

rand和srand函数的调用需要用到头文件<stdlib.h>,time函数的调用需要头文件<time.h>

但需要注意time函数的返回值是time_t类型的,而srand的参数要求是无符号整型,所以需要强制类型转换
(感兴趣的也可以去网上查,这里用的网址是www.cplusplus.com)

这里有一个小问题,我们项目的要求是随机值要在1 ~ 100之间,而rand生成的随机数字范围是多大?

是0 ~ RAND_MAX,而RAND_MAX的值通常是32767

那怎么做到把这个范围变成1 ~ 100?

取模是个不错的选择

也就是让这个数字模上100,那么这个随机值的余数就是0 ~ 99,只需要再加上1,范围就变成了1 ~ 100,符合项目要求,beautiful!

之后,我们就可以在函数内部使用printf和scanf,提醒用户可以输入自己猜测的数字了,并用scanf函数接收用户输入的值

我们可以定义一个guess变量,存储用户猜测的数字,把rand的返回值存储到num变量里,然后使用if条件语句对guess和num进行大小比较判断,而我们想实现让“一直猜”的效果,就可以用while死循环来实现,猜对后break跳出即可

这里我的循环条件使用了Bool类型,使用别的当然也是可以的(布尔类型需要头文件<stdbool.h>)

逻辑如下:

#include<stdlib.h>#include<time.h>#include<stdbool.h>
voidgame(){srand((unsignedint)time(NULL));intguess=0;intnum=rand()%100+1;while(true){printf("请输入您要猜测的数字:");if(scanf("%d",&guess)!=1){while(getchar()!='\n');printf("输入非法,请输入有效数字!\n");continue;}if(guess>num){printf("猜大了\n");}elseif(guess<num){printf("猜小了\n");}else{printf("恭喜你,猜对了!\n");break;}}}

但这里也需要注意,time(NULL)的精度是秒,如果在同一秒内多次开始游戏,生成的随机数会完全一样,所以如果玩的人比较多的话,把srand放在main函数里是更好的

至此,我们的简易项目就圆满完成了


三.功能拓展

那我们这个项目能不能拓展一些功能呢?或者进行一些优化呢?

相信大家都有自己的想法,这里我就以“增加猜测次数限制功能”举例

我们怎么实现猜测次数限制呢?

首先game函数里的while循环条件要动吗?其实可以改,也可以不改
因为我们的代码逻辑是“一直猜,猜对了就break跳出循环”,如果不改的话,无非就是增加一个次数变量,在循环内部的开头判断一次,如果条件为真break跳出即可,这和改动循环条件为次数变量,归0时再判断本质上是一样的,我们这里就不进行改动了

由于次数限制可能是需要频繁被修改的,我们可以直接宏定义一个GUESS_TIMES,次数用这个宏定义去定义就可以了

当然,如果想在用户游戏失败后,告诉用户正确答案,也是可行的

这里我就直接展示代码了,逻辑如下:

#defineGUESS_TIMES5
voidgame(){srand((unsignedint)time(NULL));intleft=GUESS_TIMES;intguess=0;intnum=rand()%100+1;while(true){if(left==0){printf("很遗憾,%d次机会用完,您失败了!\n",GUESS_TIMES);printf("正确答案为:%d\n",num);break;}printf("请输入您要猜测的数字(您还有%d次机会):",left);if(scanf("%d",&guess)!=1){while(getchar()!='\n');printf("输入非法,请输入有效数字!\n");continue;}if(guess>num){printf("猜大了\n");left--;}elseif(guess<num){printf("猜小了\n");left--;}else{printf("恭喜你,猜对了!\n");break;}}}

至此,我们的代码优化也结束了

接下来是完整的.c代码:

#define_CRT_SECURE_NO_WARNINGS#defineGUESS_TIMES5#include<stdio.h>#include<stdlib.h>#include<time.h>#include<stdbool.h>voidgame(){srand((unsignedint)time(NULL));intleft=GUESS_TIMES;intguess=0;intnum=rand()%100+1;while(true){if(left==0){printf("很遗憾,%d次机会用完,您失败了!\n",GUESS_TIMES);printf("正确答案为:%d\n",num);break;}printf("请输入您要猜测的数字(您还有%d次机会):",left);if(scanf("%d",&guess)!=1){while(getchar()!='\n');printf("输入非法,请输入有效数字!\n");continue;}if(guess>num){printf("猜大了\n");left--;}elseif(guess<num){printf("猜小了\n");left--;}else{printf("恭喜你,猜对了!\n");break;}}}voidmenu(){printf("---------------------\n");printf("------猜数字游戏------\n");printf("-------1. play-------\n");printf("-------0. exit-------\n");printf("---------------------\n");}intmain(){intinput=0;do{menu();printf("请输入您要选择的数字:");if(scanf("%d",&input)!=1){while(getchar()!='\n');printf("输入非法,请输入有效数字!\n");continue;}switch(input){case1:game();break;case0:printf("退出游戏\n");break;default:printf("输入非法,请输入有效数字!\n");break;}}while(input);return0;}

代码虽然简单,但是也还是挺有趣的~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 16:10:55

Blockchain Solutions

Blockchain Solutions Blockchain技术以其独特的去中心化特性和数据不可篡改性&#xff0c;正在成为解决各种行业问题的关键技术。从金融到供应链管理&#xff0c;从医疗保健到版权保护&#xff0c;区块链解决方案正在改变我们处理数据和交易的方式。 在金融领域&#xff0c;区…

作者头像 李华
网站建设 2026/5/22 16:09:43

在ubuntu服务器上快速接入taotoken实现多模型api调用

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在Ubuntu服务器上快速接入Taotoken实现多模型API调用 对于在Ubuntu服务器上部署应用的开发者而言&#xff0c;快速集成大模型能力是…

作者头像 李华
网站建设 2026/5/22 16:09:42

3种简单方法免费解锁加密音乐:重新掌控你的数字音乐库

3种简单方法免费解锁加密音乐&#xff1a;重新掌控你的数字音乐库 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https…

作者头像 李华
网站建设 2026/5/22 16:09:42

3PEAK思瑞浦 TPA6581Q-S5TR-S SOT23-5 运算放大器

特性 符合AEC-Q100汽车应用标准-等级1:-40C至125CTA .供电电压:2.7V至5.5V 偏移电压:典型值为0.3mV 单位增益带宽:10MHz 峰值瞬态响应率:8V/us 低功耗:每通道1.2毫安 轨到轨输入和输出 低1/f噪声:1kHz时为10nV/vHz 开关电源时无显著输出抖动 -40C至125C工作温度范围

作者头像 李华
网站建设 2026/5/22 16:06:41

鸣潮自动化工具完整指南:3步实现智能后台挂机与高效刷取

鸣潮自动化工具完整指南&#xff1a;3步实现智能后台挂机与高效刷取 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves 还在为《鸣潮》…

作者头像 李华
网站建设 2026/5/22 16:05:45

Armv8/v9架构SCTLRMASK_EL2寄存器解析与应用

1. AArch64系统控制寄存器基础解析在Armv8/v9架构中&#xff0c;系统控制寄存器(System Control Registers)是处理器状态配置的核心组件&#xff0c;它们分布在不同的异常级别(EL0-EL3)&#xff0c;用于管理处理器行为、内存系统、安全状态等关键功能。这些寄存器通常通过MRS/M…

作者头像 李华