有趣的代码——猜数字游戏的实现

前面介绍过很多的C语言常识,但是我们都知道“兴趣是最好的老师”,所以,今天我们用之前讲过的一些知识,加上部分新补充的知识点,写一个“猜数字”的小游戏,来丰富我们的编程学习生活,感受来自C语言的趣味性。

目录

1.猜数字游戏的大致流程

2.游戏实现的思路

3.随机数生成

3.1rand

3.2srand

3.3time

3.4随机数范围设置

4.猜数字游戏的代码实现

5.猜数字游戏的优化


1.猜数字游戏的大致流程

首先由计算机产生一个随机数,并给出这个随机数所在的区间,然后由玩家来猜测这个数,如果玩家猜中这个数,则显示成功并结束本轮游戏,如果猜测次数超过8次,则显示猜测失败并结束本轮游戏。

2.游戏实现的思路

我们在写编程题或者小游戏代码时,最重要的就是理清思路——主体是什么?为了实现目的要创建哪些函数?函数的功能都是什么?只有当我们心中有了一个大体的框架,知道该做些什么时,我们才能更高效地编写代码,完成程序设计。

猜数字游戏的算法如下:

1.提供游戏菜单,由玩家选择是否进行游戏:按“1”开始游戏,按“0”推出游戏,按其他则显示“选择错误,请重新选择”。

2.开始游戏后,先初始化猜测次数count = 0;

3.重复执行下述操作,直到count达到8次:

        3.1玩家输入一个数guess(进行猜测);

        3.2count++;

        3.2如果guess等于secret(计算机产生的随机数),跳出循环;否则显示“错了,请重新猜!你还有8-count次猜测次数,请把握好机会!”

4.如果count达到8次,则显示“超过次数,游戏结束!”;否则,显示“恭喜,猜对了!共猜测count次!”

如上面所示,这就是猜数字游戏大体框架的算法呈现。

我们在思考大体框架时不用过多在意具体函数的实现方法,可以先起个能表达其功能的函数名并把它放在需要的位置。(说白了就是先搞一个空壳函数占位置,等到大体框架调试完毕不再有问题后,再去实现这些空壳函数)大体框架代码如下:

#iclude<stdio.h>

int main()
{
    int secret;//随机数怎么建立呢?我们好像暂时也不清楚,那么就先假设一个空壳的,不用在意它。
    int input;
    do
    {    //menu函数在调试大体框架时,也可以是空壳函数
         menu();//打印游戏菜单。我们建立函数可以让主函数不至于太过冗长,而且增加了代码的可读性,使程序模块化。
         printf("请选择:>");
         scanf("%d", &input);
         switch(input)
         {
             case 1:
                 guess(secret);//guess是用来猜测并判断是否正确的函数,这里也是空壳函数
                 break;
             case 0:
                 printf("游戏结束\n");
                 break;
             default:
                 printf("选择错误,请重新选择\n");
                 break;
           }
     }while(input);
     return 0;
}

上面的guess函数就是个空壳函数,我们可以在把主体框架完成后再去实现。而guess函数的功能就是:

①guess(玩家猜测数)= secret,则显示“恭喜,猜对了!同猜测count次!”;

②guess(玩家猜测数)!= secret,则显示“错了,请重新猜!你还有8-count次猜测机会,请把握好机会!”

guess函数的代码实现如下:

void guess(int secret)
{
     int guess= 0, count = 0;
     do
     {
         printf("请输入一个整数>:");
         scanf("%d", &guess);
         count++;
         if(guess == secret) break;
         else pritnf("错了,请重新猜!你还有%d猜测次数,请把握好机会\n",8-count);
     }while(count<8);

     if(count < 8)
         printf("恭喜,猜对了!共猜测%d次!\n",count);
     else
         printf("超过次数,游戏结束!\n");
     
}

menu函数的代码实现如下:

void menu()
{
     printf("***********************\n");
     printf("****** 1. play ******\n");
     printf("****** 0. exit ******\n");
     printf("***********************\n");
}
3.随机数生成

上面我们已经把大体框架和空壳函数都实现,按照正常情况我们的代码已经完成了,只需要调试使其能正常运行即可,但是在这个游戏中我们还需要补充一个新的知识点——随机数的生成。

3.1rand

C语言提供了随机数生成函数rand,该函数返回0~RAND_MAX的一个随机整数,RAND_MAX是在头文件stdlib.h中定义的符号常量,其值与机器字长和编程环境有关,一般为2^15-1或2^31-1。

rand函数原型为:

int rand (void);

#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。 如果要生成不同的随机数,就要让种子是变化的。

