c - 如何使用条件和循环来模拟 Monty Hall 问题?
问题描述
我开始学习编程,现在正在使用 c 和条件循环。我想对蒙蒂大厅的车后门问题进行交互式模拟(3扇门中的一扇后面有一辆车,另外两扇有山羊。用过的挑选一扇后,蒙蒂揭示了其他一扇后面有山羊它并允许用户切换到另一扇门)。根据我从 C Programming 中读到的 KN 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语句应该会让事情变得更容易,但我不知道如何正确使用它们,谢谢
解决方案
您的代码中只有一个问题:您询问用户是否想在循环之外继续。有时它会发生,这不是很难解决的。您只需将最后一个用户交互代码块(最后一个 printf 和最后一个 scanf)移动到 while 循环括号内。
我将在此处附上完全有效的代码。我还做了一些更新和更改:
- 更改了循环迭代。而不是 0..<3; ++i 现在是 1..<4; 我++
- 用 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;
}
提示:尽量用缩进更清楚一点。下次您将能够轻松地捕捉到这种“括号和范围错误”。
此外,这是真的,您可以使用开关来执行此程序以使其变得容易。它们并不难使用。祝你好运!!
-丹尼
推荐阅读
- javascript - 为什么我在 React 中看不到路由结果?
- c# - 我需要在非静态类构造函数中引用非静态类的变量。[C#]
- python - 如何在线性规划的目标函数中编写成本板?
- javascript - Chrome 扩展程序可从每个选项卡的特定位置复制数据
- java - 如何在不增加堆大小的情况下解决生产中的内存不足问题
- java - 在 Selenium 中使用 findElements 的 NullpointerException 并且未处理 alter
- python - 为什么我的非正态样本通过正态性检验?
- python - 如何使用 self 调用类中的函数
- azure-active-directory - 使用 Azure AD Graph API 在 B2C 中添加自定义属性(扩展)未显示在 Azure 门户用户属性刀片中
- subquery - 通过过滤日期编写子查询