当前位置:网站首页>【C语言】手把手带你写游戏 —— 猜数字
【C语言】手把手带你写游戏 —— 猜数字
2022-08-02 13:04:00 【凡人编程传】
作者:凡人编程传
系列:C语言初阶(适合小白入门)
说明:以凡人之笔墨,书写未来之大梦
۞前言
这一节我们来写一个小游戏来玩,放心代码不是很多,小白只要仔细一点是能听懂的。废话不多说,咱们直接进入主题
۞游戏实现
写一个猜数字的小游戏,游戏设计要求如下
- 自动生成1-100之间的随机数
- 猜数字
(1)猜对了,提示恭喜你,猜对了,游戏结束.
(2)如果你猜错了,会提示你猜的数字是猜大了,还是猜小了,并且重新猜. - 游戏会一直进行,除非你选择退出游戏
好了看了这些要求,我们就写代码见招拆招吧.
游戏菜单模块实现
一个游戏总是要一个菜单来供用户来选择用户选择是否要玩吧,而且如果要玩一个游戏,至少要运行一次游戏的菜单界面吧。而每次玩完游戏后,是不是也要返回菜单界面来让用户选择是否还要继续玩。上述条件要求,可以知道do…while语句是满足菜单至少运行一次的,还有就是菜单的选择功能,是否继续玩,这里可以用到switch语句。所以我们大概就知道怎么写了。
代码如下:
#include<stdio.h>
void menu() //因为这个函数只是用于打印菜单,所以没有返回值和参数,可以写成void类型
{
printf("*********************************************************\n");
printf("******************** 1.play ***********************\n");
printf("******************** 0.exit ***********************\n");
printf("*********************************************************\n");
}
int main()
{
int input;
do
{
menu(); //打印菜单函数
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("猜数字\n"); //在这里暂且放一个输出语句认为是游戏模块,测试是否选择一可以进入游戏
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n"); //如果用户不按菜单提示输入,还可以重新选择,只要不是0,都可以再次进入循环
break;
}
} while (input); //选择0,循环条件为假,也就退出了游戏
return 0;
}
测试结果:
游戏模块的实现
好了,菜单设计完了,我们就要进行游戏过程的设计了。猜数字游戏的过程主要是系统生成随机数,然后让用户来猜这个游戏。根据用户猜的数字与随机数比较,大了或小了给予提示信息,若猜对了就直接提示猜对了。那么问题来了,随机数从何而来?我们这里介绍一个函数.rand函数刚好可以实现生成随机数字的功能,我们这里阅读一下MSDN来看一下他的基本情况.
这个函数的功能就是生产一个随机数,并且头文件是stdlib.h,没有参数,返回值是int,有了这些信息我们就可以继续写代码了.
#include<stdio.h>
#include<stdlib.h>
void menu() //因为这个函数只是用于打印菜单,所以没有返回值和参数,可以写成void类型
{
printf("*********************************************************\n");
printf("******************** 1.play ***********************\n");
printf("******************** 0.exit ***********************\n");
printf("*********************************************************\n");
}
void game()
{
int ret = rand(); //生产随机数
printf("%d\n", ret); //测试
}
int main()
{
int input;
do
{
menu(); //打印菜单函数
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game(); //实现游戏函数
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n"); //如果用户不按菜单提示输入,还可以重新选择,只要不是0,都可以再次进入循环
break;
}
} while (input); //选择0,循环条件为假,也就退出了游戏
return 0;
}
可是我们在测试随机数生成的时候又发现了新情况
第一次测试结果:
第二次测试结果:
发现了吧,第一次和第二次游戏的数字顺序还是大小都是一模一样,那么这个游戏还有什么挑战性呢?每次都一样只要记下来就行了。那么这是为啥呢?我们不妨再去MSDN文档研究一下这个函数
可以了解到,这个函数的随机值的范围是RAND_MAX(0-32767)之间,且调用之前需要用另外一个函数srand函数来设置随机数生成器.这里就有需要去查一查srand函数该如何使用了.
可以了解的,这个函数的作用是设置一个随机数的起点,且他的参数需要一个unsigned int类型的数字那我们不妨再测试一下加上这个函数.
测试j结果:
可以发现这个函数还要离谱,一直都是365.那么我们改一下参数
还是一直是一个数。但是我们可以得到一个结论,srand()函数参数变化,他的返回值也会变化,那么是不是又要一个随机数。那么这不是矛盾吗?我们就是因为rand()函数需要一个随机数才来设置srand()函数,现在srand()函数又要一个随机数。这里该怎么办啊?我们想想生活中什么是一直在变化的呢?是时间吧!时间又刚好可以转回成一类数字叫时间戳,我们这里是不是可以利用时间戳来给srand()函数一个随机数.那么怎么获得时间戳呢?又要用到一个函数叫做time()函数来获取(了解一下)
这个函数是有参数的我们这里可以把它参数给一个NULL(空指针),因为这里不需要用到他的参数,且因为srand()函数的参数类型是unsigned int 所以还要把它强制类型转换成unsigned int
这时候加上这个函数测试
开始时候确实是随机的,但后来我们速度按快了,他的结果就一样了。这里结果一样的原因涉及到库函数的设计(太深入了),所以我们猜测他是因为每次调用都要重新回随机开始点导致结果一样,所以我们把这个随机数生产的放在主函数内只调用一次就行了
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu() //因为这个函数只是用于打印菜单,所以没有返回值和参数,可以写成void类型
{
printf("*********************************************************\n");
printf("******************** 1.play ***********************\n");
printf("******************** 0.exit ***********************\n");
printf("*********************************************************\n");
}
void game()
{
int ret = rand(); //生产随机数
printf("%d\n", ret); //测试
}
int main()
{
int input;
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"); //如果用户不按菜单提示输入,还可以重新选择,只要不是0,都可以再次进入循环
break;
}
} while (input); //选择0,循环条件为假,也就退出了游戏
return 0;
}
解决了随机数这个大问题,就可以进行猜了。那么因为随机数的范围有点大。这时候我们可以把这个随机数与100取模(结果是0-99)+1就是1-100之间的随机数了.然后根据判断随机数和我们输入数字的大小来判断提示就行了!(这里的%100我用的是定义了一个宏来方便以后你可以增加或减小猜的数字的范围)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUM 100
void menu() //因为这个函数只是用于打印菜单,所以没有返回值和参数,可以写成void类型
{
printf("*********************************************************\n");
printf("******************** 1.play ***********************\n");
printf("******************** 0.exit ***********************\n");
printf("*********************************************************\n");
}
void game()
{
int ret = rand()% 100 + 1; //生产随机数
int get_num = 0;
while(1)
{
printf("请猜数字:>");
scanf("%d", &get_num);
if (ret > get_num)
{
printf("猜小了\n");
}
else if (ret < get_num)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了!\n");
break; //猜对了就直接跳出循环了,进入菜单
}
}
}
int main()
{
int input;
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"); //如果用户不按菜单提示输入,还可以重新选择,只要不是0,都可以再次进入循环
break;
}
} while (input); //选择0,循环条件为假,也就退出了游戏
return 0;
}
۞完整代码,和测试结果
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUM 100
void menu() //因为这个函数只是用于打印菜单,所以没有返回值和参数,可以写成void类型
{
printf("*********************************************************\n");
printf("******************** 1.play ***********************\n");
printf("******************** 0.exit ***********************\n");
printf("*********************************************************\n");
}
void game()
{
int ret = rand()% 100 + 1; //生产随机数
int get_num = 0;
while(1)
{
printf("请猜数字:>");
scanf("%d", &get_num);
if (ret > get_num)
{
printf("猜小了\n");
}
else if (ret < get_num)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了!\n");
break; //猜对了就直接跳出循环了,进入菜单
}
}
}
int main()
{
int input;
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"); //如果用户不按菜单提示输入,还可以重新选择,只要不是0,都可以再次进入循环
break;
}
} while (input); //选择0,循环条件为假,也就退出了游戏
return 0;
}
测试结果
۞结言
好了这一节的内容就到这里,可能这一节的内容对基础薄弱的小白有点难,但都要用于尝试,去慢慢感受这个过程。希望对你有收获,我们下节见!!
边栏推荐
- 路由-Tab切换页面
- Scala基础语法入门(三)Scala中的各种运算符
- Ribbon负载均衡的深度分析和使用
- 什么是 commonjs2
- openGauss数据库基本操作(超详细)
- The uniapp/applet onload method executes the interpretation every time the page is opened
- LeetCode_139_word split
- 第48篇-timestamp2参数分析【2022-08-01】
- 麻烦问一下,对mysql 场景注入故障,是不是不是对mysql server 端注入故障,只是对ja
- RESTful 风格(详细介绍 + 案例实现)
猜你喜欢
随机推荐
Scala基础语法入门(三)Scala中的各种运算符
Automatically generate code generator recommendation-code-gen
消除气泡解救蘑菇h5小游戏源码
js九宫格样式抽奖插件
Object.entries()
FreeRTOS中名称规范
吾爱第三课-修改版权和资源
最小割和对偶图(未完成)
Js scratchable latex style draw plug-in
[b01lers2020]Welcome to Earth-1
Redis全部
js stopwatch countdown plugin
Singleton pattern of seven kinds of writing, you know?
Win11怎么修改关机界面颜色?Win11修改关机界面颜色的方法
图论之Prim,最小生成树该怎么解?
Oracle数据库的闪回技术
80篇国产数据库实操文档汇总(含TiDB、达梦、openGauss等)
svg balloon rises explosion js special effect
分享一个Chrome控制台数据获取的例子
FreeRTOS创建任务--动态创建、静态创建