【C语言】分支与循环(循环篇)——结尾猜数字游戏实现

news2025/1/24 22:52:41

前言

C语言是一种结构化的计算机语言,这里指的通常是顺序结构、选择结构、循环结构,掌握这三种结构之后我们就可以解决大多数问题。

分支结构可以使用ifswitch来实现,而循环可以使用forwhiledo while来实现。

1. while循环

C语言中提供了三种循环语句,while就是其中一种。

1.1 while 与 if 的对比

while的语法:

while(表达式)
	语句;

具体我们可以通过与if语句对比一下来观察:

//代码1
int main()
{
	if(1)
		printf("hello\n");
	return 0;
}
int main()
{
	while(1)
		printf("hello\n");
	return 0;
}

通过运行我们可以发现,if语句只能执行一次后面的打印语句,而while循环可以一直打印。

1.2 while语句的执行流程

在这里插入图片描述
首先执行判断表达式,如果表达式值为0(为假),循环直接结束;表达式的值不为0(为真),则执行循环语句,语句执行后再继续进行判断。

1.3 while循环实践

比如:循环打印1~10的值

int main()
{
	int i = 1;

	while (i <= 10)
	{
		printf("%d ", i);
		i++;
	}

	return 0;
}

在这里插入图片描述

2. for循环

通常for循环是循环中使用最多的,语法如下:

2.1 语法形式

for(表达式1; 表达式2; 表达式3)
	语句;

在这里表达式1用于初始化循环变量,表达式2用于循环结束条件的判断,表达式3用于循环变量的调整。

2.2 执行流程

在这里插入图片描述
进入循环首先执行表达式1初始化循环变量,然后执行表达式2进行判断,如果表达式2的结果为0,则 循环结束;表达式2不为0则执行循环语句,执行完成后,再执行表达式3调整循环变量,然后再进行表达式2判断。

整个循环中,表达式1的初始化部分只执行1次,接下来就是表达式2循环语句表达式3在循环。

2.3 for循环实践

还是以打印1~10的值为例:

int main()
{
	int i = 1;

	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}

	return 0;
}

在这里插入图片描述

3. do-while循环

3.1语法形式

一般do while循环使用的语句比较少,它的语法如下:

do
	语句;
while(表达式)

while 循环for循环都是先判断再进入循环,而do while循环是先进入循环体执行循环语句,再执行while后的判断表达式,表达式为真就进行下一次循环,为假则跳出不再循环。

3.2 执行流程

在这里插入图片描述

3.3 do while 循环的实践

这里我们还是以打印1~10的值为例:

int main()
{
	int i = 1;
	do
	{
		printf("%d ", i);
		i++;
	} while (i <= 10);

	return 0;
}

在这里插入图片描述

4. break和continue语句

在执行循环的时候,我们经常会遇到某些情况需要提前终止循环,而在C语言中提供了breakcontinue两个关键字:

  • break的作用是永久终止循环,只要break执行,那么就会直接跳出循环,执行当前循环外的语句。
  • continue的作用是跳过本次循环continue后边的代码,进行下一轮循环。

4.1 while循环中的break和continue语句

4.1.1 break举例

int main()
{
	int i = 1;

	while (i <= 10)
	{
		if (i == 8)
			break;
		
		printf("%d ", i);
		i++;
	}

	return 0;
}

这时我们再来看看结果:
在这里插入图片描述
这里我们可以看到,只打印到了7就停止了,这是因为i在等于8的时候就执行了break语句,直接跳出了整个循环,所以只打印到了7就停止。

4.1.2 continue举例

int main()
{
	int i = 1;

	while (i <= 10)
	{
		if (i == 8)
			continue;
		
		printf("%d ", i);
		i++;
	}

	return 0;
}

在这段代码中的结果是会造成死循环,因为continue的特点是跳过当次循环后的代码,所以当 i 循环一直到值为 8 的时候,就会跳过后面的 printf 和 i++ 语句,导致 i 的值一直为 8 ,造成程序死循环,所以要避免将 continue 放在调整语句之前。

4.2 for循环中的break和continue

4.2.1 break举例

和 while 循环一样, for 循环中的 break 也是用于终止循环,只要执行到了break循环就彻底终止:

int main()
{
	int i = 0;

	for (int i = 1; i <= 10; i++)
	{
		if (i == 8)
			break;
		printf("%d ", i);
	}

	return 0;
}

在这里插入图片描述
所以当 i 等于 8 的时候,break执行,跳出循环,结果打印1~7。

4.2.2 continue举例

