有没有办法避免使用exit(0)?

时间:2014-03-03 02:45:48

标签: c recursion

我想练习一点,将逻辑分离成函数,并在原始的“猜我的数字游戏”中使用基本递归,就像一种方式来看我在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',在这种情况下它只是问“你想玩吗?”再一次,或根本不做任何事情。

4 个答案:

答案 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循环你将打破它,程序将结束。