引言
想成为一个程序员,要学习的除了知识,还要知道怎么放松,如果你想体会到自己创造一个游戏带来的成就感,不妨跟着不累子先从这个简单的猜数字游戏开始!
思路
我们要创建的这个游戏,首先思考一下完成它的思路吧:
1.生成一个随机数字,作为我们要猜的对象
2.我们输入一个数字,作为我们猜测的数字
3.判断我们猜的数字和答案是否相同,如果相同则显示获胜,如果不同则提示我们猜大了还是猜小了
4.循环执行 2-3 ,或者设置一个最大猜测次数,在次数用完后还没猜出则失败
5.稍加修改、完善
实现
生成一个随机数字
使用 r 存储生成的随机数(random意为“随机”)
#include<stdio.h>//由于我们后面一定会用到printf和scanf函数,所以这里先包含它们的头文件
#include<stdlib.h>//rand和srand函数的头文件
#include<time.h>//time函数的头文件
int main()
{
srand((unsigned int)time(NULL));//设置随机数生成器的种子
int r = rand();//将生成的随机数放到 r 里
return 0;
}
注:(unsigned int) 的作用为强制转换时间戳格式为“无符号整型”,这里不强制转换也可以,大多数编译器会自动转换
以上生成随机数的方法在我的另一篇文章中有讲哦~
如果不会的话建议跳转到我的上一篇博客,以后的另外几款小游戏中我们也会用到这个方法生成随机数的~
C语言中如何生成随机度高的随机数_c语言中随机数怎么写-优快云博客
输入一个数字,并进行判断
使用 g 存储我们猜测的数字 (guess意为“猜测”)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand((unsigned int)time(NULL));
int r = rand();
int g;
scanf("%d", &g);//输入并存储猜测的数字
if (g < r)//进行判断
{
printf("猜小了!\n");
}
else if (g > r)
{
printf("猜大了!\n");
}
else if (g == r)
{
printf("猜对了!\n");
}
return 0;
}
循环执行游戏内容
我们将猜测和判断部分放入一个循环中,使得玩家可以多次猜测
for (;;)//判断部分(两个分号之间)为空,该循环为死循环
{
scanf("%d", &g);
if (g < r)
{
printf("猜小了!\n");
}
else if (g > r)
{
printf("猜大了!\n");
}
else if (g == r)
{
printf("猜对了!\n");
break;//这种情况结束循环
}
}
此时我们运行这个程序,可以正常游玩。
但是仍然存在一些问题:
1.缺少了一个菜单
2.输入一个符号(如a),并不会显示输入错误
3.猜到了这个数字后并不会结束游戏或问你是否再玩一遍
完善游戏内容
封装游戏内容
我们将以上游戏内容部分放到一个单独的函数Game(game意为“游戏”)中,便于后续操作
这里我们把设置随机数的部分也放到该函数中,使得不结束程序而重新游玩后能生成一个新的随机数
但是设置随机数种子的部分不用移动:种子每运行一次程序设定一次就行
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int Game()//定义游戏函数
{
int r = rand();
int g;
for (;;)//循环输入
{
scanf("%d", &g);
if (g < r)
{
printf("猜小了!\n");
}
else if (g > r)
{
printf("猜大了!\n");
}
else if (g == r)
{
printf("猜对了!\n");
break;//这种情况结束循环
}
}
}
int main()
{
srand((unsigned int)time(NULL));//这里不用放到Game函数中
Game();//引用游戏函数
return 0;
}
添加菜单
我们要让玩家知道这个游戏是干嘛的,同时又不让这个游戏显得过于简洁,我们可以添加一个菜单
此处添加菜单的方法为创建一个专门的函数Menu(menu意为“菜单”),每次调用时打印菜单
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Menu()//我们不需要该函数在被调用后返回一个值,所以返回类型为 void
{
printf("*********************************\n");
printf("************猜数字游戏***********\n");
printf("**************1.游玩*************\n");
printf("**************0.退出*************\n");
printf("*********************************\n");
}
int Game()
{
Menu();//引用菜单函数以打印菜单
int r = rand();
......//其余内容省略
}
int main()
{
srand((unsigned int)time(NULL));
Game();
return 0;
}
当打印完菜单后,我们还要检测玩家输入的值是0还是1或者其他的什么
来决定接下来是退出游戏还是开始游戏:
注:
do
{循环体}
while(条件);
这个循环语句是先执行一次循环体,执行完一次后再看是否满足条件,满足则再次执行循环体,不满足则直接进行下一步
int Game()
{
Menu();
int input = 0;
do {
printf("开始?(1/0):\n");
if (scanf("%d", &input) != 1)//如果读取失败
{
printf("不要输入一些奇奇怪怪的东西呀!\n");
while (getchar() != '\n');//清空输入缓冲区,不懂可忽略
input = 0;
continue;//回到循环开始
}
if (input == 1)//这种情况在经过下面while后的判断后不再进入该输入循环,而是直接进入游戏
{
printf("祝你好运~\n");
}
else if (input == 0)//这种情况直接结束Game函数,并返回 0
{
printf("这么好玩的游戏都不玩,等着后悔吧,哼~\n");
return 0;
}
else//这种情况在经过下面while后的判断后再次进入该输入循环
{
printf("不要输入一些奇奇怪怪的东西呀!\n");
}
} while (input != 1);//当input不为 1 时再次进入该循环
int r = rand();
//能运行到这里说明玩家选择了开始游戏,于是我们提示玩家输入一个数字:
printf("开始猜测吧~\n");
for (;;)//猜测部分的 for 循环,这里只进行了部分修改
{
if (scanf("%d", &g) != 1)//这里也是检测输入是否错误,和上面一样
{
printf("不要输入一些奇奇怪怪的东西呀!\n");
while (getchar() != '\n');//清空输入缓冲区
input = 0;
continue;//回到循环开始
}
......//其余内容不变,此处省略
}
}
注:
1.如果scanf函数读取成功则返回 1 ,以上 if 后面的条件是scanf函数执行不成功
2.while (getchar() != '\n');作用为清空缓冲区,以防缓冲区残留字符导致意外故障(如果这里不懂可以照抄跳过这里的理解,后续文章不累子会专门介绍这个哦~)
3.if 语句中的 continue 作用为重新返回 do while 循环的开头
4.玩家选择 0 (即结束游戏)的后续处理情况在下面一点中合起来讲
大家也许会疑惑,do while循环中为什么有两种输入错误的情况?
第一种是玩家输入了非数字的字符如:a,b,c,!,? 等,这种情况下 scanf 读取失败,被上面的 if 语句处理
第二种是玩家输入了既不是 0 又不是 1 的数字如:666,123 等,这种情况scanf读取成功,上面的 if 语句除了不了,被下面的 if 语句处理
胜利后的完善
在添加了以上内容后,我们能正常猜测,但猜对了后程序不会自动结束
那么当我们猜对了后怎么才能返回游戏开头并重新选择是否再来一次呢?
还记得我们猜测部分的循环吗?这里只要修改一条语句就行
int r = rand();
int g;
for (;;)//循环输入
{
......//省略部分不变
else if (g == r)//运行进这种情况证明猜对了,结束 Game 函数并返回 1
{
printf("猜对了!\n");
return 1;//仅此处将 break 改为 return 1
}
}
这里我们再运行程序并猜测直到猜对了后,程序会自动回到 main 函数的循环部分,此循环为死循环,于是会再次调用 Game 函数 (打印菜单,询问玩家要不要游玩等)
也就是我们现在实现了胜利后再次游玩的功能
但如果我们输入 0 (不想玩了)程序并不会退出,而是会继续调用 Game 函数,这个时候也只需稍微修改 (希望你还记得上一点里提到的 return 0; 的作用):
int main()
{
srand((unsigned int)time(NULL));
for (;;)
{
if (Game() == 0)
{
break;
}
}
return 0;
}
我们将 main 函数改成上面这样,其实也就是把调用 Game 的部分放进了 if 的判断条件里
以下为思路:
如果我们在执行 Game 函数的过程中(执行游戏内容时)遇到了 return 0;
此时Game函数会忽略后面的任何语句直接结束并返回 0
那么再回到 main 函数中后 Game 返回的值就是 0,也就是符合上面 if 的判断条件
于是执行 break 指令结束 main 函数里的循环,导致程序结束运行
反之(在Game函数中没有遇到 return 0 或者返回的不是 0)
则在回到主函数后 Game 的返回值不是 0,不满足 if 的判断条件
此时再次执行 main 里的循环(打印菜单,询问玩家要不要游玩等)
敲到这里,其实一个完整的猜数字游戏就已经实现了,下面的部分是一些点缀
限制生成的随机数范围
上面的游戏生成的随机数范围在 0 ~ 32767 间,那么怎么使生成的随机数在一个特定范围内呢?
这里请转到我这篇文章的”限制范围“一节:C语言中如何生成随机度高的随机数_c语言中随机数怎么写-优快云博客
增加猜测次数限制
这个更改也很简单,我们对 Game 中的 for 循环稍作更改:
// int g;
int i = 0;
// for (;;)
// {
// if (scanf("%d", &g) != 1)//如果读取失败
// {
// printf("不要输入一些奇奇怪怪的东西呀!\n");
//
// while (getchar() != '\n');//清空输入缓冲区
// input = 0;
// continue;//回到循环开始
// }
//以上注释部分未作更改
if (g < r)
{
printf("猜小了!\n");
i++;//猜错了,i 自动加 1
}
else if (g > r)
{
printf("猜大了!\n");
i++;//猜错了,i 自动加 1
}
else if (g == r)
{
printf("猜对了!\n");
return 1;
}
if (i == 10)//判断 i 是否为 10,如果 i 等于 10 就直接结束 Game 函数并返回 1
{
printf("猜了10次都猜不出?What can I say?\n");//打印 what can I say 表明玩家输了
return 1;//返回的是 1,所以在回到 main 函数后并不会结束程序,而是再次进入 Game 函数询问玩家要不要再来一次
}
}
上面我们增加了变量 i ,并通过 i++ 和对 i 的判断实现了对玩家猜测次数的限制
总结
通过上面的思路、实现、完善部分你应该也敲出了一款有意思的小游戏吧!
这何尝不是学习的一种方式呢?
对一个代码的初学者来说,最重要的就是体会到这些冰冷的代码给人带来的成就感,这样我们才能坚持一步步学习下去
当然对不累子来说最重要的还有那个,就是......点赞收藏关注什么的......这些也能激励不累子后续继续创作三子棋、扫雷等更有意思的小游戏的博客教程哦~
反正这些都是免费的,就满足不累子嘛好不好~