【手把手教你实现C语言】猜数字游戏

一、前言: 什么是猜数字游戏 ?

写⼀个猜数字游戏

游戏要求:

  1. 电脑随机⽣成1~100的随机数
  2. 玩家猜数字
    如果猜小了,电脑提示猜小了;
    如果猜大了,电脑提示猜大了;
    如果猜对了,电脑提示:恭喜你,猜对了,游戏结束
  3. 如果玩完一次游戏后,不过瘾的话,还可以继续玩

二、 游戏实现思路

1. 打开方式

一般玩游戏的时候,一般如下图所示的界面,只要点击界面上的按钮,就可以实现开始游戏的效果。我们把这个界面就叫做 “菜单”。

在这里插入图片描述

2. 实现逻辑

那么我们在打开“开始游戏”界面后,就进入了游戏,那么游戏的实现逻辑就如前言给出的要求一样 。

首先电脑先给出一个1-100的随机数,能够让玩家去猜测。

在系统确定了一个数字之后,玩家就开始猜数字,这时候我们可以用一个整型变量来保存玩家输入的数字,然后告诉玩家是猜大了还是猜小了,还是猜中了。

如果猜中了,则游戏结束;如果猜错了,则让玩家继续猜,直到猜中为止。

游戏结束后,通常又会跳出一个界面,是继续玩游戏呢?还是退出游戏呢?这时可以把最开始的菜单调出来,让玩家再次选择,是否再次进入游戏。

在这里插入图片描述

当然,在游戏结束前,我们还可以把每一局游戏玩家猜的次数告诉玩家。

以上就是一个完整的猜数字游戏的思路了,重点总结如下:

(1)菜单
(2)生成随机数
(3)猜数字循环

三、代码实现

1. 随机数

1.1 rand函数

随机数的生成可以使用C语言库函数中的rand函数【1】

rand函数原型为:int rand (void);(void指的是rand函数不需要参数,但调用rand函数就会返回一个int类型的随机数。)

rand函数会返回一个伪随机数。这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是⼤部分编译器上是32767。

rand函数的使⽤需要包含⼀个头⽂件是:stdlib.h,即 #include <stdlib.h>

接下来,测试一下rand函数,调⽤5次rand函数,产⽣5个随机数。

#include <stdio.h>
#include <stdlib.h>//rand函数的使用需要包含头文件:stdlib.h

int main()
{
	//rand函数生成随机数的默认种子是1
	int r = rand();//生成的随机数为r,rand()是调用rand函数不需要传参
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	return 0;
}

在这里插入图片描述

在这里插入图片描述

调试程序后,发现无论测试多少次,5个随机数的值不变(玩完一次游戏后,第二次的值与第一次的值相同),就说明使用rand函数不能生成我们想要的随机数。

最后发现:
(1)rand函数⽣成的随机数是伪随机数,不是真正的随机数,是通过某种算法⽣成的随机数。真正的随机数的是⽆法预测下⼀个值是多少的。
(2)⽽rand函数是对⼀个叫“种⼦”的基准值进⾏运算⽣成的随机数。之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的,那是因为rand函数⽣成随机数的默认种⼦是1。
(3)如果要⽣成不同的随机数,就要让种⼦是变化的。

1.2 srand函数

C语言提供了srand函数【2】,用来初始化随机数的生成器(改变默认种子的值)。

srand函数的原型为:void srand (unsigned int seed);(srand函数传入的参数类型为unsigned int,返回值为void 空值 )

#include <stdio.h>
#include <stdlib.h>//rand函数的使用需要包含头文件:stdlib.h

int main()
{
	srand(2);//srand函数设置随机种子为2
	//rand函数生成随机数的默认种子是1
	int r = rand();//生成的随机数为r,rand()是调用rand函数不需要传参
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	return 0;
}

在这里插入图片描述

(1)srand函数设置随机种子的值为2,发现生成的随机数较rand函数生成的随机数有变化,但是多次执行后,发现随机数的值还是没有变化。

(2)原因在于:srand函数设置的随机种子是固定值2。所以我们需要一个随机值来作为srand的种子,但生成随机数的时候又需要一个随机数,互相矛盾。

