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

embedded/2025/2/4 2:53:56/

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

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/embedded/159351.html

相关文章

es6中关于let的使用以及案例,包括但不限于块级作用域,不允许重复声明,没有变量提升,暂存性死区,不与顶层对象挂钩

ES6 let 关键字完整指南 1. 块级作用域 1.1 let vs var 作用域对比 // var - 函数作用域 function varExample() {var x 1;if (true) {var x 2; // 同一个 xconsole.log(x); // 2}console.log(x); // 2 }// let - 块级作用域 function letExample() {let x 1;if (true…

Dubbo view

1、 说说Dubbo核心的配置有哪些&#xff1f; 答&#xff1a; 配置 配置说明 dubbo:service 服务配置 dubbo:reference 引用配置 dubbo:protocol 协议配置 dubbo:application 应用配置 dubbo:module 模块配置 dubbo:registry 注册中心配置 dubbo:monitor 监控中心配置 dubbo:pr…

【数据结构与算法】九大排序算法实现详解

文章目录 Ⅰ. 排序的概念及其运用一、排序的概念二、常见的排序算法三、排序算法的接口四、测试算法接口附&#xff1a;Swap接口&#xff08;使用异或的方法实现&#xff09; Ⅱ. 排序算法的实现一、插入排序二、希尔排序( 缩小增量排序 )三、选择排序四、堆排序五、冒泡排序六…

C++中的析构器(Destructor)(也称为析构函数)

在C中&#xff0c;析构器&#xff08;Destructor&#xff09;也称为析构函数&#xff0c;它是一种特殊的成员函数&#xff0c;用于在对象销毁时进行资源清理工作。以下是关于C析构器的详细介绍&#xff1a; 析构函数的特点 名称与类名相同&#xff0c;但前面有一个波浪号 ~&a…

第二篇:多模态技术突破——DeepSeek如何重构AI的感知与认知边界

——从跨模态对齐到因果推理的工程化实践 在AI技术从单一模态向多模态跃迁的关键阶段&#xff0c;DeepSeek通过自研的多模态融合框架&#xff0c;在视觉-语言-语音的联合理解与生成领域实现系统性突破。本文将从技术实现层面&#xff0c;解构其跨模态表征学习、动态融合机制与…

计算机网络部分知识点(王道考研笔记)

计算机网络体系结构&#xff08;概念、框架&#xff09;&#xff08;选择填空题&#xff09; 什么是计算机网络&#xff1f; 计算机网络的概念&#xff1a;计算机网络是一个将众多分散的、自治的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软…

【LLM】DeepSeek-R1-Distill-Qwen-7B部署和open webui

note DeepSeek-R1-Distill-Qwen-7B 的测试效果很惊艳&#xff0c;CoT 过程可圈可点&#xff0c;25 年应该值得探索更多端侧的硬件机会。 文章目录 note一、下载 Ollama二、下载 Docker三、下载模型四、部署 open webui 一、下载 Ollama 访问 Ollama 的官方网站 https://ollam…

DeepSeek本地部署详细指南

DeepSeek本地部署详细指南 随着人工智能技术的飞速发展&#xff0c;本地部署大模型的需求也日益增加。DeepSeek作为一款开源且性能强大的大语言模型&#xff0c;提供了灵活的本地部署方案&#xff0c;让用户能够在本地环境中高效运行模型&#xff0c;同时保护数据隐私。以下是…