3.2srand

C语言提供了库函数srand初始化随机种子,例如可以调用库函数time得到当前的系统时间,将当前系统时间作为随机种子。

srand函数的原型为:

void srand (unsigned int seed);

程序中在调用rand函数之前先调用srand函数,通过srand函数的参数seed来设置rand函数生成随 机数的时候的种子,只要种子在变化,每次生成的随机数序列也就变化起来了。那也就是说给srand的种子是如果是随机的,rand就能生成随机数;在生成随机数的时候又需要一个随机数,这就矛盾了,该怎么解决呢? 

3.3time

C语言提供一个函数time,用来获得系统时间。

time函数的原型为:

time_t time (time_t* timer);

time函数会返回当前的日历时间,其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位是秒。返回的类型是time_t类型的,time_t 类型本质上其实就是32位或者64位的整型类型 。

time函数的时候需要包含头文件:time.h

综合上面三个函数及介绍,则随机数生成代码实现为:

srand((unsigned int)time(NULL));//初始化随机种子
rand( );//产生随机数
3.4随机数范围设置

既然是随机数,那么就会从0~RAND_MAX中随机生成一个数字,那我们能猜对吗?😀答案是显然的,别说是八次机会,就是八十次都不一定能猜对。所以,为了照顾玩家的游戏体验,我们也必须设置随机数的范围,让它更为科学和合理。

如果我们要生成0~99之间的随机数,方法如下:

rand() %100;//余数的范围是0~99

如果我们要生成1~100之间的随机数,方法如下:

rand()%100+1;//%100的余数是0~99,0~99的数字+1,范围是1~100

 如果我们要生成a~b之间的随机数,方法如下:

a + rand()%(b-a+1)

4.猜数字游戏的代码实现

前面的准备工作已经做完了,那么就整合所有模块,一起来见证我们努力的成果吧!

#include<stdio.h>
#include <stdlib.h>
#include <time.h>//记得检查所需的函数头文件都引用没有哦 

void menu()
{
     printf("***********************\n");
     printf("****** 1. play ******\n");
     printf("****** 0. exit ******\n");
     printf("***********************\n");
}

void guess(int secret)
{
     int guess = 0, count = 0;
     do
     {
         printf("请输入一个整数>:");
         scanf("%d", &guess);
         count++;
         if(guess == secret) break;
         else printf("错了,请重新猜!你还有%d猜测次数,请把握好机会\n\n",8-count);
     }while(count<8);

     if(count < 8)
         printf("恭喜,猜对了!共猜测%d次!\n",count);
     else
         printf("超过次数,游戏结束!\n");
     
}

int main()
{
	srand((unsigned int)time(NULL));
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {    
    	int secret = rand() %100;//生成0~99之间的随机数 
		//menu函数在调试大体框架时,也可以是空壳函数
         menu();//打印游戏菜单。我们建立函数可以让主函数不至于太过冗长,而且增加了代码的可读性,使程序模块化。
         printf("请选择:>");
         scanf("%d", &input);
         switch(input)
         {
             case 1:
                 guess(secret);//guess是用来猜测并判断是否正确的函数,这里也是空壳函数
                 break;
             case 0:
                 printf("游戏结束\n");
                 break;
             default:
                 printf("选择错误,请重新选择\n");
                 break;
           }
     }while(input);
     return 0;
}

上面的代码进行了细微的调整——把rand的随机种子初始化放在do之前,然后把随机数的生成放在do…while语句中,这样我们每一轮游戏所猜的数字都是不同的,且不必重复初始化随机种子。

5.猜数字游戏的优化

我们玩几局就会发现,虽然限制了随机数的范围,但想在8次机会中猜对还是有些难度,所以为了我们亲爱的玩家,我们就再降低难度——当他们猜完数字后,给他们提示:“猜大了”或者“猜小了”

优化后的代码如下:

#include<stdio.h>
#include <stdlib.h>
#include <time.h>//记得检查所需的函数头文件都引用没有哦 

void menu()
{
     printf("***********************\n");
     printf("****** 1. play ******\n");
     printf("****** 0. exit ******\n");
     printf("***********************\n");
}