1.3 time函数

  1. 我们想到可以用程序运⾏的时间作为种⼦的,因为时间时刻在发⽣变化的。

在C语言提供了time函数【3】,就可以获得这个时间,time函数原型如下:time_t time (time_t* timer);

(1)time 函数会返回当前的⽇历时间,其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的
差值,单位是秒。返回的类型是time_t类型的,time_t 类型本质上其实就是32位或者64位的整型类型。
(2)time函数的参数 timer 如果是⾮NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
(3)如果 timer 是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
(4)time函数的时候需要包含头⽂件:time.h

我们可以利用时间戳【4】(时间戳:timer 是NULL,就只返回这个时间的差值,time函数返回的时间差)生成随机数。

在这里插入图片描述

  1. 那么如何使用时间戳生成随机数呢?

参照 cplusplus网站rand函数的例子 ,只是让time函数返回时间戳:time(NULL) //调⽤time函数返回时间戳,这⾥没有接收返回值
在这里插入图片描述

  1. 利用rand函数、srand函数和time函数(时间戳)生成随机数
#include <stdio.h>
#include <stdlib.h>//rand、srand函数的使用需要包含头文件:stdlib.h
#include <time.h>  //time函数的使用需要包含头文件:time.h

int main()
{
	//使用time函数的返回值设置种子
    //因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
	srand((unsigned int) time(NULL));

	int r = rand();//生成的随机数为r,rand()是调用rand函数不需要传参
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	r = rand();
	printf("%d\n", r);

	return 0;
}


在这里插入图片描述

在这里插入图片描述
多运行几次,发现产生的随机数都不同。

  1. 产生1~100之间的随机数(参考 cplusplus网站rand函数的例子

(1)生成1-100之间的随机数:rand()%100+1; (%100的余数是0-99,0-99的数字+1,范围是1~100)

(2)生成a~b的随机数: a + rand()%(b-a+1)
(3)生成随机数之前需要调用srand来设置随机数的生成起点,srand函数只需要调⽤⼀次就够了,不能频繁调用。

#include <stdio.h>
#include <stdlib.h>//rand函数的使用需要包含头文件:stdlib.h
#include <time.h>  //time函数的使用需要包含头文件:time.h

int main()
{
	//使用time函数的返回值设置种子
    //因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
	srand((unsigned int) time(NULL));

	int r = rand()% 100 + 1;//生成a~b的随机数: a + rand()%(b-a+1)
	printf("%d\n", r);

	r = rand() % 100 + 1;;
	printf("%d\n", r);

	r = rand() % 100 + 1;;
	printf("%d\n", r);

	r = rand() % 100 + 1;;
	printf("%d\n", r);

	return 0;
}

在这里插入图片描述

2. 游戏菜单

游戏一开始,就有一个菜单出现(do…菜单…while),供玩家选择玩游戏还是不玩游戏。

#include <stdio.h>
int main()
{
	int input = 0;//初始化input为玩家的选择: 1:play; 0:exit
	do//do..while语句:游戏开始就出现菜单
	{
		printf("******************\n");
		printf("***** 1.play *****\n");
		printf("***** 0.exit *****\n");
		printf("******************\n");

		printf(" 请选择:");//定义进入游戏的菜单
		scanf("%d", &input);//键盘输出1或者0,接收玩家的选择
		switch (input)//switch语句,创建分支:根据玩家的选择判断是否进行游戏
		{
		case 1:
			printf("猜数字\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;

		}

	} while (input);//当玩家选择完成后,while判断输入可以继续供玩家选择玩游戏与否
	return 0;
}

在这里插入图片描述

当然也可以将菜单封装到menu()函数中,使代码更简洁。

封装的menu()函数:
在这里插入图片描述

封装函数和运行效果如下:

#include <stdio.h>
void menu()
{
	printf("******************\n");
	printf("***** 1.play *****\n");
	printf("***** 0.exit *****\n");
	printf("******************\n");

	
}
int main()
{
	int input = 0;//初始化input为玩家的选择: 1:play; 0:exit
	do//do..while语句:游戏开始就出现菜单
	{
		menu();//调用函数
		printf(" 请选择:");//定义进入游戏的菜单
		scanf("%d", &input);//键盘输出1或者0,接收玩家的选择
		switch (input)//switch语句,创建分支:根据玩家的选择判断是否进行游戏
		{
		case 1:
			printf("猜数字\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;

		}

	} while (input);//当玩家选择完成后,while判断输入可以继续供玩家选择玩游戏与否
	return 0;
}

在这里插入图片描述

3. 猜数字循环

同样的,猜数字游戏也可以封装成一个函数game();
game();函数:
在这里插入图片描述

四、 整体代码

1.按照前言要求实现的代码和运行效果如下

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
	printf("******************\n");
	printf("***** 1.play *****\n");
	printf("***** 0.exit *****\n");
	printf("******************\n");

}

void game()
{
	//1.生成随机数
	//srand((unsigned int)time(NULL));//生成随机数之前需要调用srand来设置随机数的生成起点,
	                                //srand函数只需要调用一次就够了,不能频繁调用。
	int r = rand() % 100 + 1;

	//2.猜数字
	int guess = 0;
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < r)
			printf("猜小了\n");
		else if (guess > r)
			printf("猜大了\n");
		else
		{
			printf("恭喜你,猜对了,随机数是:%d\n",r);
			break;
		}
	}
}
int main()
{
	int input = 0;//初始化input为玩家的选择: 1:play; 0:exit
	srand((unsigned int)time(NULL));//因为生成随机数之前需要调用srand来设置随机数的生成起点,
	                                //srand函数只需要调用一次就够了,不能频繁调用。
	                                //所以srand函数没有写在game()函数中,而是写在主函数中,只调用一次就行。

	do//do..while语句:游戏开始就出现菜单
	{
		menu();//调用函数
		printf("请选择:");//定义进入游戏的菜单
		scanf("%d", &input);//键盘输出1或者0,接收玩家的选择
		switch (input)//switch语句,创建分支:根据玩家的选择判断是否进行游戏
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;

		}

	} while (input);//当玩家选择完成后,while判断输入可以继续供玩家选择玩游戏与否
	return 0;
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2. 如果在1的基础上,加上玩家最多猜测5次的要求