如果把上面的代码中的break换成continue会什么结果:

int main()
{
	int i = 0;

	for (int i = 1; i <= 10; i++)
	{
		if (i == 8)
			continue;
		printf("%d ", i);
	}

	return 0;
}

在这里插入图片描述
这里打印了1~10,但是没有打印8,这是因为当 i == 8 的时候, continue执行跳过了打印的语句,但是调整语句 i++ 在continue之前,所以 i 继续自增,变成 9, 不满足 if 语句,跳过continue,继续执行printf语句,所以结果没有打印 8。

4.3 do while循环中的break和continue语句

do while 语句中的break和continue作用与 while 循环中几乎一样,这里不再叙述。

5. goto语句

C语言中还提供了一种方法,就是goto语句和跳转标号,它可以实现在同一个函数内跳转到设置好的标号处。

比如:

int main()
{
	printf("hello\n");
	goto next;
	printf("world\n");

next:

	printf("跳过了world的打印\n");
	return 0;
}

在这里插入图片描述
goto语句如果使用不好就会导致在函数内乱跳转;但也并非全是缺点,如果在多层循环代码中想要快速跳出,那么使用goto就会很方便:

for(...)
{
	for(...)
	{
		for(...)
		{
			if(表达式)
				goto next;
		}
	}
}
next:

如果我们使用break的话,一次只能跳出一层循环,想全部跳出需要3个break,但使用goto的话,满足条件直接跳出所有循环,就会更加快捷。

6. 猜数字游戏

当我们了解了分支与循环的结构之后,就可以尝试着写一个猜数字的小游戏,在控制台展示出来:

不过,在写之前我们还要先了解几个函数,因为在游戏里我们会用到它们:

6.1 rand、srand、time函数与随机数

6.1.1 rand函数

在写程序的时候,有很多时候需要用到随机数,于是我们就可以使用rand函数。如下所示:

int rand(void);

注:在使用rand函数时需要包含头文件

#include <stdlib.h>

但通过程序多试几次发现,rand函数实际上生成的是一个伪随机数,每次生成的数字都是一样的:
第一次:
在这里插入图片描述

第二次:
在这里插入图片描述
伪随机数并不是真的随机数,而rand函数生成的是基于一个叫种子的基准值进行运算从而生成的随机数。
之所以每次生成的随机数都是一样的,是因为种子的默认值为“1”。
如果想生成真正的随机数,那么就需要种子是一直变化的。

6.1.2 srand函数

C语言中又提供了一个函数叫srand,是用来初始化随机数生成器的。

void srand(unsigned int seed);

在调用rand函数前先调用srand函数,用过srand的参数设置rand函数的种子,这样每次生成的随机数就会变化。

6.1.3 time函数

而一般在写程序的时候,大多数时候都会使用时间做为种子,因为时间是一直在变化的。
在C语言中有一个函数叫time,可以返回当前的时间:

time_t time (time_t* timer);

使用time函数需要包含头文件:

#include <time.h>

如果只用time函数返回时间戳,那就可以写成:

time(NULL);

6.1.4 生成随机数

了解了这些这时就可以把代码改下:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main()
{
	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;
}

这时再看得到的结果:
第一次:
在这里插入图片描述
第二次:
在这里插入图片描述
这时得到的就是真正的随机数

6.2 代码实现

游戏要求:

  1. 自动生成1~100的随机数
  2. 根据玩家猜的数字电脑给出大了或者小了的反馈,直到正确。
//打印开始界面
void menu()
{
	printf("************************\n");
	printf("*******猜数字游戏********\n");
	printf("*********1.开始*********\n");
	printf("*********0.退出*********\n");
	printf("************************\n");
}

//游戏主体
void game()
{
	//生成随机数,设定范围1~100以内
	int r = rand() % 100 + 1;
	//玩家要猜的数字
	int num = 0;

	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &num);

		if (num > r)
		{
			printf("猜大了\n");
		}
		else if (num < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了!\n");
			break;
		}
	}
}

int main()
{
	//用于选择开始游戏、退出游戏
	int input = 0;
	//设置种子,为了后面调用rand函数
	srand((unsigned int)time(NULL));

	do
	{
		//打印界面(封装为menu函数)
		menu();
		printf("请选择:");
		scanf("%d", &input);
		
		//根据玩家的输入来选择分支
		switch(input)
		{
		case 1:
			//游戏主体(封装为game函数)
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			//对于输入0和1之外的处理
			printf("选择错误,请重新选择\n");
			break;
		}
		

	} while (input);
	
	return 0;
}

