详解循环猜数字小游戏

掌握了前⾯学习的这些知识,我们就可以写⼀些稍微有趣的代码了,⽐如:写⼀个猜数字游戏
游戏要求:

  1. 电脑自动生成1~100的随机数
  2. 玩家猜数字,猜数字的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束
    要想完成猜数字游戏,⾸先得产⽣随机数,那怎么产⽣随机数呢?

1 rand 函数

C语⾔提供了⼀个函数叫 rand,这函数是可以⽣成随机数的,函数原型如下所⽰:

1 int rand (void);//void的意思就是(无),就是不需要参数,不用传参。

rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的⼤⼩是根据编译器来实现的,在不同的编译器上可能会有不同的差异,但是在⼤部分编译器上是32767。

rand函数的使⽤需要包含⼀个头⽂件是:stdlib.h

那我们就测试⼀下 rand 函数,这⾥多调⽤⼏次,产⽣5个随机数:

#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 srand函数

C语⾔中⼜提供了⼀个函数叫 srand,⽤来初始化随机数的⽣成器的,srand的原型如下:

 void srand (unsigned int seed);

程序中在调⽤ rand 函数之前会先调用 srand 函数,通过 srand 函数的参数seed来设置rand函数⽣成随机数的时候的种⼦,只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。
那也就是说给srand的种⼦是如果是随机的,rand就能⽣成随机数;在⽣成随机数的时候⼜需要⼀个随机数,这就⽭盾了。其实也不是要给 srand 传一个随机值,只需要传一个一直在变化的值就够了。

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函数返回的这个时间差也被叫做:时间戳

时间戳其实就是一段数字,这个数字转换一下就可以转换成时间,上面有超链接大家可以点进去自行体会一下就能理解了。浏览器搜索时间戳也会有
当然使用 time 函数的时候需要包含头⽂件:time.h
如果只是让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函数是不需要频繁调用的,⼀次运行的程序中调用⼀次就够了。

4 设置随机数的范围

