这篇博客是关于C语言的分支与循环部分基础的解读,为编程新手后续学习数组和函数做良好的铺垫,希望我的分享对大家有所帮助。
前面几讲,我们把 if、switch、while、for、do-while 这些家伙一个个拎出来,单独训练了一遍。 现在到了验收时刻——把它们放进同一个程序里,看它们能不能拧成一股绳。
验收项目:猜数字游戏。
验收标准:你自己玩两把,会觉得有点东西
一、先看需求(养成看题目的好习惯),别急着敲代码
游戏要求很朴素,四条:
1. 给个菜单——1 玩游戏,0 退出游戏;
2. 选 1,电脑自动生成一个 1~100 的随机数,进入猜数字环节;
3. 玩家猜,猜大了提示猜大了,猜小了提示猜小了,猜对了游戏结束;
4. 玩一次不过瘾,还能继续玩。
前三样你都会,第四样——随机数——是本讲唯一的新朋友。
二、随机数:计算机最大的"伪"装
2.1 rand:看起来挺随机,其实很记仇
C 语言给了一个函数叫 rand,声明在 stdlib.h 里:
int rand(void);
它会返回一个伪随机数,范围在 0 ~ RAND_MAX 之间。RAND_MAX 的具体值取决于编译器,但大部分编译器上是 32767。
于是你兴冲冲地写了这段:
#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;
}
第一次运行,五个数字蹦出来,还行,挺像那么回事。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// 用 time 函数的返回值设置种子
// srand 的参数是 unsigned int,所以要把 time 的返回值强制类型转换
srand((unsigned int)time(NULL));
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
再运行几次,每次结果都不一样了。(截图只是当时运行的结果,你的结果不一定和它一样。)
重要提醒:srand 不需要频繁调用,一次运行的程序里调用一次就够了。
有人喜欢把它塞进循环里,一秒内调几千次——种子一模一样,随机数自然一模一样。
2.5 把随机数"关进笼子":限定范围
rand 给的数在 0 ~ 32767 之间,直接拿来玩游戏太离谱了。用取模(%)把它压到需要的区间:
rand() % 100; // 余数范围 0~99
rand() % 100 + 1; // %100 的余数是 0~99,+1 后范围 1~100
100 + rand() % (200 - 100 + 1); // 余数 0~100,加 100 后是 100~200
总结成通式——要生成 a ~ b 之间的随机数:a + rand() % (b - a + 1)
这个公式建议直接背下来,以后写抽奖、掷骰子、洗牌,全靠它。
三、开写:猜数字游戏
一局游戏的完整逻辑:
打印菜单
纯 printf
game()
rand + while + if / else if / else
main()入口
主流程:设种子、循环选菜单
do-while + switch
3.1 一局游戏:game()
void game()
{
int r = rand() % 100 + 1; // 1~100 的随机数
int guess = 0;
while (1) // 猜不对就一直猜
{
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break; // 猜对了,跳出循环
}
}
}
这里 while(1) 配上 break,是很经典的写法:不知道要循环多少次,那就先无限循环,条件满足了再跳出去.
void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
菜单单独抽成一个函数,好处是 main 里一眼就能看懂流程,不会被一堆 printf 迷了眼。
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;
}
三个细节值得注意:
- do-while 而不是 while:菜单至少要显示一次,用 do-while 天然合适,可以反复进行游戏;
- while(input):输入 0 时循环结束,输入 1 继续玩,用输入值本身当循环条件,比再写个 flag 变量清爽;
- switch 的 default:玩家手滑输入个 7,也能优雅地提示"选择错误",而不是默默退出。
数一数,一百行上下。这一百行,把你前四讲学的分支和循环几乎全用上了。
五、给游戏加点"难度"
代码能跑,只是及格线。下面两个游戏扩展,拿去练手:
1. 限制次数。 给游戏增加难度,最多只能猜 5 次,5 次都猜不出来就算失败。
提示:一个计数器 + 循环条件限制 + 猜错后判断次数。
2. 加上计时。 每次猜完数字,显示当前已经花费了多少秒。
提示:游戏开始时记一个时间戳,每次猜完再取一次,两个时间戳相减就是秒数。
改完之后你会发现:需求一变,代码结构就得跟着调整——这比背语法有意思多了。
如果你实在不会,就把游戏需求交给AI吧,不过得自己上手一遍哦,祝你游戏愉快
439



被折叠的 条评论
为什么被折叠?



