【问题标题】:How can I use conditionals and loops to simulate the Monty Hall porblem?如何使用条件和循环来模拟 Monty Hall 问题?
【发布时间】:2020-05-15 16:48:42
【问题描述】:

我开始学习编程,现在正在使用 c 和条件循环。我想对蒙蒂大厅的车后门问题进行交互式模拟(3扇门中的一扇后面有一辆车,另外两扇有山羊。用过的挑选一扇后,蒙蒂揭示了其他一扇后面有山羊它并允许用户切换到另一扇门)。根据我从 C Programming 中读到的内容,K.N. 提出了一种现代方法。 King,这应该可以通过一些函数、条件和循环来实现。但是我编写的代码在我的一个函数中无限循环,我不知道为什么,这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// A function that gets a valid door input from the user
int chooseDoor(){
    int choice = 0;
    while(choice < 1 || choice > 3){
        printf("Choose a door from 1 to 3: ");
        scanf("%d",&choice);
        printf("%d\n", choice);
    }
    return choice;
    }
// A function to get a valid yes or no response from the user
int validateYn(){
    char yn[1];
    fgets(yn,1,stdin);
    while(yn[0] != "Y" && yn[0] != "y" && yn[0] != "N" && yn[0] != "n"){
        printf("Error: Please enter Y or N: ");
        fgets(yn,1,stdin);}
    if(yn[0] == "Y" || yn[0] == "y"){
        return 1;}
    else{
        return 0;}}
int main(){
    bool play = true; //conditional boolean to repeat the game
    while(play){
        int car, shown, other, choice; //initialisers for the door with the car, door that monty will reveal, the remaining door and door chosen by player
        bool swap;
        car = rand()%3; //select a random door between 1 and 3
        choice = chooseDoor(); //call function to get user input of chosen door
        printf("You picked door #%d", choice);
        // A loop to find the lowest door that is not picked by the user and has a goat behind it
        for(int i = 0; i<3; ++i){
            if( i == car || i == choice){
                continue;}
            shown = i;
            break;}
        // A loop to find the remaining door besides the one revealed and the one user picks
        for(int i = 0; i<3; ++i){
            if( i == car || i == choice || i == shown){
                continue;}
            other = i;
            break;}
        printf("Monty opens door #%d, there's a goat!\nWould you like to switch to door #%d?", shown, other);
        swap = validateYn();
        // Change user choice if user says yes to swap
        if(swap){
            choice = other;}
        // win if user choice had car, lose otherwise 
        if(choice == car){
            printf("Monty opens door #%d, it's the car! You win!", car);}
        else{
            printf("Monty opens door #%d, there's a goat. You lose.", choice);}
        } 
        printf("Would you like to play again?");
        play = validateYn();
return 0;}

我的朋友也告诉我switch语句应该让事情变得更简单,但我不知道如何正确使用它们,谢谢

【问题讨论】:

    标签: c loops conditional-statements


    【解决方案1】:

    您的代码中只有一个问题:您询问用户是否要在循环之外继续。有时它会发生,这不是很难解决的。 您只需将最后一个用户交互代码块(最后一个 printf 和最后一个 scanf)移动到 while 循环括号内。

    我将在此处附上完全有效的代码。我还做了一些更新和更改:

    • 更改了循环迭代。而不是 0..
    • 使用 getchar 更改了 fget,因为您只输入一个字符而不是字符串。
    • 添加了 fflush(stdin) 以释放输入缓冲区,然后您获取一个字符,因为当您获取不同类型的输入时,scanf 可能会发疯并显示混乱的结果。
    • 改变了随机性。现在种子将随着 srand 和 time 改变每次迭代
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h> 
    #include <stdbool.h>
    
    // A function that gets a valid door input from the user
    int chooseDoor()
    {
        int choice = 0;
        while (choice < 1 || choice > 3)
        {
            printf("Choose a door from 1 to 3: ");
            scanf("%d", &choice);
        }
        return choice;
    }
    
    // A function to get a valid yes or no response from the user
    int validateYn()
    {
        char yn;
        yn = getchar();
        while (yn != 'Y' && yn != 'y' && yn != 'N' && yn != 'n')
        {
            printf("Error: Please enter Y or N: ");
            yn = getchar();
        }
        if (yn == 'Y' || yn == 'y')
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    int main()
    {
        srand((unsigned int) time(NULL)); // generating number with better randomness
        bool play = true; //conditional boolean to repeat the game
        while (play)
        {
            int car, shown, other, choice; //initialisers for the door with the car, door that monty will reveal, the remaining door and door chosen by player
            bool swap;
    
            car = 1 + rand() % 3;      //select a random door between 1 and 3
            choice = chooseDoor(); //call function to get user input of chosen door
            printf("You picked door #%d", choice);
            // A loop to find the lowest door that is not picked by the user and has a goat behind it
            for (int i = 1; i < 4; i++) 
            {
                if (i == car || i == choice)
                {
                    continue;
                }
                shown = i;
                break;
            }
            // A loop to find the remaining door besides the one revealed and the one user picks
            for (int i = 1; i < 4; i++)
            {
                if (i == car || i == choice || i == shown)
                {
                    continue;
                }
                other = i;
                break;
            }
            printf("\nMonty opens door #%d, there's a goat!\nWould you like to switch to door #%d? (y/n).\nChoose: ", shown, other);
            fflush(stdin);
            swap = validateYn();
            // Change user choice if user says yes to swap
            if (swap)
            {
                choice = other;
            }
            // win if user choice had car, lose otherwise
            if (choice == car)
            {
                printf("\nMonty opens door #%d, it's the car! You win!", car);
            }
            else
            {
                printf("\nMonty opens door #%d, there's a goat. You lose. ", choice);
            }
            printf("\n\nWould you like to play again?"); //here now it is inside the while loop
            play = validateYn();
        }
        return 0;
    }
    

    提示:尽量让缩进更清晰一点。下次您将能够轻松捕获这种“括号和范围错误”。

    此外,您确实可以通过开关来执行此程序以使其变得简单。它们并不难使用。祝你好运!!

    -丹尼

    【讨论】:

    • 代码很棒,但要注意一点:srand((unsigned int) time(NULL)); 在循环中被调用。 fflush(stdin); 是未定义的行为。
    • 感谢您的建议,刚刚将 srand(...) 移到了循环之外。关于 fflush 的未定义行为是什么意思? @KamilCuk
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多