我想为Monty Hall问题创建一个简单的模拟,作为一个有趣的,快速的辅助项目.我的计划是创建完整的游戏,有可点击的门和所有的形式,但我首先想创建一种方法来模拟尽可能多的游戏,我想证明给自己,切换门有66%的机会获胜.问题是,我每次都有50/50的赔率.

有人能发现我的模拟有什么问题吗?当我增加门的数量时,切换门后获胜的几率就会增加.然而,有3个门,我总是得到大约50/50,所以我知道有一个问题与我的代码.

private void simulateButton_Click(object sender, EventArgs e)
{
    int wins = 0;
    int losses = 0;
    int attempts = 0;
    int numberOfDoors = 3;

    // Main game loop. Number of simulations can easily be changed from 1000
    for (int games = 0; games < 1000; games++)
    {                               
        List<Door> doors = new List<Door>();
        for (int i = 0; i < numberOfDoors; i++)
        {
            doors.Add(new Door
            {
                Contents = "goat",
                Opened = false,
                PlayerChoice = false,
            });     
        }


        // Randomly pick a door for the car to be in
        Random random = new Random();
        int doorNumWithCar = random.Next(0, numberOfDoors - 1);
        doors[doorNumWithCar].Contents = "car";


        // I set player choice to always be door #1 to make it simpler
        doors[0].PlayerChoice = true;


        // Monty randomly removes one of the 2 doors not chosen by the player.
        // (obviously, he doesn't remove the door with the car)
        int doorMontyOpens;
        while (doors.Count != 2)
        {
            doorMontyOpens = -1;
            while (doorMontyOpens == -1)
            {
                int possibleDoorToBeShown = random.Next(1, doors.Count);

                if (doors[possibleDoorToBeShown].Contents != "car")
                {
                    doorMontyOpens = possibleDoorToBeShown;
                }
            }
            
            // I just remove the door since that is essentially what Monty Hall is doing when 
            // He reveals one of the goats
            doors.RemoveAt(doorMontyOpens);
        }


        // Since player choice is always door #1 (index 0) and there are only two doors left,
        // we only need to check door #2 at index 1. If it has the car, it is a win. If not, a loss.
        // This simulation only tests the case in which the player changes doors after Monty reveals
        // a door. So it SHOULD usually have about 667 wins and 333 losses. Why do I get 50/50???
        if (doors[1].Contents == "car")
        {
            wins++;
        }
        else
        {
            losses++;
        }

        attempts++;
        this.winsTextbox.Text = $"{wins}";
        this.lossesTextbox.Text = $"{losses}";
        this.attemptsTextbox.Text = $"{attempts}";                
    }

    MessageBox.Show("Done!");
}

public class Door
{
    public string Contents { get; set; }
    public bool Opened { get; set; }
    public bool PlayerChoice {  get; set; }
}

别介意代码的蹩脚.这是一个超级快速和肮脏的模拟.代码的每一段注释都在注释中.谢谢!

推荐答案

问题就在这里:

int doorNumWithCar = random.Next(0, numberOfDoors - 1);

Next的上限(第二个参数)是互斥的(参见Random.Next(Int32, Int32)文档),所以通过使用numberOfDoors - 1,你将car限制为只出现在前两个门中的一个,所以最初的猜测是50/50而不是~33/~66.

应当

int doorNumWithCar = random.Next(0, numberOfDoors);

Fixed demo @dotnetfiddle

Csharp相关问答推荐

ASP.NET Core 8.0 JWT验证问题:尽管令牌有效,但SecurityTokenNoExpirationError异常

. NET JSON属性自定义所需逻辑

如何在C#中将对象[*,*]直接转换为字符串[*,*]?

Polly v8—使用PredicateBuilder重试特定的状态代码

在C#中,有没有一种方法可以集中定义跨多个方法使用的XML参数描述符?

用C#调用由缓冲区指针参数组成的C API

无法创建';';类型的';DbContext';.异常';无法解析类型';Microsoft.EntityFrameworkCore.DbContextOptions`1[Comm的服务

如何在C#中实现非抛出`MinBy`?

如何将字符串变量传递给JObject C#-无法加载文件或程序集';System.Text.Json

具有可空类型的C#NOTNULL约束具有意外行为

在字符串C#之前获取数字

Google OAuth令牌交换在.Net中不起作用

C#多键字典和TryGetValue

使用switch 类型模式时出现奇怪的编译器行为

VS代码扩展无法在新版本扩展C#中运行从v2.10.28开始

在.NET Maui中,Flyoutindow/Hamburger菜单可以在shell 之外实现吗?

删除MudRadio时,MudRadioGroup未 Select 正确的MudRadio

C#中COM对象的实际地址

在Unity C#中按键点击错误的参数

读取测试项目中的应用程序设置