在学习C语言时,其实并不是必须要学完所有的知识才能写一些好玩有趣的代码,其实在学完循环后就可以开始慢慢的实现一些有趣味的代码了,比如下面介绍的猜数字小游戏。
对,你没看错,学完循环就可以实现有趣的小游戏了,这样一来的话好像就可以在比较枯燥的语法学习过程中增添一些乐趣,也可以让我们对继续学习后面更多的知识保持激情。
游戏规则
1.电脑自动生成1~100的随机数
2.玩家通过键盘输入来进行猜数字
3.游戏程序通过玩家猜测的数据的大小来给出“猜大了”或“猜小了”的反馈提示
4.每局游戏限制玩家5次机会,超过5次没猜对的话则游戏失败
5.若玩家在5次之内就猜对数字的话,恭喜玩家游戏成功
6.每局游戏结束后让玩家选择退出游戏,或者再来亿把
因为顾虑可能有小伙伴不能读懂我的代码,所以写得非常细致。制作不易,望点赞+收藏。
代码实现
**1.**准备工作:既然是要完成一个小游戏,那么就搞个游戏菜单(乞丐版)
#include <stdio.h>
//游戏菜单
void menu()
{
printf("******************\n");
printf("*** 1.play ***\n");
printf("*** 2.exit ***\n");
printf("******************\n");
}
**2.**这里先捋清大的框架与思路。这里可以先让玩家选择是否开始游戏,进入游戏后就可以玩游戏了,每玩完一把后就再次让玩家选择是否开始游戏,有了这个思路后下面就用循环实现。
#include <stdio.h>
int main()
{
int input = 0;//用于选择play 或 exit
do
{
void menu();//对menu函数声明
menu();//调用menu函数
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("进行游戏");
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误!请输入0或1\n");
break;
}
} while (input);
return 0;
}
这里的while (input)中的input恰好不需要进行任何判断。
1.如果玩家输入了1。那么自然就为真,循环继续
2.如果玩家输入了0。那么为假,循环结束
3.如果玩家输入的既不是0也不是1。那么依然为真(只要非0就是真),循环继续
**3.**现在有了大框架后我们就要往更具体的方向去实现一些细节了。在上面的代码块中,case 1: 后执行的还只是一个简单的打印,其实想实现的功能是进行游戏,下面来完成这个功能(为了提高代码的可读性,使代码逻辑更加清晰,这里选择写一个game函数来封装“进行游戏”的代码)。
#include <stdio.h>
#include <stdlib.h>
//进行游戏
void game()
{
//rand函数可以生成一个随机数,调用rand函数需要引入头文件stdlib.h
//数学常识:两个正整数相除,余数的范围是0~除数之间(不包含除数本身)
//生成0~100的随机数
int n = rand() % 101;
int guess = 0;//存放玩家猜测的数字
while (1)
{
printf("你要猜的数字是:");
scanf("%d", &guess);
//判断玩家猜大还是猜小
if (guess > n)
{
printf("猜大了\n");
}
else if (guess < n)
{
printf("猜小了\n");
}
else
{
printf("恭喜你!猜对了!\n");
break;
}
}
}
上方的代码块是进行游戏的代码。
1.既然这个游戏是猜数字,那首先肯定要生成一个随机数给玩家猜
2.我们让玩家猜的数字与rand函数生成的那个随机数进行比较(这里使用多分支语句),如果猜的数比生成的数大,提示玩家猜大了;如果猜的数比生成的数小,提示玩家猜小了;不管猜大还是猜小,我都想让玩家继续猜,直到猜对,所以将这写判断全部放到循环语句中去,直到玩家猜对了,才结束循环
**4.**到这一步,猜数字游戏大部分功能都可以实现了,但是游戏规则中规定玩家每局只有5次机会,并且5次都没猜对就结束游戏。下面我们就来实现限制玩家猜测次数。
#include <stdio.h>
#include <stdlib.h>
//进行游戏
void game()
{
//rand函数可以生成一个随机数,调用rand函数需要引入头文件stdlib.h
//数学常识:两个正整数相除,余数的范围是0~除数之间(不包含除数本身)
//生成0~100的随机数
int n = rand() % 101;
int guess = 0;//存放玩家猜测的数字
int count = 5;//玩家猜测次数
while (1)
{
printf("你还有%d次机会\n", count);
printf("你要猜的数字是:");
scanf("%d", &guess);
//判断玩家猜大还是猜小
if (guess > n)
{
printf("猜大了\n");
}
else if (guess < n)
{
printf("猜小了\n");
}
else
{
printf("恭喜你!猜对了!\n");
break;//结束游戏
}
//每猜错一次就让count-1
count--;
if (count == 0)
{
printf("很遗憾!你的5次机会已用光\t谜底数字是:%d\n", n);
break;//结束游戏
}
}
}
这里只需在加上一个count变量来记录玩家猜测的次数,这里初始值给5,每猜错一次就让count-1,然后分支语句判断一下count是否为0,为0自然就表示猜了5次。
但是我想让这个游戏的功能进一步完善,比如每次猜之前提示玩家还有几次猜测机会,5次都没猜中后告诉玩家谜底数字再结束游戏。
所以在上述代码块中可以利用变量count来记录猜测次数,每猜错一次就让这个记录次数变量减1(第16行与第35行)。如果想在结束之前打印谜底数字的话直接打印rand函数生成的随机数就行了(也就是上述代码中的n)
5.到这里猜数字游戏就完成了,但是上述的代码块中是单个的函数,并不是所有代码,完整代码如下所示。
#include <stdio.h>
#include <stdlib.h>
//游戏菜单
void menu()
{
printf("******************\n");
printf("*** 1.play ***\n");
printf("*** 2.exit ***\n");
printf("******************\n");
}
//进行游戏
void game()
{
//rand函数可以生成一个随机数,调用rand函数需要引入头文件stdlib.h
//数学常识:两个正整数相除,余数的范围是0~除数之间(不包含除数本身)
//生成0~100的随机数
int n = rand() % 101;
int guess = 0;//存放玩家猜测的数字
int count = 5;//玩家猜测次数
while (1)
{
printf("你还有%d次机会\n", count);
printf("你要猜的数字是:");
scanf("%d", &guess);
//判断玩家猜大还是猜小
if (guess > n)
{
printf("猜大了\n");
}
else if (guess < n)
{
printf("猜小了\n");
}
else
{
printf("恭喜你!猜对了!\n");
break;//结束游戏
}
//每猜错一次就让count-1
count--;
if (count == 0)
{
printf("很遗憾!你的5次机会已用光\t谜底数字是:%d\n", n);
break;//结束游戏
}
}
}
int main()
{
//函数声明
void menu();
void game();
int input = 0;//用于选择play 或 exit
do
{
menu();//调用menu函数
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("玩游戏");
game();//调用game函数
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误!请输入0或1\n");
break;
}
} while (input);//这里不需要对input进行判断,0就循环结束;1就循环继续;输入错误(也是非0),循环继续
return 0;
}
运行结果
建议大家在看完后也可自行敲一遍,如果在敲的过程中卡主了,可以再来看本文思路
知识拓展
现在要告诉你们一个秘密了!其实每重新运行程序后后,直接猜数字41就能猜对,也就是说每次重新运行代码所生成的那个随机数总是41。
不信我运行给你看,运行结果如下:
那这是为什么呢?
其原因就是rand函数所生成的随机数其实是伪随机的,并不是真正的随机数,这种伪随机数是同过某种算法生成的随机数。而rand函数是对某一个固定的“基准值”进行运算生成的随机数,这就导致了每次从新运行程序后直接猜41就能猜成功。如果要想每次都生成不同的随机数,就要让“基准值”是变化的。
C语言中提供了一个函数叫srand,是用来初始化随机数的生成器的。通过srand函数的参数来设置rand函数生成随机数的时候的“基准值”,只要“基准值”在变化,每次生成的随机数也就跟着变化起来了。
这时候就要调用一个叫time的函数来实现了,使用time函数的返回值(返回的值是1970年1月1日0时0分到此时此刻时间的时间差,单位是秒)作为srand函数的参数(也就是作为生成随机数的“基准值”)。
这样一来这个“基准值”就一直是变化的,因为此时此刻的时间是一直在变化的。下面是具体的代码实现,请注意下方代码中第65行代码。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//游戏菜单
void menu()
{
printf("******************\n");
printf("*** 1.play ***\n");
printf("*** 2.exit ***\n");
printf("******************\n");
}
//进行游戏
void game()
{
//rand函数可以生成一个随机数,调用rand函数需要引入头文件stdlib.h
//数学常识:两个正整数相除,余数的范围是0~除数之间(不包含除数本身)
//生成0~100的随机数
int n = rand() % 101;
int guess = 0;//存放玩家猜测的数字
int count = 5;//玩家猜测次数
while (1)
{
printf("你还有%d次机会\n", count);
printf("你要猜的数字是:");
scanf("%d", &guess);
//判断玩家猜大还是猜小
if (guess > n)
{
printf("猜大了\n");
}
else if (guess < n)
{
printf("猜小了\n");
}
else
{
printf("恭喜你!猜对了!\n");
break;//结束游戏
}
//每猜错一次就让count-1
count--;
if (count == 0)
{
printf("很遗憾!你的5次机会已用光\t谜底数字是:%d\n", n);
break;//结束游戏
}
}
}
int main()
{
//函数声明
void menu();
void game();
int input = 0;//用于选择play 或 exit
//使用time函数的返回值设置种子
//因为srand函数的参数是unsigned int类型,所以将time函数的返回值强制类型转换
srand((unsigned int) time(NULL));
do
{
menu();//调用menu函数
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("玩游戏");
game();//调用game函数
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("输入错误!请输入0或1\n");
break;
}
} while (input);//这里不需要对input进行判断,0就循环结束;1就循环继续;输入错误(也是非0),循环继续
return 0;
}
上述代码中其实只是增加了第65行这一行代码,使用time函数要引用time.h头文件。
作此修改后我们可以再次运行进行测试,测试结果如下:
其实所讲的“基准值”也被叫做:种子
time函数返回的时间差也被叫做:时间戳