You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

蒙提霍尔问题模拟出现50/50概率异常,求代码问题排查

蒙提霍尔问题模拟代码bug排查

我计划开发蒙提霍尔问题的完整游戏作为副业项目,先做批量模拟来验证换门胜率应为66%,但3门场景下每次模拟都得到约50/50的概率,增加门数后换门胜率才上升。附上C#模拟代码,请求帮忙找出问题所在。

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; }
}

问题根源

  1. 随机数范围错误
    设置汽车所在门的代码int doorNumWithCar = random.Next(0, numberOfDoors - 1);存在逻辑错误。Random.Next(int minValue, int maxValue)是左闭右开区间,当numberOfDoors=3时,该调用仅会生成0或1,永远不会选中索引为2的第三扇门。这导致汽车只能出现在前两扇门中:

    • 汽车在0号门(玩家初始选择):Monty随机移除1或2号山羊门,换门后必然失败;
    • 汽车在1号门:Monty只能移除2号山羊门,换门后必然成功;
      两种情况各占50%概率,最终换门胜率自然是50%,与预期的66%不符。
  2. 循环内重复创建Random实例
    在每次游戏循环中创建Random random = new Random();,由于Random默认使用系统当前时间作为种子,循环执行速度极快时,多次创建的Random会使用相同种子,导致生成的随机数重复,进一步影响模拟结果的准确性。

修复方案

  • 将Random实例移到游戏循环外,避免重复创建;
  • 修正随机数范围,确保覆盖所有门的索引:
private void simulateButton_Click(object sender, EventArgs e)
{
    int wins = 0;
    int losses = 0;
    int attempts = 0;
    int numberOfDoors = 3;
    // 将Random实例移到循环外,确保随机数序列正常生成
    Random random = new Random();

    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,
            });     
        }

        // 修正随机数范围,覆盖0到numberOfDoors-1的所有索引
        int doorNumWithCar = random.Next(0, numberOfDoors);
        doors[doorNumWithCar].Contents = "car";

        // ... 其余代码保持不变 ...
    }

    MessageBox.Show("Done!");
}

内容的提问来源于stack exchange,提问作者mattjr747

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:02:02