蒙提霍尔问题程序模拟(C#)

7
我正在尝试用我最熟悉的编程语言C#模拟蒙提霍尔问题(因为我从Think Statistics一书中了解到,有个人只有在看到计算机模拟后才被说服)。我的情景是奖品位置是随机的(每次运行),我的选择也是随机的,而游戏主持人打开门的选择是随机的(如果我选了非奖励,则不能是随机的)。
然而令人惊讶的是,无论我是否换门,我的程序都能实现50:50的获胜几率。以下是代码(对于长度请原谅我):
class Program
{
    static void Main(string[] args)
    {
        Random rand = new Random();

        int noSwitchWins = RunGames(rand, false, 10000);
        int switchWins = RunGames(rand, true, 10000);

        Console.WriteLine(string.Format("If you don't switch, you will win {0} out of 1000 games.", noSwitchWins));
        Console.WriteLine(string.Format("If you switch, you will win {0} out of 1000 games.", switchWins));

        Console.ReadLine();
    }

    static int RunGames(Random rand, bool doSwitch, int numberOfRuns)
    {
        int counter = 0;

        for (int i = 0; i < numberOfRuns; i++)
        {
            bool isWin = RunGame(rand, doSwitch);
            if (isWin)
                counter++;
        }

        return counter;
    }

    static bool RunGame(Random rand, bool doSwitch)
    {
        int prize = rand.Next(0, 2);
        int selection = rand.Next(0, 2);

        // available choices
        List<Choice> choices = new List<Choice> { new Choice(), new Choice(), new Choice() };
        choices[prize].IsPrize = true;
        choices[selection].IsSelected = true;
        Choice selectedChoice = choices[selection];
        int randomlyDisplayedDoor = rand.Next(0, 1);

        // one of the choices are displayed
        var choicesToDisplay = choices.Where(x => !x.IsSelected && !x.IsPrize);
        var displayedChoice = choicesToDisplay.ElementAt(choicesToDisplay.Count() == 1 ? 0 : randomlyDisplayedDoor);
        choices.Remove(displayedChoice);

        // would you like to switch?
        if (doSwitch)
        {
            Choice initialChoice = choices.Where(x => x.IsSelected).FirstOrDefault();
            selectedChoice = choices.Where(x => !x.IsSelected).FirstOrDefault();
            selectedChoice.IsSelected = true;
        }

        return selectedChoice.IsPrize;
    }
}

class Choice
{
    public bool IsPrize = false;
    public bool IsSelected = false;
}

这完全是出于我个人的兴趣,我用最熟悉和舒适的方式写下了它。请随意提出您自己的意见和批评,非常感谢!

3个回答

6
rand.Next(0,2)

只返回0或1;上限是排除在外的。除非您更改选择,否则永远不会选择第三扇门,第三扇门也永远不会有奖品。您正在模拟错误的问题。

请尝试:

rand.Next(0,3)

同样地:
int randomlyDisplayedDoor = rand.Next(0, 1);

只选择候选门中的第一扇门;应该改为:

int randomlyDisplayedDoor = rand.Next(0, 2);

现在我们得到了:
If you don't switch, you will win 3320 out of 1000 games.
If you switch, you will win 6639 out of 1000 games.

注意 - 当上限等于时,上限是包括在内的 - 即 rand.Next(1,1) 总是返回 1

1
为了补充Marc的回答,您还可以使用Random.Next(Int32),因为您的下限为0,所以它会变得简单:
rand.Next(3)

1

查看 Random.Next(minValue, maxValue)

参数

minValue 类型:System.Int32 返回的随机数(含)下限。

maxValue 类型:System.Int32 返回的随机数(不含)上限。maxValue 必须大于或等于 minValue。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接