简体   繁体   中英

Monty hall simulation not functioning as expected

    import java.util.Scanner;
    import static java.lang.System.*;
    import static java.lang.Math.*;
    import java.util.Random; 


    public class Montyhall 
   {
    public static void main(String[] args) 
    {
        Scanner keyboard = new Scanner(System.in);
        System.out.print("Enter number of attempts:");
        int attempts = keyboard.nextInt();/*Decide how many times you want this to
        run. The larger the number, the more realistic an answer you will get.*/

        int curtains[] = new int[3]; //like the game show, one of these will be a winner

        Random rand = new Random(); /*sets the methods up with the same random seed, which
        otherwise changes by the milisecond and could influence the response*/

        withoutswitch(curtains, attempts, rand);
        withswitch(curtains, attempts, rand);



    }

    public static void withoutswitch(int curtains[], int attempts, Random rand)
    {

        int nsCorrect=0;

        for(int x=0; x < attempts; x++)
        {
            int winner = rand.nextInt(3);//Sets the winner to 1, leaving the other two at 0.
            curtains[winner] = 1;        //It then checks to see if they are the same, 
            int guess = rand.nextInt(3); //a 1/3 chance, roughly.

            if(curtains[guess]==1){
                nsCorrect++;
            }
            curtains[0]=0;
            curtains[1]=0;
            curtains[2]=0;
        //the player never changes their decision, so it does not matter if a door is opened.
        }
        System.out.println("Number of successes with no switch: " + nsCorrect);


    }

    public static void withswitch(int curtains[], int attempts, Random rand)
    {

        int ysCorrect=0;
        int goat = 0;

        for(int x=0; x < attempts; x++)
        {
            int winner = rand.nextInt(3);
            curtains[winner] = 1;
            int guess = rand.nextInt(3);
            goat = rand.nextInt(3);//one of the doors is opened
            while(goat == winner || goat == guess)//the opened door is randomized until
                goat = rand.nextInt(3); //it isn't the guess or the winner.


            int guess2 = rand.nextInt(3);
            while(guess2 == guess || guess2 == goat)
                guess2 = rand.nextInt(3);//the second guess goes through a similar process

            if(curtains[guess2]==1){

                ysCorrect++;
                }
            curtains[0]=0;
            curtains[1]=0;
            curtains[2]=0;
        }
        System.out.println("Number of successes with a switch: " + ysCorrect);
        }   

}

Sorry it's a bit messy, I'm trying to get back into coding after almost a year hiatus. The first part functions as intended, returning roughly a 1/3 chance of success. The second, however, should be giving me a 2/3 chance, but I'm still getting roughly the same amount right with the switch as with no switch. I looked through the site, and mostly found things outside of Java that I'm not familiar with. This one was very similar, but no one seemed to actually help with the main issue.

What can I do to make the odds more realistic? Advice on cleaning up the code would be appreciated as well.

Edit:Code now functions, I'm now just trying to slim it down.

In your method withoutswitch you need to change

if(guess==1)
  nsCorrect++;

to

if (curtains[guess] == 1)
  nsCorrect++;

same as in the withswitch method. After each run of the for-loop you need to reset the curtains to 0. Otherwise the previous 1 will be in there and after a few runs the curtains will only contain 1s.

private static void resetCurtains(int[] curtains) {
  for (int i = 0; i < curtains.length; i++) {
    curtains[i] = 0;
  }
}

Call that method after every run within the for-loop.

In addition, i would recommend using {} even if the statements are 1-liner:

if (curtrains[guess] == 1) {
  nsCorrect++;
}

Both of your methods do not function as intended.

Your "withoutswitch" method only picks a random number from 0, 1, or 2, and adds to a counter when its 1. In other words, I can simplify your "withoutswitch" method to this:

public static void withoutswitch(int attempts, Random rand) {
    int counter = 0;
    for (int i = 0; i < attempts; i++) {
        if (rand.nextInt(3) == 1) counter++;
    }
    System.out.println(counter);
}

Your "withswitch" method, believe it or not, does the exact same thing. You start guessing using one variable, then you completely disregard it and do it to a second variable, and check if that is 1. So, it produces the exact same results.

Both of your methods use the "curtains" array, but not correctly. The point of this problem is to put the car behind a random door every time, but you never set your array back to all zeros, and so, after a few runs, it becomes an array of all ones, which definitely isn't what you want.

Here is some pseudocode to help you get started:

number of switch wins = 0
number of stay wins = 0
scan in the number of attempts
loop through each attempt:
    make an array {0, 0, 0}
    pick a random number (0, 1, or 2), and set that array index to 1 (winning index)
    pick a random number (0, 1, or 2), and set it to choice
    pick a random number (0, 1, or 2), and set it to the shown door
    loop while the door number isn't the choice number or the winning index:
        pick a random number (0, 1, or 2) and set it to the shown door
    increment stay wins if the choice is equal to the winning index
    increment switch wins if (3 - choice - showndoor) is equal to the winning index
print stay wins and switch wins

Note: that last bit of logic determines the index of the switched door, since your only possible indices are 0, 1, and 2, (0 + 1 + 2 = 3), then 3 - the door you chose - the door you were shown = the last door.

Hope this helps!

I would back up and restructure the whole thing. One object for the game, two descendents, one of which simply picks a door, one of which picks and then switches.

I'm not entirely following your switch logic but it's definitely wrong. Monty's logic is if the prize is behind the player's door you open one randomly, otherwise you open one with the goat. Only a single random number is desirable.

Likewise, the player switches. There is only one curtain at this point, no random numbers are needed.

A rough stab at the logic (not Java, not the whole program):

MontyHaulGame
{
    int[] Curtains = new int[3];
    int Car = Random(3);
    int Guess;
    Pick();
    if (Guess == Car) Wins++;    
}

MontyHaulNoSwitch : MontyHaulGame
{
    Pick()
    {
        Guess = Random(3);
    }
}

MontyHaulSwitch : MontyHaulGame
{
    Pick()
    {
         Guess = Random(3);
         OpenOne();
         Switch();
    }

    OpenOne()
    {
         if Guess == Car then
              Repeat
                  Monty = Random(3);
              Until Monty != Guess;
         else 
             Monty = 1;
             While (Monty == Guess) || (Monty == Car)
                  Monty++;
    }

    Switch()
    {
        NewGuess = 1;
        While (NewGuess == Guess) || (NewGuess == Monty)
            NewGuess++;
        Guess == NewGuess;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM