当前位置: 首页 > article >正文

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

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

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_T
 		typedef __time32_t time_t;
	#else
 	typedef __time64_t time_t;
 	#endif
#endif

typedef 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.kler.cn/a/519046.html

相关文章:

  • Oracle查看数据库表空间使用情况
  • 代码随想录算法训练营day31(补0124)
  • 基于模糊PID的孵化箱温度控制系统(论文+源码)
  • 做Midjourney最好图文教程-提示词公式以及高级参数讲解
  • RabbitMQ 死信队列
  • 【高项】6.3 排列活动顺序 ITTO
  • cuda reductionreduce
  • 如何使用 SQL CREATE TABLE 创建一个表
  • 【机器学习】自定义数据集使用scikit-learn中的包实现线性回归方法对其进行拟合
  • 浅谈贪心算法
  • 【PySide6快速入门】PySide6构建Qt项目
  • Java Web-Request与Response
  • Spring MVC (三) —— 实战演练
  • 什么是Pytest Fixtures作用域及如何为Pytest Fixtures设置合适的作用域
  • Arduino大师练成手册 -- PCF8574T I2C控制LCD1602
  • 【云安全】云原生-Docker(五)容器逃逸之漏洞利用
  • GMP底层
  • Web3 与数据隐私:如何让用户掌控个人信息
  • Vue组件开发-使用 html2canvas 和 jspdf 库实现PDF文件导出 设置页面大小及方向
  • 国自然数学与医疗健康交叉重点专项|基于多组学大数据的鼻咽癌个体化临床智能决策算法与支持系统|基金申请·25-01-23
  • 导航的 “精确之误“:道路拥堵的 SPF 成因与解决
  • 如何跨互联网adb连接到远程手机-蓝牙电话集中维护
  • 深度学习|表示学习|卷积神经网络|离散卷积的操作详细|10
  • DBSCAN密度聚类
  • 批量创建ES索引
  • 【Rust自学】14.5. cargo工作空间(Workspace)