2013-04-25 8 views
7

Próbuję symulować Monty Hall Problem (ponieważ czytałem z książki Think Statistics, że facet był szczególnie przekonany dopiero po obejrzeniu symulacji komputerowej) w języku C#, najbardziej znanym mi języku programowania. Mój scenariusz jest taki, że pozycja nagrody jest losowa (w każdym przebiegu), mój wybór jest losowy, a wybór hosta przez grę otwierający drzwi jest losowy (nie może być losowy, jeśli wybrałem nie-nagrodę).Monty Hall Symulacja programu (C#)

Co zaskakujące, mój program osiąga wynik 50:50 szansy na wygraną, niezależnie od tego, czy przełączę, czy nie. Oto kod do niego (pardon za przewlekłość):

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

Jest to całkowicie dla mego własnego interesu, a pisałem go w sposób najbardziej znanym i wygodne dla mnie. Nie krępuj się wyrażać własne opinie i krytykę, dziękuję bardzo!

Odpowiedz

5
rand.Next(0,2) 

zwraca tylko 0 lub 1; górna granica to exclusive. Nigdy nie wybierasz trzecich drzwi (chyba, że ​​się zmieniasz), a trzecie drzwi nigdy nie mają nagrody. Modelujesz niewłaściwy problem.

Spróbuj zamiast:

rand.Next(0,3) 

Podobnie:

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

tylko kiedykolwiek wybiera pierwsze drzwi kandydujących; powinno być:

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

Teraz otrzymujemy:

If you don't switch, you will win 3320 out of 1000 games. 
If you switch, you will win 6639 out of 1000 games. 

Uwaga - górna granica jest włącznie gdy równa - tj rand.Next(1,1) zawsze zwraca 1.

+0

Wygląda na to, że zawiedli na części randomizacji, dzięki! – matt

1

Zobacz Random.Next(minValue, maxValue)

Parametry

MINVALUE Typ: System.Int32 Włącznie dolna granica liczby losowej zwrócony.

maxWartość Typ: System.Int32 Wyłączone ograniczenie górnej liczby losowej. maxValue musi być większa lub równa minValue.

1

Aby dodać odpowiedź Marca, można również użyć Random.Next(Int32) ponieważ twój dolna granica wynosi 0, więc byłoby po prostu:

rand.Next(3)