猜数字游戏——C语言实现

前言

在学习了选择和循环结构后,我们就可以根据现有的知识编写一些简单有趣的代码了。下面介绍一种简单又好玩的猜数字游戏,希望大家在游戏中体会到编程的快乐!

游戏简介

电脑自动生成1~100的随机数。玩家猜数字,如果猜大了,则提示“猜大了!”,如果猜小了,则提示“猜小了!”,如果猜对了,则提示“恭喜你,猜对了!”。

实现过程

一、打印菜单

为使main函数部分代码简洁,这里单独封装menu函数实现打印菜单功能。实现过程较简单,即玩家输入“1”,开始游戏;玩家输入“0”,退出游戏,这里不过多赘述。

void menu()
{
	printf("*****************************\n");
	printf("*****************************\n");
	printf("*****      1.PLAY      ******\n");
	printf("*****      0.EXIT      ******\n");
	printf("*****************************\n");
	printf("*****************************\n");
}

二、确定游戏框架

下面我们来确定游戏主体框架,即main函数部分。
为实现玩家输入“1”,开始游戏;玩家输入“0”,退出游戏;玩家输入其他数字,提示无效输入。考虑使用switch语句。
由于为保证玩家能进行多次游戏,且需要保证循环体至少执行一次,考虑使用do-while循环。

int main()
{
	int input = 0;
	do
	{
		menu();//打印菜单
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//game函数部分请看后面哦!
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("无效选择!请重新选择!\n");
			break;
		}
	} while (input);//input为1,能继续循环;input为0,退出游戏

	return 0;
}

三、生成随机数

确定游戏框架后,怎么让计算机自动生成随机数呢?
为使计算机能自动生成随机数,下面我们先介绍几种函数,相信看完后你就能明白其中的秘密。

1、rand函数

C语言提供了一个函数叫rand,这个函数是可以生成随机数的。使用时需包含头文件<stdlib.h>。
函数原型:

 int rand (void);

rand函数会返回一个(伪)随机数,这个随机数的范围实在0~RAND_MAX之间,RAND_MAX的大小是依赖编译器实现的,但是大部分编译器上RAND_MAX是32767。
下面我们就测试一下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个随机数:
第一次运行结果
可是,我们发现,不管程序运行几次,生成的随机数总是这5个:
第二次运行结果
生成的随机数“不随机”,这是为什么呢?
原来,rand函数生成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法生成的随机数。rand函数是对一个叫做“种子”的基准值进行运算而生成的随机数。
之所以前面每次运行程序产生的随机数是一样的,是因为rand函数默认生成随机数的种子为1。
那么,为了生成不同的随机数,就要让rand函数的“种子”是变化的。

2、srand函数

C语言中又提供了一个函数叫srand,这个函数是用来初始化随机数的生成器的。使用时需包含头文件<stdlib.h>。
函数原型:

 void srand (unsigned int seed);

所以,程序中在调用rand函数之前,要先调用srand函数,通过srand函数的参数seed来初始化rand函数生成随机数时的种子。这样,种子在变化,每次生成的随机数也就是变化的。
也就是说,如果给srand函数的种子如果是随机的,rand就能生成随机数。
那么,怎样使srand函数的种子是随机的呢?

3、time函数

在程序中,我们一般是使用程序运行的时间作为种子的,因为时间是时刻在发生变化的。
C语言中提供了一个函数叫time,这个函数可以用来获取时间。使用时需包含头文件<time.h>。
函数原型:

 time_t time (timr_t* timer);

