我想练习一点,将逻辑分离成函数,并在原始的“猜我的数字游戏”中使用基本递归,就像一种方式来看我在C编程中的位置。
以下是代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
char playAgain()
{
printf("\nDo you wanna play again? ");
char resp = 0;
while (TRUE) {
scanf("%c", &resp);
if (resp == 'y') break;
if (resp == 'n') break;
}
return resp;
}
void play()
{
srand((int)time(NULL));
int num = rand() % 10 + 1;
int guess = 0;
int flag = 0;
int attempts = 0;
printf("\nGuess the number: \n");
while (TRUE) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
attempts++;
}
else if (num < guess)
{
printf("Too high! ");
attempts++;
}
else if (num == guess)
{
attempts++;
printf("You won! You did it in %d attempts", attempts);
char yo = playAgain();
if (yo == 'y') play();
else if (yo == 'n') exit(0);
else {
printf("Error!");
exit(1);
}
}
}
}
int main()
{
return play();
}
一切正常但我只是在用户说'n'时通过使用exit(0)设法让它退出,我听说这是不好的做法。但是花了几个小时只是在身边徘徊并尝试我能想到的所有其他方式(例如使用旗帜),我无法让它发挥作用。它适用于'y',但是一旦我输入'n',它就不会退出并再次调用playAgain()函数,或者完全冻结(没有任何反应)。
我因为无法解决这个问题而感到羞愧,但我没有想法。除了exit(0)之外还有其他方法让它跳出play()直接在main()中返回0吗?问题似乎是我有一个无限的游戏循环,所以当答案是'n'时,我需要突破循环并退出play()函数,这已被证明是有问题的。我记得当我没有函数时能够轻松地做到这一点,但只是main()中的所有相关代码,但这一点的全部意义是使用函数。例如,我无法弄清楚如何使用返回类型的play(),以便它知道何时退出。
P.S。一如往常,看到人们被指责这种情况的频率,我向你保证这不是功课,因为我一直都在做,只是作为一种爱好进行编程。除了你之外,没有教授我回答:-)相信我,我确实试图找出解决方案,但似乎没有任何效果。这是一个好的与坏的设计的问题,所以它对我的自我教学尤其重要。退出(0)似乎是一个hackish解决方案,没有教育目的。
P.P.S。顺便说一句,我正在使用xCode,程序在其输出窗口中运行。可能不是,但也许这就是“n”退出的原因不起作用?
摘要:代码工作正常,除非答案为'n',在这种情况下它只是问“你想玩吗?”再一次,或根本不做任何事情。
答案 0 :(得分:4)
让您的播放功能返回结果: - int play( void ) {
然后代替exit(1)
和exit(0);
使用return 1;
和return 0;
在游戏结束时return 0;
然后在主
{
return play();
}
而不是递归,只需做一个循环
int play( void)
{
srand((int)time(NULL));
int num;
int guess;
int flag;
while(1)
{
num = rand() % 10 + 1;
guess = 0;
flag = 0;
printf("\nGuess the number %d: \n", num);
while (1) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
}
else if (num < guess)
{
printf("Too high! ");
}
else if (num == guess)
{
printf("You won!");
char yo = playAgain();
if (yo == 'y') break;
else if (yo == 'n') return 0;
else {
printf("Error!");
return 1;
}
}
}
}
}
如果你想要更多的游戏引擎类型方法
enum {
GUESS,
GAMEOVER,
QUIT,
} GAME_STATES;
typedef struct
{
enum GAME_STATES state;
int num;
int game_over;
} guessing_game_t;
void init_game(guessing_game_t* g)
{
g->state = GUESS;
g->game_over = 0;
g->num = rand() % 10 + 1;
}
void evaluate_guess(guessing_game_t* g, int guess)
{
if(g->num == guess)
{
printf("You won!");
g->state = GAMEOVER;
}
else if (g->num > guess)
{
printf("Too low! ");
}
else if (g->num < guess)
{
printf("Too high! ");
}
}
int input_guess( void )
{
int guess;
scanf("%d", &guess);
return guess;
}
void play_again( guessing_game_t* g)
{
char resp = 0;
printf("\nDo you wanna play again? ");
scanf("%c", &resp);
if (resp == 'y') init_game(g);
if (resp == 'n') g->state = QUIT;
}
void play( guessing_game_t* g)
{
while(g->state != QUIT)
{
switch(g->state)
{
case GUESS:
evaluate_guess(g, input_guess());
break;
case GAMEOVER:
play_again(g);
break;
}
}
}
int main()
{
guessing_game_t game;
init_game(&game);
play(&game);
}
答案 1 :(得分:0)
你可以在继续循环之前放置一个标志 将while(true)更改为while(continue_play),continue_play是示例
的标志名称然后,
if (yo == 'n') exit(0);
可以改为
if (yo == 'n') continue_play=false;
并执行exit(1)case
的类似操作 然后continue_play将成为退出该函数的标志。
答案 2 :(得分:0)
由于您可以递归调用play()
函数,我认为退出exit(0)
是正确的选择。
Acutall,我认为使用递归来实现play()
根本不是一个好主意,两个无限循环就足够了。你可以像这样实现它:
void play(void)
{
srand((int)time(NULL));
int num;
int guess = 0;
int attempts = 0;
int try_again = 1;
while (try_again) {
num = rand() % 10 + 1;
printf("\nGuess the number: \n");
while (TRUE) {
scanf("%d", &guess);
if (num > guess)
{
printf("Too low! ");
attempts++;
}
else if (num < guess)
{
printf("Too high! ");
attempts++;
}
else if (num == guess)
{
attempts++;
printf("You won! You did it in %d attempts", attempts);
char yo = playAgain();
if (yo == 'n') try_again = 0;
break;
}
}
}
}
答案 3 :(得分:0)
您还有一件事程将结束:您的代码逻辑就像你也可以使用break;
代替exit(0)
和exit(1)
因为你使用while循环你将打破它,程序将结束。