可以在game()函数中的while循环中加入一个计数变量等于5,当计数变量为0后,直接打印猜数字游戏失败。
在这里插入图片描述

最终代码如下:

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

void menu()
{
	printf("******************\n");
	printf("***** 1.play *****\n");
	printf("***** 0.exit *****\n");
	printf("******************\n");

}

void game()
{
	//1.生成随机数
	//srand((unsigned int)time(NULL));//生成随机数之前需要调用srand来设置随机数的生成起点,
									//srand函数只需要调用一次就够了,不能频繁调用。
	int r = rand() % 100 + 1;

	//2.猜数字
	int guess = 0;
	int count = 5;
	while (count)
	{
		printf("你还有%d次机会\n", count);
		printf("请猜数字(1~100):");
		scanf("%d", &guess);
		if (guess < r)
			printf("猜小了\n");
		else if (guess > r)
			printf("猜大了\n");
		else
		{
			printf("恭喜你,猜对了,随机数是:%d\n", r);
			break;
		}
		count--;
	}
	
	if (count == 0)
	{
		printf("你失败了,随机数是%d\n", r);
	}

}

int main()
{
	int input = 0;//初始化input为玩家的选择: 1:play; 0:exit
	srand((unsigned int)time(NULL));//因为生成随机数之前需要调用srand来设置随机数的生成起点,
	                                //srand函数只需要调用一次就够了,不能频繁调用。
	                                //所以srand函数没有写在game()函数中,而是写在主函数中,只调用一次就行。

	do//do..while语句:游戏开始就出现菜单
	{
		menu();//调用函数
		printf("请选择:");//定义进入游戏的菜单
		scanf("%d", &input);//键盘输出1或者0,接收玩家的选择
		switch (input)//switch语句,创建分支:根据玩家的选择判断是否进行游戏
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;

		}

	} while (input);//当玩家选择完成后,while判断输入可以继续供玩家选择玩游戏与否
	return 0;
}

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值