问题:
先由计算机“想”一个1~100之间的教请玩家猜,如果猜对了,则显示“Right!”",并赞美一番;否则显示“Wrong !”,并提示所猪的数是大了还是小了。最多可以猜7次。如7 次仍未猜中,则停止本次猜数。每次运行程序可以反复猜多个数,直到玩家想退出时才结束。
解题思路:首先从整体把握,程序要完成的功能是“想数”、“猜数”和“是否继续猜”。如果继续猜,再重新开始“想数”、“猜数”......流程图如下:
其中,“生成数字”和“猜数字”是两个子模块,在做整体设计时只需要想它们应该做什么,而不用想怎么做。按此流程,编写程序的框架代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<time.h>
#include<assert.h>
#include<stdlib.h>
#define MAX_NUMBER 100
#define MIN_NUMBER 1
#define MAX_TIMES 7
int MakeNumber(void);
void GuessNumber(int number);
int main(void)
{
int number;
int cont;
srand(time(NULL));
//主功能开始
do {
number = MakeNumber();
GuessNumber(number);
printf("Continue?(Y/N):");
cont = getchar();
while (getchar() != '\n')//读走回车符及其之前的所有无用字符
{
;
}
} while (cont != 'N' && cont != 'n');
//主功能结束
return 0;
}
在自顶向下完成程序框架之后,再对子模块逐个击破。先细化MakeNumber()。它的实现并不复杂,调用主函数rand()生成随机数,通过运算把数值控制在 MIN_NUMBER和MAX_NUMBER之间。
//函数功能:返回MIN_NUMBEER和MAX_NUMBER之间的一个随机数
int MakeNumber(void)
{
int number;
number = (rand() % (MAX_NUMBER - MIN_NUMBER + 1)) + MIN_NUMBER;
assert(number >= MIN_NUMBER && number <= MAX_NUMBER);
return number;
}
上面使用了assert()测试算法的正确性。然后,让我们再把目光转向GuessNumber()。弄清它的逻辑是关键。代码如下:
void GuessNumber(int number)
{
int guess;
int times = 0;
assert(number >= MIN_NUMBER && number <= MAX_NUMBER);
do {
times++;
printf("Round%d:", times);
scanf("%d", &guess);
while (getchar() != '\n')//读走换行符及其之前所有无用字符
{
;
}
if (guess > number)
{
printf("Wrong!Too high.\n");
}
else if (guess < number)
{
printf("Wrong!Too low\n");
}
} while (guess != number && times < MAX_TIMES);
//输出结果
if (guess == number)
{
printf("Congratulations!You'ra so cool!\n");
}
else
{
printf("Mission failed after %d attempts.\n", MAX_TIMES);
}
}
这样,通过三个相对独立思考过程,我们完成了这个程序。每个独立的函数都不复杂,但如果我们把它们都揉为一体,放入main(),那将是多重循环嵌套,复杂分支结构,程序的清晰性会大大下降。