6.3 逻辑分析

6.3.1 main()函数

  1. 首先进入main函数,因为游戏一开始就要打印一个菜单,所以我们使用do while循环,do while的特点就是第一次直接进入循环语句。
  2. 先打印菜单,然后使用scnaf让玩家输入,根据玩家输入的值选择switch的分支语句,如果输入 1 就进入case1语句,开始游戏;选择 0 那么就提醒玩家退出游戏,接着break跳出,如果输入非 01 的数字就走default语句提示重新选择。
  3. 使用input做为循环条件是因为,如果玩家输入 1 进入游戏之后,无论输赢导致游戏结束,都会再让玩家选择一次,也就是再打印一次菜单,再scanf输入选择,避免了游戏结束直接退出程序。而玩家输入0的话,整个循环也就随着停止,及退出游戏,如果输入其他的,只要是大于0就会提示重新选择,然后再次循环。

6.3.2 game()函数

  1. 如果玩家选择了1进入游戏主体,首先生成一个1~100的随机数并赋值给r
  2. 创建一个num变量用于玩家输入,并且因为猜数字很难一次猜对,所以输入的动作我们也放在循环里。
  3. while循环让他一直循环,内部就是一个比较的过程,根据玩家输入的数字走不通的分支并进行提示,直到猜对之后break跳出循环。

6.4 运行结果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[CP_AUTOSAR]_系统服务_DEM模块(三)功能规范之诊断事件定义

目录 1、诊断事件定义1.1、Event priority&#xff08;事件优先级&#xff09;1.2、Event occurrence&#xff08;事件发生计数器&#xff09;1.3、Event kind&#xff08;事件类别&#xff09;1.4、Event destination&#xff08;故障内存&#xff09;1.5、Diagnostic monitor…

2.MonggoDB是什么?

1. 不是什么&#xff1f; 要想知道MongoDB是什么&#xff0c;我们得先搞清楚它不是什么&#xff0c;首先它不是关系数据&#xff0c;不是像下面这样这种格式存储数据。 这个图展示了关系型数据库的常用存储方式&#xff0c;一个表格&#xff0c;里面存储了多行记录&#xff0…

Linux系统中的两个核心进程:`init`和`kthreadd`

文章目录 1 init 进程1.1 基本信息1.2 主要功能1.3 示例 2 kthreadd 进程2.1 基本信息2.2 主要功能2.3 示例 3 对比总结4 用户空间进程与内核线程4.1 用户空间进程特点 4.2 内核线程特点 5 对比总结6 结论参考链接封面 本文详细对比了Linux系统中的两个核心进程&#xff1a; i…

nvm 对node版本的控制

使用nvm切换Node.js版本的步骤如下 nvm list available // 显示可以安装的所有node.js的版本 如果出现空白 问题解决 经过查找nvm的文档&#xff0c;发现&#xff0c;对于中国用户而言&#xff0c;可以切换nodejs或npm的镜像地址来访问&#xff1a; nvm node_mirror https:…

软raid - - udev规则

一、什么是udev FROM AI: udev是Linux 2.6内核及以后版本中引入的一个设备管理框架&#xff0c;它取代了之前的devfs系统。udev以守护进程的形式运行&#xff0c;并且工作在用户空间而不是内核空间。它的主要功能是动态地创建和管理/dev目录下的设备节点&#xff0c;并且能够根…

SAP支出管理,企业成本控制的智能钥匙

在企业运营中&#xff0c;有效的支出管理是确保财务健康和提升竞争力的关键。SAP支出管理系统作为企业资源规划的核心组成部分&#xff0c;提供了一套全面的解决方案&#xff0c;帮助企业实现成本控制、风险管理和合规性监督。实现支出管理流程自动化&#xff0c;并主动管理更多…

蚂蚁笔试0511-编程题

解题思路&#xff1a; 记录0、正数、负数的个数&#xff0c;分类讨论。 解题思路&#xff1a; 有n个位置&#xff0c;每个位置有m个数&#xff0c;所以一共有m^n种情况&#xff0c;每种情况至少包含权值1&#xff0c;也就是全相等是一段&#xff0c;或者说是一个数形成的 从第二…

黑马Java零基础视频教程精华部分_11_面向对象进阶(3)

系列文章目录 文章目录 系列文章目录一、抽象类1、为什么要有抽象类&#xff1f;2、抽象方法3、抽象类4、抽象类和抽象方法定义格式5、注意事项 二、接口1、为什么会有接口&#xff1f;2、接口和抽象类的异同3、接口的定义和使用4、接口中成员的特点5、接口和类之间的关系6、实…

