C语言——猜数字游戏与关机程序(详细版)

一、猜数字游戏

游戏要求:

1.要求电脑生成1~100的随机数;

2.玩家猜数字,在猜数字的过程中,根据所猜测出的结果程序会给出猜大了或猜小了的反馈,直到你的猜测结果正确,游戏结束。

乍一看,是不是感觉挺简单的啊,不就是猜数字吗?这我还能不会吗?但当你冷静下来仔细看一下我们的大标题“C语言”,是不是有点慌了。不过不要怕,且听我娓娓道来。

那么这其中让我们觉得有点困难的地方在哪呢?我们再仔细审题,“随机数...."emm...,我寻思着我也不会生成随机数啊?你看,这病源不就找到了吗?既然找到了病源,那俺就好下药了。

接下来,我会将该游戏实现前的所有准备工作向大家汇报:

1.rand

随机数的生成需要rand函数(头文件:stdlib.h)的应用,这个函数是可以生成随机数的,函数原型如下:

1   int rand (void);

  rand函数会返回一个伪随机数(通过算法生成的,并非自然界真正的随机数),这个随机数的范围是0-RAND_MAX之间,这个RAND_MAX是依赖编译器上实现的,大部分编译器上是32767。

接下来我们来验证一下我们的初始代码:

第一次:

第二次:

王德法?这对吗?我们不是要生成随机数吗?第一次看着确实有那么点随机的味道,可这第二次是啥子哦。不信邪的我接连试了好几次,可还是这个结果,可想而知我当时的内心:。待我冷静下来上网搜索了一番,结合前面对于rand函数的概念了解一番,还是被我发现了端倪:rand函数实际上是对一个叫“种子”的基准值进行运算生成的随机数。

那么我们的错因显而易见了:我们自认为完美无瑕的运行了不知道多少次,可结果无动于衷的罪魁祸首就是生成随机数的默认种子一直都是1!所以如果我们想要生成不同的随机数,就需要让种子是变化的。俺特地去C++rederence里调取了rand函数如下图:

在我的细心观察下,发现了一个名为srand的东东,后来一经搜索才发现这个东东大有用处。

2.srand

srand函数是用来初始化随机数的生成器(种子)的,函数原型如下:

1  void srand(unsigned int seed);

只要给srand传一个变化的值,rand就能生成随机数。我就说这俩咋长得这么像,这不就是兄弟之间的关系吗?哥哥(rand)吩咐弟弟(srand)事情,弟弟(srand)照做。个人认为这样好记二者之间的关系:srand中的s可以理解为small。但是仅有这俩兄弟是远远不够的。我们如何才能找到一个合适(变化)的“种子”呢?接下来有请我们日常生活中一直不怎么起眼的time“嘉宾”登场。

3.time头文件:time.h

在程序中我们一般是使用程序运行的时间作为种子,因为时间是时刻在发生变化的。

time函数原型如下:

time_t  time(time_t* timer)

这里涉及到后面需要学习的指针,time_t*即为该函数原型中的指针,目前学识有限的我也不知道咋解释,就不管它了,撂倒一边去。这个参数我们就不用它了,直接传NULL。

time函数可以返回当前的日期时间。该返回值就是用现在程序运行的时间减去计算机的起始时间(1970.1.1 0:0:0),单位是秒。返回的类型是time_t类型,本质上其实就是32位或者64位的整型类型。

既然兄弟俩和我们的嘉宾都已经就绪,应该就可以为我们表演变脸(随机值)了吧。

第一次:

第二次:

接连好几次尝试,都是不一样的结果。

那么表演也是非常成功啊。当然在这里我们也要强调一下,如下图:

前面提到srand需要的参数类型是unsigned int,我们怕编译器不认识,所以我们将返回值转换成unsigned int。

已经到这一步了,可如果数字这么凌乱和不规则我们还猜啥数嘞,我们再回顾一下游戏要求:要求电脑生成1~100的随机数,那么我们肯定要设置随机数的范围。所以接下来我们来介绍一下随机数的生成方法。

4.设置随机数的范围:

如果要生成0~99之间的随机数:

rand () %100; //余数范围是0~99

如果要生成1~100之间的随机数:这个在上面的加1就行了

rand () %100 +1; //余数范围是1~100

如果要生成100~200之间的随机数:

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

所以我们可以得到一般情况:生成a~b的随机数:

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

好啦,掌握以上知识就足够啦,我们可以来实现我们的猜数字游戏喽!

猜数字游戏的实现:初始版==>进阶版==>进阶版plus

初始版:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
	int i = 0;
	do
	{
		printf("***************************\n");
		printf("********* 1.play **********\n");
		printf("********* 0.exit **********\n");
		printf("***************************\n");
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			printf("猜数字\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("别乱选,就俩数,一边玩去\n");
			break;
		}

	} while (i);

	return 0;
}

运行结果如下:

注:switch语句中的break跳出break只会跳出switch,不会跳出do while

通过观察我们不难发现,每次将那么长的菜单打印出来既不美观又繁琐,所以我们有什么方法可以将其单独封装吗?有的,兄弟,有的。

我们需要引入menu函数来封装:

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

