C语言初阶猜数字游戏解析

1.游戏功能分析

  1. 电脑随机生成一个数
  2. 进行键盘输入数字猜测  
  3. 猜大了,提示猜大了,继续猜测
  4. 猜小了,提示猜小了,继续猜测
  5. 猜对了提示猜对了
  6. 选择退出或者继续再来一次 

2.游戏过程实现分析 

2.1 首先打印开始菜单

d257c3abd094470b9dd0d6fdf1852120.png

2.2利用Switch语句,执行用户选择的基本功能,出现游戏框架 

079eb6bd123f4d0a975a00a8d78eb3a5.png

2.3 游戏功能实现

2.3.1  电脑生成随机数 

我们查询发现rand()库函数可以生成一个随机数,于是:

345e0bbb19724ed2a6fbf7be8df74ba4.png

当我们使用rand函数的时候的确产生了随机值,但是当我再次运行代码,出现了这样的结果

b013b45cfc174dda8ba21c1147e2f03c.png

虽然rand函数产生了随机数,但是我们发现,第一次开始游戏和第二次开始游戏产生的数字是一样的。那这个就是一个bug,伪随机。比如:我玩过一次,我知道你再次进入游戏产生的数是多少,第二次就是18467,我直接猜就对了。(这里不是我没清理解决方案导致的错误,是因为rand函数用法错误,大家1可以试一下源码,接下来让我们看看rand函数的用法)

大家可以自己试一下错误源码的效果

#include<stdio.h>


//猜数字游戏实现
void menu()
{
	printf("******************************\n");
	printf("********* 1.play *************\n");
	printf("********* 0.exit *************\n");
	printf("******************************\n");
}

void game()
{
	//生成随机数
	int ret = rand();
	printf("%d\n", ret);
}

int main()
{
	//1.首先生成菜单
	//当客户玩完一句应该实现可以再次选择的功能或者用户输入错误可以再次输入的功能,所以这个使用 do while 循环来实现功能。
	int input = 0;
	do
	{


		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("游戏退出\n");
			break;
		default:
			printf("输入错误重新选择:\n");
			break;
		}
	} while (input);//当玩家选择0就是要退出游戏就直接出循环就行。

	return 0;
}

接下来让我们看看rand函数,学习一下,了解他的正确用法:

2.3.1.1 rand函数 

c698c9137c6344e59d27625859a68597.png

rand函数:产生一个从0到RAND_MAX的随机值

返回值 int

RAND_MAX       大家可以转到定义查看,这个是十进制数字32767

第三行:在使用rand之前,都必须使用srand函数来初始化一个随机数生成器。

所以这里就可以看出原来rand使用前必须调用一个srand函数来初始化一个随机数生成器,设置一个随机数生成器的起点。

那么srand函数又是什么样的呢,我们来看看

2.3.1.2 srand函数 

3da2ab05cf4c4aeab413fdf7c963b9c4.png

 1.无返回值

2.参数需要无符号整型

那么接下来我们就来修改代码

39968b8d9e2f43de8b055c9dbb140849.png

1b20dd38b5a1484fb4bbe0fc78eea4a5.png

又发现问题,由于srand参数类型是无符号整型,所以第一次我传入1,第二次我传入2,但是我们发现这样rand每次产生的数都是一样的,这是因为我传入srand函数里面的值如果是固定的值,那么初始化生成器就是固定的,导致rand函数每次产生一个固定的值。那么我们的srand就需要传入一个变化的值。这个变化的值从哪里去获取呢,我们注意到计算机上的时间是时刻变化的,刚好符合我们的变化值所需要的要求。接下来引入时间戳概念。

2.3.1.3 时间戳 time()函数

1.首先时间戳是什么:
849ea3ec42bb491cbb79c9b89f581af4.png

2.我们如何获得时间戳

time函数可以返回时间戳

c722a806502845f8ab3a7077f0bc171e.png

参数:time_t 类型的指针,这里不需要参数可以传空指针NULL

返回一个时间戳

time_t   这个类型实际是 long long 大家可以转到定义查看

但是我们的srand函数需要的是一个无符号整型所以使用的时候就需要强制转换一下。

看一下效果:

3033a9a0045b4a6bbe267a6119715a2b.png

达到了我们的要求,但是

1.我们不能每次猜数字都这么大,可以优化一下

 我们知道一个除数的余数是用于小于这个除数的

比如:

n%100  余数最大是99

所以我们想要控制一下产生的随机数不要太大

rand%100

 2.当我们在同一秒快速选择多次1,实际上产生的随机数是一样的。但是为了保证每次游戏只产生一个随机数,我们的srand函数调用一次就好,所以将它移到前面。

看一下优化后的整个代码效果如何:

15a3a1bf467a4861b36f6acf886b3f14.png

效果完美,接下来可以实现第二个功能了。

2.3.2 猜数字 

f6f721cc089e4ba49e8e149fb44cc549.png

这里的输入函数也要放到循环里才能实现循环输入哦。至此我们的猜数字游戏就完成了

附上源码大家可以自行体验或者游戏一下。不足之处欢迎指正。

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>


//猜数字游戏实现
void menu()
{
	printf("******************************\n");
	printf("********* 1.play *************\n");
	printf("********* 0.exit *************\n");
	printf("******************************\n");
}

void game()
{
	//生成随机数
	
	int ret = rand()%100;
	//printf("%d\n", ret);
	int guess = 0;
	
	while (1)//这里的循环保证了只有猜对才可以跳出,否则就会一直猜测
	{
		printf("请输入您猜测的数字:\n");
		scanf("%d", &guess);
		if (guess > ret)
		{
			printf("您猜大了,请重新猜测\n");
		}
		else if (guess < ret)
		{
			printf("您猜小了,请重新猜测\n");
		}
		else {
			printf("恭喜猜对了\n");
			break;
		}
	}
}

int main()
{
	
	//1.首先生成菜单
	//当客户玩完一句应该实现可以再次选择的功能或者用户输入错误可以再次输入的功能,所以这个使用 do while 循环来实现功能。
	int input = 0;
	srand((unsigned)time(NULL));
	do
	{
		


		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("游戏退出\n");
			break;
		default:
			printf("输入错误重新选择:\n");
			break;
		}
	} while (input);//当玩家选择0就是要退出游戏就直接出循环就行。

	return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值