做者 谢恩铭,公众号「程序员联盟」。 转载请注明出处。 原文:www.jianshu.com/p/7d03f054c…git
《C语言探索之旅》全系列程序员
上一课是 C语言探索之旅 | 第一部分第九课:循环语句 。github
通过前面这么多课的努力,咱们终于迎来了第一个比较正式的程序:一个 C语言小游戏。编程
虽然这个游戏没有图形界面,是命令行的形式,可是不论怎样,这都是一个小小的里程碑。bash
咱们的目的是让你们看到通过以前几课的学习,你已经能够完成一些有意思的事了。dom
虽然咱们知道理论是很好的,可是若是咱们不能把所学的理论付诸实践,那也很没有意思。函数
信不信由你,你其实已经有水平实现本身的第一个有意思的程序了。学习
在动手编程以前,得先跟你们说一下这个程序是干什么的。ui
咱们能够称呼这个游戏为《或多或少》。spa
游戏的原理是这样:
每一轮电脑从 1 到 100 中随机抽一个整数。
电脑请求你猜这个数字,所以你要输入一个 1 到 100 之间的整数。
电脑将你输入的数和它抽取的数进行比较,并告知你的数比它的数大了仍是小了。
而后它会再次让你输入数字,并告诉你比较的结果。
一直到你猜到这个数为止,一轮结束。
游戏的目的,固然就是用最少的次数猜到这个“神秘”数字。虽然没有绚丽的图形界面,可是或多或少,这都是你的第一个游戏了,应该值得骄傲。
下面演示了一轮的样式,你要编程来实现它:
这个数字是什么?50
猜小了!
这个数字是什么?75
猜小了!
这个数字是什么?85
猜大了!
这个数字是什么?80
猜大了!
这个数字是什么?78
猜小了!
这个数字是什么?79
太棒了,你猜到了这个神秘数字!!
复制代码
但你们要问了:“如何随机地抽取一个数呢?不知道怎么办啊,臣妾作不到啊。”
诚然,咱们还没学习如何来产生一个随机数。让亲爱的电脑兄来作这个是不简单的:它很会作运算,可是要它随机选择一个数,它还不知道怎么作呢。
事实上,为了“尝试”获得一个随机数,咱们不得不让电脑来作一些复杂的运算。好吧,归根结底仍是作运算。
咱们有两个解决方案:
请用户经过 scanf 函数输入这个神秘数字,那么就须要两个玩家咯。一个选数字,一个猜数字。
背注一掷地让电脑来为咱们自动产生一个随机数。好处是:只须要一个玩家,能够自娱自乐。缺点是:须要学习该怎么作...
咱们来学习用第二种方案编写这个游戏,固然你也能够以后本身编写第一种方案的代码。
为了生成一个随机数,咱们要用到 rand() 函数(rand 是英语 random 的缩写,表示“随机的”)。
顾名思义,这个函数能为咱们生成随机数。可是咱们还想要这个随机数是在 1 到 100 的整数范围内(若是没有限定范围,那会很复杂)。
咱们会用到如下的形式:
srand(time(NULL));
mysteryNumber = (rand() % (MAX - MIN + 1)) + MIN;
复制代码
第一行(srand 函数)用于初始化随机数的生成器。srand 实际上是 seed random 的缩写。seed 在英语中是“种子”的意思。
给出 百度百科 的简单解释:
srand 和 rand 配合使用产生伪随机数序列。rand 函数在产生随机数前,须要系统提供的生成伪随机数序列的种子,rand 根据这个种子的值产生一系列随机数。若是系统提供的种子没有变化,每次调用 rand 函数生成的伪随机数序列都是同样的。srand(unsigned seed) 经过参数 seed 改变系统提供的种子值,从而可使得每次调用 rand 函数生成的伪随机数序列不一样,从而实现真正意义上的“随机”。一般能够利用系统时间来改变系统的种子值,即 srand(time(NULL)),能够为 rand 函数提供不一样的种子值,进而产生不一样的随机数序列。
所谓的“伪随机数”指的并非假的随机数,这里的“伪”是有规律的意思。其实绝对的随机数只是一种理想状态的随机数,计算机只能生成相对的随机数即伪随机数。计算机生成的伪随机数既是随机的又是有规律的 -- 一部份遵照必定的规律,一部份则不遵照任何规律。好比“世上没有两片形状彻底相同的树叶”,这正点到了事物的特性 -- 规律性;可是每种树的叶子都有近似的形状,这正是事物的共性 -- 规律性。从这个角度讲,咱们就能够接受这样的事实了:计算机只能产生伪随机数而不是绝对的随机数。
经过 time() 函数来得到计算机系统当前的日历时间(Calendar Time),处理日期时间的函数都是以本函数的返回值为基础进行运算。其原型为:time_t time(time_t * t); 若是你已经声明了参数t,你能够从参数t返回如今的日历时间,同时也能够经过返回值返回如今的日历时间,即从一个时间点(例如:1970 年 1 月 1 日 0 时 0 分 0 秒)到如今此时的秒数。若是参数为空(NULL),函数将只经过返回值返回如今的日历时间。
若是咱们在使用 rand 函数前没有用 srand 函数制定 seed 的值,或者虽然用了 srand 函数,可是给它的参数是一个常量,好比 srand(1),那么每次程序运行 rand 产生的数字都是同样的。只有用例如 time() 函数来给一个每次都不同的 seed 值,才能使得 rand 的返回值不同,才能作到“随机”。
srand 函数只须要在 rand 函数前面调用一次就够了,也只能调用一次,以后你想要调用 rand 函数几回都无所谓,可是每一个程序中不能用两次 srand 函数,切记。
上面代码格式中的 MAX 和 MIN 是常量或 const 类型的变量。MAX 是 Maximum 的缩写,表示“最大”。MIN 是 Minimum 的缩写,表示“最小”。顾名思义,MAX 和 MIN 分别是你规定的范围的最大值和最小值。
建议在程序的一开始定义这两个 const 类型的变量:
const int MAX = 100, MIN = 1;
复制代码
为了程序可以顺利运行,咱们须要引入三个库:
咱们之前的课说过库的做用。库里面提供一些定义好的函数,好比 time.h里面就有咱们的 time() 函数,stdlib 中有 rand 和 srand 函数。
好啦,我不继续透露了。咱们已经说明了游戏的原理,给出了一轮游戏的运行例子,也给出了主要的随机数生成代码,该轮到你来完成游戏的代码了。加油,相信你能够的!
但愿你们本身先写代码,查阅一些资料,或复习前面几课的内容。运行成功了或实在写不出来才来看答案。
如下给出个人版本。固然了,这个游戏的代码能够有不一样的版本。你彻底能够本身发挥。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (int argc, char** argv)
{
int mysteryNumber = 0, guessNumber = 0;
const int MAX = 100, MIN = 1;
// 生成随机数
srand(time(NULL));
mysteryNumber = (rand() % (MAX - MIN + 1)) + MIN;
/* 程序的循环部分, 若是用户没猜中数字,就一直进行循环 */
do
{
// 请求用户输入所猜数字
printf("这个数字是什么 ? ");
scanf("%d", &guessNumber);
// 比较用户输入的数字和神秘数字
if (mysteryNumber > guessNumber)
printf("猜小了 !\n\n");
else if (mysteryNumber < guessNumber)
printf("猜大了 !\n\n");
else
printf ("太棒了,你猜到了这个神秘数字 !!\n\n");
} while (guessNumber != mysteryNumber);
return 0;
}
复制代码
程序的解释(从上到下的顺序):
预处理指令:就是开头的那三行,以 # 开始。include 是英语“包含,引入”的意思,因此表示引入什么库。
变量:这个游戏中,不须要太多变量,只有一个用于记录用户输入的数字的变量 guessNumber,和一个电脑随机抽取的数字 mysteryNumber。guess 表示“猜”,mystery 表示“神秘”,number 表示“数字”。咱们也定义了两个常量(const 变量,其实叫只读变量比较准确)MAX 和 MIN,值分别是 100 和 1。这样定义的好处是,若是你后面要改这两个数值,会很方便,直接改这一行的两个值就行了。若是没有用 MAX 和 MIN 而是在程序里每个地方写 100 和 1 的话,那若是之后要改数值,工做量就大了。
随机数:srand 和 rand 那两行,用于生成在 1 和 100 之间的一个随机数,值赋给 mysteryNumber。
循环:我选择用 do...while 循环。理论上一个 while 循环也能够作到,但我以为这里用 do...while 可能更合逻辑。为何呢?还记得 do...while 循环的特色吗?就是循环体里的指令至少会执行一次,不像 while 循环可能一次也不执行。这里咱们至少要让用户输入一次数字,不可能用户一次也不输入就猜到了数字。
在每一次进入循环体里运行时,咱们都请求用户输入一个数字,而且把这个数字的值赋给 guessNumber 变量,接下来就比较 guessNumber 和 mysteryNumber(须要猜的数字)的大小:
循环也须要一个条件,咱们给出的条件是:只要猜的数字和神秘数字不同,循环就继续。
如今这个游戏仍是很基础很简单的,可是能够有如下的改进方案:
增长一个记录步数的计数器,在你猜对的时候输出:“太棒了,你用**步猜到了这个神秘数字!”
目前的程序只进行一轮就结束了,若是玩家不过瘾,还想继续下一轮怎么办呢?能够加入一个问题:“你还想继续玩吗?”,等待用户输入数字来回答。定义一个布尔值 continue(continue 表示“继续”)来存储用户输入的回答,好比 continue 的默认值是 1,就是用户默认是继续玩下一轮的;但若是用户输入 0,那么程序中止,游戏结束。
增长一个模式:双人模式。能够你出题我来猜。可是我但愿你可以在程序一开始就让用户选择是玩哪种模式,是经典的人机对战,仍是人人对战。若是是双人模式的人人对战,那么就不是用 srand 和 rand 来产生神秘数字了,而是让玩家一经过 scanf 来输入这个数字。
设置几个难度级别,让玩家选择:初级(1-100 中的一个数),中级(1-1000 中的一个数),高级(1-10000 中的一个数)。若是你这样设计,就须要改写 MAX 值了,而此时 MAX 就不能再是一个 const 变量了,必需要把 MAX 前面的 const 去掉,MIN 的还能保留。
你也能够本身增设难度,想出更多好玩的点子来丰富这个游戏。经过完善和改进这个小游戏,你会学到更多。
今天的课就到这里,一块儿加油吧!
下一课咱们来学习函数这个极为重要和有用的内容吧!
我是 谢恩铭,公众号「程序员联盟」运营者,慕课网精英讲师 Oscar 老师,终生学习者。 热爱生活,喜欢游泳,略懂烹饪。 人生格言:「向着标杆直跑」