机器学习第五十周周报 CGNN

文章目录 week50 CGNN摘要Abstract0. 概述1. 题目2. Abstract3. 网络结构3.1 状态更新网络3.2 method 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程 5. 结论6.相关代码CompositeLGNNCompositeGNNcomposite-graph-class小结参考文献 week50 CGNN 摘要 本周阅读了题为Co…

【题解】189. 轮转数组(数组、数学、双指针)

https://leetcode.cn/problems/rotate-array/description/?envTypestudy-plan-v2&envIdtop-interview-150 class Solution { public:void rotate(vector<int>& nums, int k) {k k % nums.size(); // 注意k要取一下模reverse(nums.begin(), nums.end()-k);rev…

常见cms漏洞之ASPCMS

项目地址&#xff0c;自行百度 漏洞复现&#xff0c;使用后台配置文件拿shell 访问后台 http://192.168.177.153/admin_aspcms/login.asp 账号密码已设置成&#xff0c;登录即可 admin 123456

关于Win11无法自动进入休眠问题

最近从win10升到11了 感觉还挺好用的 就是右键有点逆天 主要是为了3k屏连接1080显示器更新的 但是发现彻底无法休眠了&#xff0c;这个还要说的是以前win10睡眠一次就算一次硬盘通电&#xff0c;现在更新后不会了 下面说回休眠 b站浏览一番后发现是22H2隐藏了休眠时间设置&a…

哈希 || unordered系列的关联式容器底层 | 哈希模拟实现 | HashTable代码实现

底层结构 unordered系统的关联式容器之所以效率比较高&#xff0c;是因为其底层使用了哈希结构。 哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须经过关键码的多次比较。 顺序查找的…

【机器学习算法基础】(基础机器学习课程)-10-逻辑回归-笔记

一、模型的保存与加载 逻辑回归是一种常见的机器学习算法&#xff0c;广泛用于分类问题。为了在不同的时间或环境下使用训练好的模型&#xff0c;我们通常需要将其保存和加载。 保存模型 训练模型&#xff1a;首先&#xff0c;你需要用你的数据训练一个逻辑回归模型。例如&…

【软考】甘特图

目录 1. 说明2. 图示3. 特点4. 例题4.1 例题1 1. 说明 1.Gantt图是一种简单的水平条形图,它以日历为基准描述项目任务。2.水平轴表示日历时间线(如时、天、周、月和年等)&#xff0c;每个条形表示一个任务&#xff0c;任务名称垂直地列在左边的列中&#xff0c;图中水平条的起…

猫头虎分享:从零开始掌握ChatGPT的实用技巧与多样应用

猫头虎分享&#xff1a;从零开始掌握ChatGPT的实用技巧与多样应用 ChatGPT使用方法与应用场景分享 大家好&#xff0c;我是猫头虎 &#x1f42f;&#xff0c;欢迎大家来到这次的分享课程。在这里&#xff0c;我们将深入了解ChatGPT的使用方法和应用场景。本文旨在帮助大家从零…

配置nacos显示nacos registry register finished但是nacos页面看不到服务

在idea配置按以下配置&#xff1a; 父工程&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2021.0.1.0</version><type>pom</type&…

内网权限维持——映像劫持CLR劫持

文章目录 一、映像劫持1.1 IFEO简介1.2 利用Shfit后门技术进行劫持1.3 GlobalFlag 二、CLR劫持2.1 CLR简介2.2 利用CLR探查器进行权限维持 攻击机kali IP&#xff1a;192.168.111.0 跳板机win7 IP&#xff1a;192.168.111.128&#xff0c;192.168.52.143 靶机win server 2008 I…

【开端】通过springboot框架创建对象

日常创建对象的方式 UserService userService new UserService() 这中方式创建对象&#xff0c;是程序运行中&#xff0c;才会创建的对象。在web中&#xff0c;我们需要再web服务器启动完成就创建一系列的对象。这是就可以把创建对象的任务交给spring的IOC框架。 例如创建U…

SOMEIP_ETS_003:数组长度过短导致有效载荷被剥离

测试目的&#xff1a; 确保DUT在接收到的SOME/IP消息中数组长度小于实际数组长度时&#xff0c;能够正确地截断负载数据至声明的数组长度。 描述 本测试用例旨在验证DUT在处理一个声明数组长度小于其实际长度的SOME/IP消息时&#xff0c;是否能够将响应消息的负载数据截断至…