void guess(int secret)
{
     int guess = 0, count = 0;
     do
     {
         printf("请输入一个整数>:");
         scanf("%d", &guess);
         count++;
         if(guess == secret) 
		 	break;
         else if(guess > secret)
         {
         	if(count != 8) 
		 		printf("猜大了,请重新猜!你还有%d猜测次数,请把握好机会\n\n",8-count);
		 	else 
		 		printf("可惜最后还是猜大了\n");
		 }	
		 else
		 {
         	if(count != 8) 
		 		printf("猜小了,请重新猜!你还有%d猜测次数,请把握好机会\n\n",8-count);
		 	else 
		 		printf("可惜最后还是猜小了\n");
		 }
     }while(count<8);

     if(count < 8)
         printf("恭喜,猜对了!共猜测%d次!\n",count);
     else
         printf("不好意思,次数已用完,游戏结束!\n");
     
}

int main()
{
	srand((unsigned int)time(NULL));
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {    
    	int secret = rand() %100;//生成0~99之间的随机数 
		//menu函数在调试大体框架时,也可以是空壳函数
         menu();//打印游戏菜单。我们建立函数可以让主函数不至于太过冗长,而且增加了代码的可读性,使程序模块化。
         printf("请选择:>");
         scanf("%d", &input);
         switch(input)
         {
             case 1:
                 guess(secret);//guess是用来猜测并判断是否正确的函数,这里也是空壳函数
                 break;
             case 0:
                 printf("游戏结束\n");
                 break;
             default:
                 printf("选择错误,请重新选择\n");
                 break;
           }
     }while(input);
     return 0;
}

猜数字小游戏到这里算是结束喽,不知道大家学习的过程辛苦不辛苦,反正我是痛并快乐着的🙂🙂🙂

关于猜数字的更多玩法和可能性,就全权交由聪明的大家了。当然大家有啥好想法又不想一个人搞的,也可以在评论区发出来,大家一起交流交流,研究研究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/197207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【小布_ORACLE】Part11-1--RMAN Backups笔记

Oracle的数据备份于恢复RMAN Backups 学习第11章需要掌握&#xff1a; 一.RMAN的备份类型 二.使用backup命令创建备份集 三.创建备份文件 四.备份归档日志文件 五.使用RMAN的copy命令创建镜像拷贝 文章目录 Oracle的数据备份于恢复RMAN Backups1.RMAN Backup Concepts&#x…

云原生系列Go语言篇-编写测试Part 1

本文来自正在规划的​​Go语言&云原生自我提升系列​​&#xff0c;欢迎关注后续文章。 2000年以来&#xff0c;自动化测试的广泛应用可能比任何其他软件工程技术都更能提高代码质量。Go是一种专注于提高软件质量的语言和生态系统&#xff0c;很自然的在其标准库中包含了测…

《2023全球隐私计算报告》正式发布!

2023全球隐私计算报告 1、2023全球隐私计算图谱2、国内外隐私计算相关政策3、隐私计算技术的最新发展4、隐私计算技术的合规挑战5、隐私计算的应用市场动态6、隐私计算开源整体趋势7、隐私计算的未来趋势 11月23日&#xff0c;由浙江省人民政府、商务部共同主办&#xff0c;杭州…

Appium自动化如果出现报错怎么办?这么做确实解决问题

解决通过appium的inspector功能无法启动app的原因 在打开appium-desktop程序&#xff0c;点击inspector功能&#xff0c;填写app的配置信息&#xff0c;启动服务提示如下&#xff1a; 报错信息&#xff1a; An unknown server-side error occurred while processing the com…

牛客 算法题 记负均正II golang实现

