C语言--分支循环实践:猜数字游戏

server/2025/2/4 19:07:40/

在这次的实践项目中,需要编写一个可以在控制台运行的猜数字的游戏

1. 游戏要求

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

2. 游戏设计思路

2.1 游戏界面

首先设置一个菜单让玩家可以自行选择是否进入游戏,对于菜单部分只需要使用基本的printf函数根据自己的想法打印出菜单即可。

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

2.2 随机数的生成

要想完成猜数字的游戏首先要生成随机数,所以以下随机数的生成部分是本次实践的重点部分。

2.2.1 rand

C语言提供了一个函数叫做rand,这个函数是可以生成随机数的,函数原型如下所示:

int rand (void);

rand函数会返回一个伪随机数,这个随机数的范围是在0 ~ RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是大部分编译器上是32767。

rand函数的使用需要包含一个头文件:stdlib.h

下面是在VS中调用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;
}

其中运行两次的结果如下:

在这里插入图片描述

可以看到虽然一次运行中产生的5个数字是相对随机的,但是下一次运行程序生成的结果和上一次是一摸一样的这就说明是有一定问题的。

这是因为其rand函数生成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法生成的随机数。真正的随机数是无法预测下一个值是多少的。而rand函数就是对一个叫做 **“种子”**的基准值进行运算生成的随机数。

之所以前面每次运行程序产生的随机数序列是一样的,那是因为rand函数生成的随机数默认种子是1 。所以要生成不同的随机数,就要让种子是变化的。

2.2.2 srand

C语言中又提供了一个函数srand,用来初始化随机数的生成器的,srand函数的原型如下:

void srand (unsigned int seed);

程序中调用rand函数之前先调用srand函数的参数seed来设置rand函数生成随机数的时候的种子,只要种子在变化,每次生成的随机数序列也就变化起来了。

那也就是说给srand的种子是如果是随机的,rand就能生成随机数;在生成随机数的时候又需要一个随机数,这就矛盾了。

2.2.3 time

在程序中我们的一般使用程序运行的时间作为种子,因为时间是时刻发生变化的。

在C语言中有一个函数叫做time,可以获得这个时间,time函数原型如下:

time_t time (time_t* timer)

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

time函数的参数timer如果是非NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。

如果timer是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:[时间戳](时间戳(Unix timestamp)转换工具 - 在线工具)。

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

//VS2022 上time_t类型的说明 #ifndef _CRT_NO_TIME_T#ifdef _USE_32BIT_TIME_Ttypedef __time32_t time_t;#elsetypedef __time64_t time_t;#endif
#endiftypedef long 				__time32_t;
typedef __int64 			__time64_t;

如果只是让time函数返回时间戳,可以这样写

time (NULL);//调用time函数返回时间戳,这里没有接收返回值

现在可以将上面生成随机数的代码改写成如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main()
{//使用time函数的返回值设置种⼦ //因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换 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;
}

运行结果:

在这里插入图片描述

srand函数是不需要频繁调用的,一次运行的程序中调用一次就够了。

5.2.2.5 设置随机数的范围

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

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

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

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

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

100 + rand() % (200 - 100 + 1);
//余数的范围是0~100,加100之后就是100~200

如果要生成a~b之间的随机数

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

5.2.3 游戏过程中的实现

游戏中的核心是利用分支循环语句实现每次玩家输进去的值都和利用rand函数获取的随机数进行比较,再对三种情况分别在对应的分支语句中输出想要展示给玩家的信息。

同时还可以在游戏开始之前,询问玩家想要猜数字的次数,可以增加游戏难度和趣味性,并在每猜一次再把剩下的次数返回给玩家。