完整代码:

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






 #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
	int i = 0;
    srand((unsigned int) time(NULL));//由前面内容可知,此处应放入主函数,保证调用一次就行,没必要放入game函数
	do
	{
		menu();
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			printf("猜数字\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("别乱选,就俩数,一边玩去\n");
			break;
		}

	} while (i);

	return 0;
}

我们再来看看效果:

我们发现效果是一样的,但整体上美观多了。但我们再来看这串代码,总不能花费这么长时间写了个这么无聊的甚至称不上游戏的游戏吧。那当然是不可能的,心急吃不了热豆腐,且听我娓娓道来。

可是既然要优化我们的猜数字游戏,那么多的游戏内容如果放入我们的代码中会显得非常冗长,那么我们应该怎么办呢?相信你已经有了答案,没错,再找一个函数来封装我们的游戏内容。我们可以将case 1中的"printf("猜数字\n")"改为game()。于是有了以下进阶版代码:

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


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

void game()
{
	int r = rand() % 100 + 1;//生成随机数
	int j = 0;//准备猜数字,可你知道你需要猜多少次才能猜对吗?并不知道,所以引入下面的while循环
	while (1)
	{
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &j);
		if (j < r)
			printf("牢弟,猜小了,还得练\n");
		else if (j > r)
		{
			printf("牢弟,猜大了,还得练\n");
		}
		else
		{
			printf("不错哦,猜对了,数字是:%d\n", r);
			break;//因为这里是while的死循环
		}
	}
}

int main()
{
	int i = 0;
	srand((unsigned int)time(NULL));//由前面的内容可知,此处应该放入主函数,保证调用一次就行,没必要放入game函数
	do
	{
		menu();
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("别乱选,就俩数,一边玩去\n");
			break;
		}

	} while (i);

	return 0;
}

运行结果如下:

当然这里俺(古希腊掌管猜数字游戏的神)也是非常厉害,不到三次就猜出来了。说到次数,我们还可以将代码进一步优化得到进阶版plus,代码如下:

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


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

void game()
{
	int r = rand() % 100 + 1;//生成随机数
	int j = 0;//准备猜数字,可你知道你需要猜多少次才能猜对吗?并不知道,所以引入下面的while循环
	int count = 3;
	while (count)
	{
		printf("还剩%d次机会\n", count);
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &j);
		if (j < r)
			printf("牢弟,猜小了,还得练\n");
		else if (j > r)
		{
			printf("牢弟,猜大了,还得练\n");
		}
		else
		{
			printf("不错哦,猜对了,数字是:%d\n", r);
			break;//因为这里是while的死循环
		}
		count--;
	}
	if (count == 0)
		printf("牢弟,次数没了,回家练吧\n");
}

int main()
{
	int i = 0;
	srand((unsigned int)time(NULL));//由前面的内容可知,此处应该放入主函数,保证调用一次就行,没必要放入game函数
	do
	{
		menu();
		printf("请准备开始游戏,输入你的数字:");
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("别乱选,就俩数,一边玩去\n");
			break;
		}

	} while (i);

	return 0;
}

代码运行如下:

忙到现在还没吃饭,没力气了,不然肯定出来了。

注:如果你想把这个程序拷贝给你的损友耍,记得将Debug改为Release就可以了。

      

二、关机程序

程序介绍:程序运行起来后,电脑就倒计时1分钟关机,如果在1分钟内输入“我是猪,我是猪,我是一只可爱的粉红pig”,就取消关机,不输入的话,1分钟就关机。

制作该程序提前需要了解:

shutdown:用来关机的命令

-s:设置关机

-t:设置倒计时

-a:取消关机

                              system 函数:用来执行命令的    strcmp函数:用来字符串的比较

所需头文件:<stdlib.h>                   所需头文件:<string.h>

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	char i[20] = { 0 };//字符数组,用来存放字符串
	system("shutdown -s -t 60");
next:
	printf("如果在1分钟内输入“我是猪,我是猪,我是一只可爱的粉红pig”就取消关机\n");
	scanf("%s", &i);
	if (strcmp(i, "我是猪,我是猪,我是一只可爱的粉红pig") == 0)//两个字符串在比较内容时,不能使用==
	{
		system("shutdown -a");//取消关机
		printf("关机被取消\n");
	}
	else
	{
		goto next;
	}
		return 0;
}

这个我就不演示了,感兴趣的可以自己试试。当然此处使用goto语句无非是想要就是循环,那么我们也可以使用while循环来代替:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	char i[20] = { 0 };//字符数组,用来存放字符串
	system("shutdown -s -t 60");
	while (1)//死循环,直到有一次输入正确
	{
	  printf("如果在1分钟内输入“我是猪,我是猪,我是一只可爱的粉红pig”就取消关机\n");
	  scanf("%s", &i);
	  if (strcmp(i, "我是猪,我是猪,我是一只可爱的粉红pig") == 0)//两个字符串在比较内容时,不能使用==
	  {
		  system("shutdown -a");//取消关机
		  printf("关机被取消\n");
		  break;//跳出去
	  }
		return 0;
}

那么我的任务完成了,本人是C语言新手,如果有不足的地方,还请大家指出来。希望大家可以一起共同进步!谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值