Vito Cassisi – Tech Blog Delving into technology

5Aug/091

Proving a probability paradox – Part 2

This one's about the code.

door2

Today we continue with the discussion regarding the Monty Hall Paradox. Part 1 of this guide can be found here. For those who want more insight into the Monty Hall problem, there's a good explanation on Wikipedia.

Programming is a great tool for solving problems, especially those which involve mathematics. As mentioned previously, the programming language I've chosen is C#. You could also replicate the simulation on several other languages.

Note:
This is not a programming tutorial. If you want to learn C#, there are many guides on the Internet. This write-up will only briefly cover the C# language. The following describes how the software itself functions. That being said, mucking around with the code will help you learn how to work with the language.

We'll start with the code for the 'GO' button. Recall that this code is only executed when the 'GO' button is pressed.

Random Door = new Random();

C# is an object orientated programming language. This means we need to work with 'objects' to create applications. An object, to put it simply, is a collection of code which defines an entity. For example, a 'person' is an object, which can perform actions such as walk, sleep, eat - and has properties of age, height, weight. This is a very brief description, there's much more to objects than this.

Random is a random number generator object. Since we're simulating a probability problem, having it act randomly helps to emulate the 'player' and 'host' roles, which would normally be a human action. This specific line reads "create an instance of object 'Random' called 'Door', and run its default behaviour". All we need to know, for the purpose of this guide, is that when called, this object will supply a random number.

int i;
int stayWinCounter = 0;
int swapWinCounter = 0;
double ratioVal = 0;

int and double are data types. int is short for integer, while double is short for double precision number (or in simplistic layman's terms, a number with decimal precision). Here we're creating an area in memory called i which we'll use to store an integer later. stayWinCounter, swapWinCounter and ratioVal do the same, but are initialised to store the value 0.

int numRounds = Convert.ToInt32(noRounds.Text);
stayWin.Text = Convert.ToString(0);
swapWin.Text = Convert.ToString(0);
ratio.Text = Convert.ToString(0);

Convert.ToInt32(noRounds.Text) is a function with parameter noRounds.Text which converts the value within the TextBox object (noRounds) to an integer, so it can be stored as an int. By default, the value of text in a TextBox is of type string, also known as a 'string literal'.

The remaining three lines set the text property value of the stayWin, swapWin and ratio label objects. In this case, they're set to 0.

DoorOne.Image = MontyHall.Properties.Resources.door;
DoorTwo.Image = MontyHall.Properties.Resources.door2;
DoorThree.Image = MontyHall.Properties.Resources.door3;

Here DoorOne, DoorTwo and DoorThree ImageBox objects are set to their respective default images.

MontyHallSim.ActiveForm.Cursor = Cursors.WaitCursor;

This sets the cursor to the waiting animation. This is particularly useful when running large values in the simulator, so that the user knows it's still working.

for (i = 0; i < numRounds; i++)

This is a for loop. It allows code to be repeated a set amount of times. This loop can be read as "set variable i to 0, then loop the following code whilst i is smaller than variable numRounds. Increment the value i after each loop." i essentially acts as a counter, to keep track of how many times the code has been executed. Remember that numRounds is the value that was input by the user via the TextBox. The number of times the simulation code will run depends on the value the user has chosen.

The code which is executed during the loop is located between the matching braces (i.e. { }). Braces define a code block.

int doorWin = Door.Next(1, 4);
int doorPlayer = Door.Next(1, 4);
int doorHost = Door.Next(1, 4);

Here we use the random number generator we created (Door) to assign doorWin, doorPlayer and doorHost random integers. The Next() function request a random number from the generator. The parameter 1, 4 limits the range of numbers to 1 - 3 (i.e. the number of doors in the problem). 1, 4 is used because the second parameter is non-inclusive, whilst the first is inclusive.

while (doorHost == doorWin || doorHost == doorPlayer)
{
    doorHost = Door.Next(1, 4);
}

This code uses a while loop to check if the host (doorHost) has been assigned a door which violates the rules of the paradox. It reads "while doorHost is equal to doorWin, or doorHost is equal to doorPlayer, loop the following code." The code within the braces assigns another random number to doorHost. When the assigned number satisfies the loop conditions, the next part of the code is executed. Note than '||' means 'or'. Also remember that '==' is used for comparisons, whilst '=' is used to assign values.

if (goatDoor == 1 || doorHost == 1)
{
    DoorOne.Image = MontyHall.Properties.Resources.doorLose;
}
if (goatDoor == 2 || doorHost == 2)
{
    DoorTwo.Image = MontyHall.Properties.Resources.doorLose;
}
if (goatDoor == 3 || doorHost == 3)
{
    DoorThree.Image = MontyHall.Properties.Resources.doorLose;
}

The conditional statement if is used here, to determine the appropriate course of action given the current situation. The code encompassed by the first if statement is executed if "goatDoor equals 1, or hostDoor equals 1". As you may have guessed, the code sets the ImageBox value to the goat image if the condition is satisfied. The remaining two if statements act in a similar manner.

switch (doorWin){
    case 1:
        DoorOne.Image = MontyHall.Properties.Resources.doorPrize;
        break;
    case 2:
        DoorTwo.Image = MontyHall.Properties.Resources.doorPrize;
        break;
    case 3:
        DoorThree.Image = MontyHall.Properties.Resources.doorPrize;
        break;
    default:
        break;
}

Here we use switch to check whether doorWin equals 1, 2 or 3. If 1, the ImageBox DoorOne is set to the car image (doorPrize). A value of 2 sets DoorTwo to the same image, and 3 does the same again with DoorThree. A similar process could have been written with a few if statements.

if (doorWin == doorPlayer)
{
    stayWinCounter++;
}
else
{
    swapWinCounter++;
}
if (stayWinCounter != 0)
{
    ratioVal = (double)swapWinCounter / stayWinCounter;
}

Here, the first if code block serves the purpose of incrementing the stayWinCounter by 1, if doorWin is equal to doorPlayer. If the condition isn't met, the else block states that the swapWinCounter will be incremented instead. The '++' prefix is akin to writing "swapWinCounter = swapWinCounter + 1".

Thinking back to the Monty Hall paradox, we're basically tallying up the results of random door choices. If doorWin (i.e. the winning door) equals doorPlayer (the door which the player has selected) then staying would result in a win, hence the increment to stayWinCounter. The only other choice is to swap, so if they aren't equal, swapWinCounter is incremented.

The last if statement finds the ratio between the swapWinCounter and stayWinCounter variables. It only does this if stayWinCounter is not equal to 0. We must check this since we cannot divide a number by 0, the result is undefined by mathematics.

At this point, the for loop reaches its closing brace, and checks its conditional statement to determine if another loop is necessary. If not, we continue to execute the following:

stayWin.Text = Convert.ToString(stayWinCounter);
swapWin.Text = Convert.ToString(swapWinCounter);
ratio.Text = Convert.ToString(ratioVal);
MontyHallSim.ActiveForm.Cursor = Cursors.Arrow;

Now we set the stayWin, swapWin and ratio labels to reflect the results of the simulation. Last but not least, we return the cursor to its normal state.

That's the code for the 'OK' button out of the way. Next we'll look at the TextBox code, which implements error checking.

http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/digg_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/reddit_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/stumbleupon_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/delicious_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/technorati_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/facebook_24.png http://www.vitocassisi.com/wp-content/plugins/sociofluid/images/twitter_24.png