⽣成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.猜数字游戏实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void meun()
{
	printf("**************************\n");
	printf("******  1. 开始游戏 ******\n");
	printf("******  0. 结束游戏 ******\n");
	printf("**************************\n");
}
void gaem()
{
	int guess = 0;
	int z = 0;
	int r = rand() % 100 + 1;
	while (1)
	{
		printf("猜数字:");
		z++;
		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("猜对了~~~\n");
			printf("恭喜你一共用了%d次猜对了\n", z);
			break;
		}
	}
}
int main()
{
	int z = 0;
	srand((unsigned int)time(NULL));

	do
	{
		//打印菜单
		meun();

		printf("请选择 :>");
		scanf("%d", &z);
		switch (z)
		{
		case 1:
			printf("游戏开始\n");
			gaem();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (z);
	return 0;
}

在这里插入图片描述

5.1 限定猜数字的次数

其实原理和上面的计数是一样的,只需要在循环里面改变就可以了。

void gaem()
{
	int guess = 0;
	int z = 5;
	int r = rand() % 100 + 1;
	while (1)
	{
		printf("\n你还有%d次机会\n", z);
		z--;
		printf("猜数字:");

		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("猜对了~~~\n");
			break;
		}
		if (z == 0)
		{
			printf("你失败了,正确值是:%d\n", r);
		}
	}

}

在这里插入图片描述

6.分析猜数字小游戏原理

这个猜数字小游戏可以分成两个部分:1. 打印菜单 2. 循环体猜数字
接下来由作者将为大家详细讲解

6.1 打印菜单

首先这三个头文件得包含;

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

假设我们在玩一个游戏,玩完觉得不过瘾,还想再玩一把,如果这个游戏结束之后,需要关掉,重新打开,是不是就挺麻烦的?
那我们是不是可以这样想,就是运行玩完一把之后,不在退出程序,可以重新再来一把,比如说这把玩完了给你一个选择,选择 1 继续玩游戏,选择 0 就退出游戏。那这么一个逻辑,是不是提供一个菜单就可以实现?
那这个时候就可以给大家一个 do while 的循环结构
do while 循环的特点就是,上来之后不管三七二十一直接菜单

6.1.1 第一步:
方法1int main ()
{

	do
	{
		//直接在里面打印菜单的话,有点啰嗦,,那我们是不是可以直接分装一个函数来打印菜单
		meun();
	}while ();
	return 0;
}
方法2int main ()
{

	do
	{
	printf("**************************\n");
	printf("******  1. 开始游戏 ******\n");
	printf("******  0. 结束游戏 ******\n");
	printf("**************************\n");
	.....
	}while ();
	return 0;
}

这两种方法都正确,看大家按照喜好选择就可以;

6.1.2第二步:分装一个函数打印菜单
//那我们就可以在主函数的外面分装一个简易的菜单,他的类型我们就可以就可以写成“void”,
//“meun”的返回类型就是不需要他做任何返回,只需要悄悄地打印就可以了,因为前面我们写成了“void”,“void”的意思就是不需要返回;
void meun()
{
	printf("**************************\n");//这里可以打印的菜单可以是多样化的,我这里只是给大家一个示范。
	printf("******  1. 开始游戏 ******\n");
	printf("******  0. 结束游戏 ******\n");
	printf("**************************\n");
}
6.1.3第三步:判断是否继续
void meun()
{
	printf("**************************\n");
	printf("******  1. 开始游戏 ******\n");
	printf("******  0. 结束游戏 ******\n");
	printf("**************************\n");
}
int main ()
{
	int z = 0;
	do
	{
		meun();
		//那菜单打印出来之后,我们是不是就可以判断了,是玩游戏还是退出游戏,那我们这里提示一下
		printf("请选择:");
		//那这里选了1或0,就是输入一个值嘛,那就需要一个整形变量零存储这个值,那就在循环外面定义一下
		scanf("%d",&z);
		//在这里有人选择了 1或0 ,但是也有可能不小心选择了其他的数
	   //那我们是不是就需要根据别人的选择做出相应的处理,那我们就可以使用上“switch”选择语句了
	}while ();
	return 0;
}
6.1.4 第四步 :使用“switch”语句
方法1int main ()
{
	int z = 0;
	do
	{
		printf("**************************\n");
		printf("******  1. 开始游戏 ******\n");
		printf("******  0. 结束游戏 ******\n");
		printf("**************************\n");
		printf("请选择:");
		scanf("%d",&z);
		//使用 switch 语句判断 z 的值到底是什么
		switch (z)
		{
		case 1:
			printf("游戏开始\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	//当我们选择了 0 ,break 跳出来,就可以直接结束,那我们就可以在 “while” 里面放上“z”,
	//刚好0为假嘛,whike 就直接结束循环,而选择错误为非0,继续循环重新选择。这里大家就可以自己去测试一下了
	}while (z);
	return 0;
}

方法2图片演示:
在这里插入图片描述

6.2 循环体猜数字

6.2.1 第一步:分装一个game函数
int main()
{
	int z = 0;
	
	do
	{
		meun();//菜单

		printf("请选择 :>");
		scanf("%d", &z);
		switch (z)
		{
		case 1:
			printf("游戏开始\n");
			//开始游戏之后就可以直接从掉用我们分装的这个函数;
			gaem();//猜数字
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (z);
	return 0;
6.2.2 第二步:生成随机数
//首先函数类型,不需要它返回值,就可以写“void”,函数名字“gaen”
//这个里面就可以实现整个猜数字的过程
void gaem()
{
	//用“gaen”生成随机数,使用 rand() % 100 + 1,然后在把他存在变量 r 里面去
	//而调用“rand”之前,我们还调用 srand 而这个参数还得由 (time(NULL) 给我们产生的
	//而这个 srand(time(NULL)) 这个返回值我们最好强制类型转换一下
	//这里需要注意一点:还记得我们前面说过的srand函数是不需要频繁调用的
	//⼀次运行的程序中调用⼀次就够了反倒是频繁调用会出问题的
	//如果我们放在这个循环里面,就会每循环玩一次就会调用一次,那这个怎么解决呢?
	//我们可以把它放进主函数里面去,就只需要在开始的时候调用一次就够了
	int r = rand() % 100 + 1;
	
}
如:
int main()
{
	int z = 0;
	srand((unsigned int)time(NULL));

	do
	{
		meun();

		printf("请选择 :>");
		scanf("%d", &z);
		switch (z)
		{
		case 1:
			printf("游戏开始\n");
			gaem();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (z);
	return 0;
}
6.2.3 第三步:猜数字
void gaem()
{
	int guess = 0;
	int r = rand() % 100 + 1;
	//首先还是先提醒一下
		printf("猜数字:");
	//那猜数字是不是得猜,得输入一个数,那就需要定义一个变量,并且把它存起来
		scanf("%d", &guess);
	//然后开始判断:
		if (guess > r)
		{
			printf("猜大了\n");//如果你猜的数大于 r 那就提示你猜大了
		}
		else if (guess < r)
		{
			printf("猜小了\n");//如果你猜的数小于 r 那就提示你猜小了
		}
		else
		{
			printf("猜对了~~~\n");//如果你猜的数等于 r 那就提示你猜对了
			break;
		}
}
但是如果猜大了或者猜小了,那是不是就得用循环来继续游戏,不然猜一次就结束了,循环我们就可以用 while 循环
void gaem()
{
	int guess = 0;
	int z = 5;
	int r = rand() % 100 + 1;
	while (1)//这个里面给上一个1,就够了,死循环一直猜,直到你猜对了 break 跳出去
	{
		printf("\n你还有%d次机会\n", z);
		z--;
		printf("猜数字:");

		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("猜对了~~~\n");
			break;
		}
	}
}
6.2.4 源码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void meun()
{
	printf("**************************\n");
	printf("******  1. 开始游戏 ******\n");
	printf("******  0. 结束游戏 ******\n");
	printf("**************************\n");
}
void gaem()
{
	int guess = 0;
	int r = rand() % 100 + 1;
	while (1)
	{
		printf("猜数字:");

		scanf("%d", &guess);
		if (guess > r)
		{
			printf("猜大了\n");
		}
		else if (guess < r)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("猜对了~~~\n");
			break;
		}
	}

}

int main()
{
	int z = 0;
	srand((unsigned int)time(NULL));

	do
	{
		meun();
		printf("请选择 :>");
		scanf("%d", &z);
		switch (z)
		{
		case 1:
			printf("游戏开始\n");
			gaem();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (z);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值