Jragon
August 15, 2013, 2:26am
115
Megacannon:
Here we go. I fixed the program and made it much better overall. It now uses truly random numbers from Random.org and is also much more robust than before. Requires an Internet connection to play.
http://www.mediafire.com/download/c0e2tikbeah4sbf/monty.exe
Full disclosure code:
using System;
using System.Text;
using System.Net;
using System.IO;
namespace monty
{
class Program
{
static int Main(string[] args)
{
int[] rand;
rand = GetRandomNumbers(2000, 1, 3);
if (rand == null)
return 1;
Console.WriteLine("");
Console.WriteLine("**************************************");
Console.WriteLine("* Welcome to Monty *");
Console.WriteLine("**************************************");
Console.WriteLine("");
bool keepPlaying = true;
int winningDoor;
int montysChoice;
int usersChoice;
double totalCount = 0;
double winCount = 0;
int next = 0;
String userInput;
while (keepPlaying == true)
{
usersChoice = 0;
montysChoice = 0;
winningDoor = rand[next];
next++;
Console.WriteLine("There are three doors. Please enter your choice (1, 2, or 3): ");
userInput = Console.ReadLine();
usersChoice = Convert.ToInt32(userInput);
Console.WriteLine("Monty will now pick a door of the remaining two.");
if (usersChoice == 1)
{
if (usersChoice != winningDoor)
{
if (winningDoor == 2) { montysChoice = 3; }
else { montysChoice = 2; }
}
else
{
montysChoice = rand[next];
next++;
while (montysChoice == 1)
{
montysChoice = rand[next];
next++;
}
}
}
else if (usersChoice == 2)
{
if (usersChoice != winningDoor)
{
if (winningDoor == 1) { montysChoice = 3; }
else { montysChoice = 1; }
}
else
{
montysChoice = rand[next];
next++;
while (montysChoice == 2)
{
montysChoice = rand[next];
next++;
}
}
}
else //Assume user picked number 3
{
if (usersChoice != winningDoor)
{
if (winningDoor == 1) { montysChoice = 2; }
else { montysChoice = 1; }
}
else
{
montysChoice = rand[next];
next++;
while (montysChoice == winningDoor)
{
montysChoice = rand[next];
next++;
}
}
}
Console.WriteLine("Monty has chosen door number " + montysChoice + ". And revealed it to be a dud.");
Console.WriteLine("Do you want to switch doors? (y or n) ");
userInput = Console.ReadLine();
if (userInput == "y")
{
if (usersChoice == 1 && montysChoice == 2)
usersChoice = 3;
else if (usersChoice == 1 && montysChoice == 3)
usersChoice = 2;
else if (usersChoice == 2 && montysChoice == 1)
usersChoice = 3;
else if (usersChoice == 2 && montysChoice == 3)
usersChoice = 1;
else if (usersChoice == 3 && montysChoice == 1)
usersChoice = 2;
else if (usersChoice == 3 && montysChoice == 2)
usersChoice = 1;
}
if (usersChoice == winningDoor)
{
Console.WriteLine("Congratulations! Door " + usersChoice + " was the winning door!");
winCount++;
totalCount++;
}
else
{
Console.WriteLine("Sorry. Door " + usersChoice + " was not the winning door.");
totalCount++;
}
Console.WriteLine("Wins: " + winCount + " Total Games: " + totalCount + " Win %: " + winCount / totalCount);
Console.WriteLine("Play again? (y or n) ");
userInput = Console.ReadLine();
if (userInput == "n") { keepPlaying = false; }
}
return 0;
}
static int[] GetRandomNumbers(int quantity, int lowerBound, int upperBound)
{
Console.WriteLine("Retrieving random numbers from Random.org...");
Console.WriteLine("Checking quota...");
bool quotaExceeded = false;
quotaExceeded = CheckQuotaIsExceeded();
if (quotaExceeded == true)
{
Console.WriteLine("Quota for this IP address has been met or exceeded. Stopping.");
int[] failure = null;
return failure;
}
else
{
Console.WriteLine("Quota check OK.");
}
String strRequestURL = "http://www.random.org/integers/?num=" + quantity +
"&min=" + lowerBound + "&max=" + upperBound + "&col=1&base=10&format=plain&rnd=new";
WebRequest webRequest = WebRequest.Create(strRequestURL);
int[] results = new int[quantity];
try
{
Stream objStream = webRequest.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string line = "";
for (int i = 0; line != null && i < quantity; i++)
{
line = objReader.ReadLine();
results* = Convert.ToInt32(line);
}
}
catch (Exception ex)
{
Console.WriteLine("Retrieval of random numbers failed.");
Console.WriteLine("Exception: " + ex.Message);
}
Console.WriteLine("Numbers retrieved successfully.");
return results;
}
static bool CheckQuotaIsExceeded()
{
String strRequestURL = "http://www.random.org/quota/?format=plain";
WebRequest webRequest = WebRequest.Create(strRequestURL);
Stream objStream = webRequest.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
String strQuota = objReader.ReadLine();
if (Convert.ToInt32(strQuota) <= 0)
return true;
else
return false;
}
}
}
PS: I didn’t write it to look pretty.
In an old Monty thread I wrote a similar short program in Java:
So I wrote a little program to calculate your winnings if you always switch. Writing it reveals the huge reason that this problem holds – Monty’s choice is dependent on yours… and he’s omniscient.
int NUM_DOORS = 3;
int ITERATIONS = 1000000;
int winCounter = 0;
for(int i = 0; i < ITERATIONS; i++){
Random rand = new Random();
int winningDoor = rand.nextInt(NUM_DOORS);
int yourDoor = rand.nextInt(NUM_DOORS);
int montysDoor;
if(yourDoor == winningDoor){
montysDoor = rand.nextInt(NUM_DOORS);
while(montysDoor == yourDoor)
montysDoor = rand.nextInt(NUM_DOORS);
} else {
montysDoor = winningDoor
}
// Because we switched doors, we win if monty won
if(montysDoor == winningDoor){
++winCounter;
}
}
Here’s the thing, you have a 1/NUM_DOORS chance of picking the winning door. Monty, being omniscient, always picks the winner if you haven’t. That’s a NUM_DOORS-1/NUM_DOORS chance (i.e. 2/3 in a 3 door game). What Monty is basically asking you is if you want to trust omniscience or blind luck. He ALWAYS gets the winning door if you didn’t trip on it.
Fun fact about the trials – the more doors, the better it is to switch. A game with two doors causes you to win about 50% of the time by switching (you pick a door, Monty picks the other, you switch). 3 doors is always 65-67%, but usually 66.x% (remember, I’m doing a million iterations here). If you have about 100 doors, results are usually in the 99% range. Once you get one million doors, it’s not uncommon for switching to win 100 percent of the time, though it’s usually in the upper 99 percent range.
It doesn’t let you play, but it simulates about a million games (controllable with a variable). As I say in that post: the crux is that Monty is omniscient and always picks the correct door if it’s available. As you set NUM_DOORS to successively higher numbers, the game becomes increasingly impossible to win without switching.