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

news/2025/2/3 11:37:49/

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

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/news/1568941.html

相关文章

JVM运行时数据区域-附面试题

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域 有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直存在&#xff0c;有些区域则是 依赖用户线程的启动和结束而建立和销毁。 1. 程序计…

C++11—右值引用

目录 简介 左值和右值 左值 右值 右值引用 生命周期 引用折叠 实际应用 移动语义 移动构造函数 移动赋值运算符 完美转发 简介 之前我们曾学习过引用叫左值引用&#xff0c;但那是C98的&#xff0c;在C11中新增了一种引用叫右值引用。右值引用主要用于支持移动语…

LeetCode:474.一和零

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;474.一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度…

【赵渝强老师】K8s中Pod探针的TCPSocketAction

在K8s集群中&#xff0c;当Pod处于运行状态时&#xff0c;kubelet通过使用探针&#xff08;Probe&#xff09;对容器的健康状态执行检查和诊断。K8s支持三种不同类型的探针&#xff0c;分别是&#xff1a;livenessProbe&#xff08;存活探针&#xff09;、readinessProbe&#…

《LLM大语言模型+RAG实战+Langchain+ChatGLM-4+Transformer》

文章目录 Langchain的定义Langchain的组成三个核心组件实现整个核心组成部分 为什么要使用LangchainLangchain的底层原理Langchain实战操作LangSmithLangChain调用LLM安装openAI库-国内镜像源代码运行结果小结 使用Langchain的提示模板部署Langchain程序安装langserve代码请求格…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.4 索引优化:避免意外复制的高效技巧

2.4 索引优化&#xff1a;避免意外复制的高效技巧 目录/提纲 #mermaid-svg-hmMAIqF8kFh46fbH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hmMAIqF8kFh46fbH .error-icon{fill:#552222;}#mermaid-svg-hmMAIqF8kF…

深度学习查漏补缺:2. 三个指标和注意力机制

一、bachsize, num_epochs, dataset 在训练卷积神经网络&#xff08;CNN&#xff09;或任何其他深度学习模型时&#xff0c;有几个关键参数和概念需要了解&#xff1a;batch size、num epochs 和 dataset。下面是对它们的详细解释&#xff1a; Batch Size&#xff08;批量大小&…

设计模式Python版 抽象工厂模式

文章目录 前言一、抽象工厂模式二、抽象工厂模式示例三、抽象工厂模式在Django框架中的应用 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结…