题目 HJ105 记负均正II golang 实现 package mainimport ("bufio""fmt""io""os""strconv""strings" )func main() {scanner : bufio.NewScanner(os.Stdin)nums:make([]int,0)sum:0minus:0for scanner.Scan() {l…

java开发需要掌握的maven相关知识和Junit单元测试

maven简介 什么是maven&#xff1a; maven是一款管理和构建java项目的工具&#xff0c;是apache旗下的一个开源项目。 maven的作用&#xff1a; 依赖管理&#xff1a; 方便快捷的管理项目依赖的资源&#xff08;jar包&#xff09;。 项目构建&#xff1a; 标准化的跨平台&#…

20 章 多线程

20.1线程简介. 20.2创建线程 2.1继承Thread类 Thread 类是java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立Thread 实例。Thread类中常用的两个构造方法如下: public Thread():创建一个新的线程对象。 public Thre…

【LeetCode】128. 最长连续序列——哈希的应用(3)

文章目录 1、思路2、解题方法3、复杂度时间复杂度:空间复杂度: 4、Code Problem: 128. 最长连续序列 1、思路 我会用一种做题者的思路来去看待这道题。 我们在乍一看到这道题的时候&#xff0c;看到它的时间复杂度要求为O(N)&#xff0c;然后又要求去找序列(就是让你判断这个…

stm32 TIM

一、TIM简介 TIM&#xff08;Timer&#xff09;定时器定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断。16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计数时钟下可以实现最大59.65s的定时定时器不仅具备基本的定时中断功能&…

前端 | iframe框架标签应用

文章目录 &#x1f4da;嵌入方式&#x1f4da;图表加载显示&#x1f4da;100%嵌入及滑动条问题&#x1f4da;加载动画保留 前情提要&#xff1a; 计划用iframe把画好的home1.html&#xff08;echarts各种图表组成的html数据大屏&#xff09;嵌入整合到index.html&#xff08;搭…

只需十分钟快速入门Python,快速了解基础内容学习。零基础小白入门适用。

文章目录 简介特点搭建开发环境版本hello world注释文件类型变量常量数据类型运算符和表达式控制语句数组相关函数相关字符串相关文件处理对象和类连接mysql关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源…

摇滚史密斯2014重置版外接声卡

摇滚史密斯2014重置版外接声卡 前提 由于rs_asio是通过模拟原厂线的方法来使游戏可以支持声卡的&#xff0c;因此&#xff0c;声卡的采样频率需要满足原厂线要求&#xff0c;即采样率可以设置为 48000 Hz。 我使用的是 Sonic Cube 这款声卡&#xff0c;非常幸运&#xff0c;…

汽车电子 -- 车载ADAS之FCW(前方碰撞预警)

相关法规文件: FCW: GB∕T 33577-2017 智能运输系统 车辆前向碰撞预警系统 性能要求和测试规程 一、前方碰撞预警 FCW&#xff08; Forward Collision Warning&#xff09; 参看&#xff1a;法规标准-GB/T 33577标准解读(2017版) 1、状态机 系统关闭 当车辆前向碰撞预警系…

unity学习笔记07

一、组件 有几个物体他们之间有着重复的功能&#xff0c;该如何避免重复的去写代码&#xff1f; 可以将一些相同的功能写成一个组件&#xff0c;也就是组件就等同于功能。 什么是组件&#xff1f; 在Unity中&#xff0c;游戏物体是不具备任何功能的&#xff0c;如果想要为其…

香港科技大学数据建模(MSc DDM)硕士学位项目(2024年秋季入学)招生宣讲会-武汉专场

时间&#xff1a;2023 年12 月 8 日&#xff08;周五&#xff09; 15:00 地点&#xff1a;华中科技大学大学生活动中心B座303 嘉宾教授&#xff1a;张锐 教授 项目旨在培养科学或工程背景的学员从数据中提取信息的数据建模能力&#xff0c;训练其拥有优秀的解难和逻辑思考与分…

3.OpenResty系列之Nginx反向代理

1. Nginx简介 Nginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器 什么是反向代理&#xff1f; 反向代理&#xff08;Reverse Proxy&#xff09;方式是指以代理服务器来接受 internet 上的连接请求&#x…

金山办公前端二面

1. react 和 vue的区别 还有jquery&#xff1f; &#xff08;1&#xff09; jquery 和 vue、react 的区别&#xff1a; vue 和 react : 数据和视图分离 以数据驱动视图&#xff0c;只关心数据变化 dom 操作被封装&#xff08;数据驱动&#xff09; jquery&#xff1a;依靠 do…

python环境的搭建+pytharm安装教程

一、Anaconda安装 1、去官网下载anaconda >百度搜索anaconda按回车键 >找到官网地址进去&#xff08;注意看网址&#xff09; >下载位置 2、安装anaconda 具体就安装步骤就不演示了&#xff08;写文章时已经安装好了&#xff09; 二、pycharm安装 1、去官网下载py…

Redis 基本命令—— 超详细操作演示!!!

内存数据库 Redis7—— Redis 基本命令 三、Redis 基本命令&#xff08;下&#xff09;3.8 benchmark 测试工具3.9 简单动态字符串SDS3.10 集合的底层实现原理3.11 BitMap 操作命令3.12 HyperLogLog 操作命令3.13 Geospatial 操作命令3.14 发布/订阅命令3.15 Redis 事务 四、Re…

【C语言加油站】函数栈帧的创建与销毁 #保姆级讲解

函数栈帧的创建与销毁 导言一、计算机硬件1.冯•诺依曼机基本思想2.冯•诺依曼机的特点&#xff1a;3.存储器3.1 分类3.2 内存的工作方式3.3 内存的组成 4.寄存器4.1 基本含义4.2 寄存器的功能4.3 工作原理4.4 分类4.4.1 通用寄存器组AX(AH、AL)&#xff1a;累加器BX(BH、BL)&a…