5.3 代码部分

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <stdlib.h>
#include <time.h>void game()
{int r = rand() % 100 + 1;				//生成0~100的随机数int guess = 0;							//用于存储玩家猜测的数字int count = 0;							//规定猜数字的次数printf("请选择你猜数字的次数:");		//玩家自定义猜数字的字数,并在每次游戏开始的时候都有一次机会选择scanf("%d", &count);do{	printf("请猜数字:");scanf("%d", &guess);if (guess < r){printf("猜小了\n");count--;printf("你还有%d次机会\n", count);}else if (guess > r){printf("猜大了\n");count--;printf("你还有%d次机会\n", count);}else{printf("恭喜你猜对了\n");break; }} while (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();scanf("%d", &input);switch (input)							//对玩家选择的不同模式进行分支处理{case 1:game();break;case 0:printf("游戏结束,请重新选择");break;default:printf("选择错误请重新选择");break;}} while (input);return 0;
}

http://www.ppmy.cn/server/164952.html

相关文章

python算法和数据结构刷题[1]:数组、矩阵、字符串

一画图二伪代码三写代码 LeetCode必刷100题&#xff1a;一份来自面试官的算法地图&#xff08;题解持续更新中&#xff09;-CSDN博客 算法通关手册&#xff08;LeetCode&#xff09; | 算法通关手册&#xff08;LeetCode&#xff09; (itcharge.cn) 面试经典 150 题 - 学习计…

2025年2月2日(tcp3次握手4次挥手)

TCP&#xff08;三次握手和四次挥手&#xff09;是建立和关闭网络连接的标准过程&#xff0c;确保数据在传输过程中可靠无误。下面是详细解释&#xff1a; 1. 三次握手&#xff08;TCP连接建立过程&#xff09; 三次握手是为了在客户端和服务器之间建立一个可靠的连接&#x…

html中的列表元素

列表元素分为无序列表ul&#xff08;unordered list&#xff09;、有序列表和定义列表 用ul定义无序列表&#xff0c;用li定义列表项。ul标签支持全局标准属性和全局事件属性 无序列表的特点&#xff1a; 列表项目作为一个整体&#xff0c;与上下文段落各有一行空白&#xff…

python渗透开发 高阶段位之 waf绕过sql注入 sqlmap --temper模块开发以及框架逻辑修改 以及解释Temper是什么?

目录 temper 解释: 这种操作常见于以下场景&#xff1a; 常见用法: tamper脚本位置 SQLMAP之temper二次开发说明 如何开发 temper 中的 Python 文件 基本的 temper Python 脚本结构 代码结构: 解释: 二次开发Temper中 base64encode.py 脚本 源码 编码前解释 二次框…

初始JavaEE篇 —— Spring Web MVC入门(上)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 RequestMappingg 注解介绍 Postman的介绍与使用 PostMapping 与 GetMapping 注解 构造并接收请求 接收简单参数 接收对象…

【Linux】使用VirtualBox部署Linux虚拟机

1. 下载并安装 VirtualBox 访问 VirtualBox 官网&#xff0c;下载适合你操作系统的版本&#xff08;Windows&#xff09;。安装 VirtualBox&#xff0c;按照安装向导的提示完成安装。 2. 下载 Linux 发行版 ISO 文件 访问你选择的 Linux 发行版官方网站&#xff08;例如&…

算法设计-0-1背包动态规划(C++)

一、问题阐述 0-1 背包问题的目标是在给定背包容量 W 的情况下&#xff0c;从 n 个物品中选择一些物品放入背包&#xff0c;使得背包中物品的总价值最大。每个物品只能选择一次&#xff08;即要么放入背包&#xff0c;要么不放入&#xff09;。 二、代码 #include <iostr…

【C++】string类(上):string类的常用接口介绍

文章目录 前言一、C中设计string类的意义二、string类的常用接口说明1. string类对象的常见构造2. string类对象的容量操作2.1 size、capacity 和 empty的使用2.2 clear的使用2.3 reserve的使用2.4 resize的使用 3. string类对象的访问及遍历操作3.1 下标[ ] 和 at3.2 迭代器it…