如何将此代码转换为使用 while 循环而不是递归?
void game(void)
{
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
if (level < 8) {
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
game();
}
else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
game();
}
}
else {
printf("Great Job, You Won!");
}
}
我尝试从 while 循环开始并尝试向后工作,但我迷失在代码的海洋中
你的程序中有一些奇怪的事情,我稍后会再讨论,但首先,让我们关注这个问题:
如何将此代码转换为使用 while 循环而不是递归?
有很多方法可以做到这一点...
当前的递归调用,即
game();
,不带参数,也不使用返回值。因此,摆脱递归并保持完全相同的功能的一个非常简单的方法可能是:
在所有现有代码周围添加一个
while(1)
循环
用
continue;
语句替换当前的递归调用
当循环要终止时添加
break;
语句
看起来像:
void game(void)
{
while(1) { // Add a while loop
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
if (level < 8) {
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
// game();
continue; // Start a new round of the game
}
else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
//game();
continue; // Start a new round of the game
}
}
else {
printf("Great Job, You Won!");
break; // End the game by breaking out of the while loop
// This could also be a return; statement
}
}
}
上述解决方案保留了原始程序的结构。如果我们允许一些(小的)重组,我们可以做得更好一点。
void game(void)
{
while(1) {
int answer;
printf("%s", Questions[level]);
scanf("%d", &answer);
// Check if the game has finished
if (level >= 8) {
printf("Great Job, You Won!");
return; // or break;
}
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
} else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
}
上述版本不是检查“游戏是否继续”,而是检查“游戏已完成”,如果是,则返回。通过这样做,我们不再需要显式的
continue;
语句。
现在回到程序中的“奇怪”的事情:
当用户赢得游戏时(即
level
达到8),代码仍会再问一个问题,一旦输入答案,程序就会结束。 这可能不是故意的...
此外,完成游戏的唯一方法就是赢得游戏(即连续多次回答正确)。我希望用户能有一种方式说“我放弃”
最后,您的代码存在严重问题,可能会导致程序崩溃或无限循环等错误。一定要检查
scanf
的返回值! (见尾注)
解决这些问题并进行更多的重组可能会产生如下计划:
void game(void)
{
level = 0; // Assuming a new game always starts a level zero
while(1) {
int answer;
printf("%s", Questions[level]);
if (scanf("%d", &answer) != 1) {
// Wrong input or input error
// Add error handling... but for now, just terminate
exit(1);
}
// Let the user end the program with a negative input
if (answer < 0) {
printf("Sorry to see you leave before finishing the game. Bye.\n");
return 0;
}
if (is_right(level, answer)) {
printf("Good Job!\n");
level += 1;
// Check if the game has finished
if (level == 8) {
printf("Great Job, You Won!");
return;
}
} else {
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
}
尾注:
虽然确实应该检查
scanf
的返回值,但更好的建议是:
切勿使用
scanf
。
表面上
scanf
看起来是一种获取用户输入的简单方法,但事实是它有很多陷阱,只有真正的专家才能使用它(他们可能不会)。以(不正确使用)scanf
为问题根本原因的 SO 问题数量非常多。他们不断地来......
所以忘记你曾经听说过
scanf
。如果您确实喜欢 scanf
的功能,那么通过使用 fgets
和 sscanf
,您(几乎)总是会做得更好。
很难称之为递归。
void game(void)
{
int answer;
while (level < 8)
{
printf("%s", Questions[level]);
if(scanf("%d", &answer) != 1){ /* handle error */}
if (is_right(level, answer))
{
printf("Good Job!\n");
level += 1;
}
else
{
printf("Sorry, you got the wrong answer. Try Again! \n");
sleep(1);
system("clear");
level = 0;
}
}
printf("Great Job, You Won!");
}