time函数会返回当前的日历时间,实际上,time函数返回的是1970年1月1日0时0分0秒到现在程序运行时间的差值,单位是秒。返回的类型是time_t类型的,time_t类型本质上其实是32(#`O′)或64位的整形类型。
如果time函数的参数timer是空指针NULL,就只会返回这个时间的差值,返回的这个时间差也叫:时间戳
即如果只是想让time函数返回时间戳,我们就可以这样写:

 time (NULL);

学习了rand srand time这三种函数后,我们就可以将生成随机数的代码改写如下:
注意:由于time函数的返回值是整形,而srand函数的参数是unsigned int,这里需要将time函数的返回值强制类型转换 。

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

int main()
{
	srand((unsigned int)time(NULL));//使用time函数的返回值设置种子
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	
	return 0;
 } 

这样,我们就可以每次都真正产生完全随机的5个数:
在这里插入图片描述

4、设置随机数的范围

由于我们只需要产生0~100之间的随机数,而rand函数最大能产生的随机数为32767,这对我们来说太大了,这就需要设置随机数的范围。
这里需要一点数学知识,我们要知道,任何一个数除以100的余数一定是在0到99之间的,那么如果要生成1到100之间的随机数,方法如下:

 rand () % 100 + 1;//这时余数范围为1~100

以此类推,如果要生成100~200之间的随机数,方法如下:

 100 + rand () % (200 - 100 + 1)//余数的范围是0~100,加100后就是100~200

如果要生成a~b之间的随机数,方法如下:

 a + rand () % (b - a + 1);

三、实现猜数字

最后,我们来到游戏的game函数部分。
我们通过无限循环while(1)来实现反复输入所猜的数字,并反复给出提示与反馈。
首先确定1~100之间的一个随机数,然后玩家输入一个数字,如果猜大了,则提示“猜大了!”,如果猜小了,则提示“猜小了!”,如果猜对了,则提示“恭喜你,猜对了!”。

void game()
{
	int ret = rand()%100+1;
	int guess = 0;
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < ret)
		{
			printf("猜小了!\n");
		}
		else if (guess > ret)
		{
			printf("猜大了!\n");
		}
		else
		{
			printf("恭喜你,猜对了!\n");
			break;
		}
	}
}

完整源码

能看到这里,你实在太棒了!
好了!下面让我们一起来看一看完整的C语言源代码吧!

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

void menu()
{
	printf("*****************************\n");
	printf("*****************************\n");
	printf("*****      1.PLAY      ******\n");
	printf("*****      0.EXIT      ******\n");
	printf("*****************************\n");
	printf("*****************************\n");
}

void game()
{
	int ret = rand()%100+1;
	int guess = 0;
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < ret)
		{
			printf("猜小了!\n");
		}
		else if (guess > ret)
		{
			printf("猜大了!\n");
		}
		else//guess=ret,猜对了!
		{
			printf("恭喜你,猜对了!\n");
			break;
		}
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//设置种子,在调用rand函数之前先调用srand函数
	do
	{
		menu();//打印菜单
		printf("请选择:");
		scanf("%d", &input);//输入所猜的数字
		switch (input)
		{
		    case 1:
			    game();//进入游戏game函数部分
			    break;
		    case 0:
			    printf("游戏结束\n");
			    break;
		    default:
			    printf("无效选择!请重新选择!\n");
			    break;
		}
	} while (input);

	return 0;
}

这里有一点需要重点说明,就是srand函数调用的位置。即do-while循环之外,主函数之中。由于种子只需要设置一次即可,所以srand函数一定要在main函数之中,因为main函数只执行一次,而不能在game函数之中。如果将srand函数放在game中,则会导致两次游戏生成的随机数非常相近。且一定要在do-while循环之外,否则每次猜一个数字后电脑生成的随机数都会改变,导致游戏出现bug。

游戏机制优化——次数限制

为了增加游戏的趣味性,让游戏变得更加刺激,我们还可以加上次数限制。玩家有5次猜数字机会,如果5次猜不出来,则游戏失败。

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

void menu()
{
	printf("*****************************\n");
	printf("*****************************\n");
	printf("*****      1.PLAY      ******\n");
	printf("*****      0.EXIT      ******\n");
	printf("*****************************\n");
	printf("*****************************\n");
}

void game()
{
	int ret = rand()%100+1;
	int guess = 0;
	int count = 5;//引入计数变量count
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < ret)
		{
			printf("猜小了!\n");
		}
		else if (guess > ret)
		{
			printf("猜大了!\n");
		}
		else
		{
			printf("恭喜你,猜对了!\n");
			break;
		}
		count--;//每次猜错count--
		if (count == 0)
		{
			printf("失败了!正确的数字是:%d\n", ret);//失败了,显示正确数字
			break;
		}
	}
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("无效选择!请重新选择!\n");
			break;
		}
	} while (input);

	return 0;
}

总结

今天我们学习了选择与循环结构的简单应用,实现了简单又好玩的猜数字游戏。快去和你的小伙伴们玩起来吧!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值