Create a Monty Hall game in Vanilla JavaScript

Create a Monty Hall game in Vanilla JavaScript

·

9 min read

Monty Hall problem is a popular probability puzzle based on a television game show and named after its host, Monty Hall.

In this Monty Hall game,

There will be three closed doors and you will be given a choice to choose one of them. Behind one of the doors, there is a car and behind the other doors, goats. The host knows about the placement of the car and goats. After you choose a door, the host opens one of the other two doors which has a goat. Now, you can either stick with your original choice of door or you can switch.

Here's a glimpse of the game.

montyhall.gif

Let's create an interactive version of this game with HTML, CSS, and vanilla JavaScript.

HTML: The main parts we need in the game are:

Dialogue space for the host, where he/she interacts with the player. The 3 doors Result page

We include all possible scenarios and dialogues and later with JavaScript, we can use them when necessary.

Here, in the instructions class, we included all the dialogues of the host, and we can make this interactive with JavaScript. After the instructions class, there is the main section which contains the 3 doors. Finally, we have different scenarios based on the player's choice.

HTML

<!DOCTYPE html>
<head>
    <title>MontyHall</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="body">
        <header>
            <h1>welcome to Montyhall game</h1>
        </header>
        <div id="instructions" class="instructions">
            <div id="row1" class="row1">
              Please Select a door
            </div>
            <div id="d1">You selected door1</div>
            <div id="d2">You selected door2</div>
            <div id="d3">You selected door3</div>
            <div id="row2" class="row2">
                  <p>Ok, I'm opening a door</p>
                  <p>Do you want to switch?</p>
                   <div class="buttons">
                    <button id="btn-1">Yes</button>
                    <button id="btn-2">No</button>
                </div>
            </div>
        </div>
        <main class="door-row">
            <img id="door1" class="door" 
                 src="./door.png" alt="door">
            <img id="door2" class="door" 
                 src="./door.png" alt="door">
            <img id="door3" class="door" 
                 src="./door.png" alt="door">
        </main>
    </div>
    <div id="switchAndWin" class="result">
        <p>Congratulations!!!!!</p>
        <p>You made the right choice by switching</p>
         <p>By switching, you increased your probability of winning to 0.67</p>
        <div class="links">
            <button><a href="https://en.wikipedia.org/wiki/Monty_Hall_problem" target="_blank">Know more</a>
            </button>
            <button><a href="index.html">
                      Play again
                    </a></button>
        </div>
    </div>
    <div id="switchAndLose" class="result">
<p>You Lost!!!</p>
<p>The chances of you winning was 67% since you
            switched,yet you still lost </p>
<p>Play again to redefine your luck</p>
        <div class="links">
            <button><a href=
"https://en.wikipedia.org/wiki/Monty_Hall_problem" 
                       target="_blank">
              Know more</a>
            </button>
            <button><a href="index.html">Play again</a></button>
        </div>
    </div>
    <div id="NoSwitchAndWin" class="result">
      <p>Congratulations!!!!!</p>
      <p>You are a very lucky person</p>
      <p>The probability of you winning was only 0.33 because you didn't switch,yet you still won</p>
        <div class="links">
            <button><a href="https://en.wikipedia.org/wiki/Monty_Hall_problem" target="_blank">Know more</a>
            </button>
            <button><a href="index.html">
              Play again</a>
            </button>
        </div>
    </div>
    <div id="NoSwitchAndLose" class="result">
        <p>You Lost!!!!</p>
        <p>Since you didn't switch, your chances 
            of winning was only 33%</p>
      <p>Play again to redefine your luck</p>
        <div class="links">
            <button><a href=
"https://en.wikipedia.org/wiki/Monty_Hall_problem" 
                       target="_blank">
              Know more</a>
            </button>
            <button><a href="index.html">Play again</a></button>
        </div>
    </div>
    <script src="script1.js" async defer></script>
</body>
</html>

CSS: Let's add a little styling to our game. It's highly customizable and feels free to add your own stylings.

CSS

/*Basic Styling */
* {
    margin: 0;
    padding: 0%;
    box-sizing: border-box;
}

body {
    background-color: #ffffff;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}

header {
    height: 20vh;
    font-family: 'Bangers', cursive;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 30px;
    text-align: center;
}

.instructions {
    height: 15vh;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 30px;
    font-family: 'McLaren', cursive;
    margin: 30px 0;
}

.door-row {
    text-align: center;
    margin-top: 40px;
}

.door {
    width: 200px;
    height: 350px;
    margin: 10px 40px;
    margin-bottom: 40px;
    cursor: pointer;
    border: 10px solid #000;
}

.buttons {
    width: 300px;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
}

button {
    padding: 10px 40px;
    background-color: #000;
    border: none;
    border-radius: 50px;
    color: #f5f5f5;
    cursor: pointer;
    margin: 0 20px;
    font-size: 18px;
    outline:none;
    box-shadow: 0px 10px 13px -7px #000000, 
                7px 5px 15px 5px rgba(0, 0, 0, 0);
}

button:active {
    transform: scale(0.9);
}

.result p {
    font-size: 22px;
    line-height: 40px;
    text-align: center;
}

.result p:first-child {
    font-family: 'Bangers', cursive;
    letter-spacing: 2px;
    text-transform: uppercase;
    font-size: 40px;
    margin-bottom: 30px;
}

.links {
    width: 100vw;
    height: 10vw;
    text-align: center;
    margin: 40px 0;
}

.result a {
    color: gray;
    background-color: #000;
    text-decoration: none;
}
.result a:hover {
    color:#f5f5f5;
}

@media screen and (max-width:700px) {
    header {
        margin-top: 20px;
        font-size: 20px;
        text-align: center;
    }
}

JavaScript: The workflow of javascript is:

Declare all the global variables. Hide unnecessary elements. Create a function for randomly shuffling the doors every time we play. Add Event listeners for each door when chosen. For every door that is clicked, show the host dialogue, open a door that contains a goat, and ask the player to choose. Then, according to the player's choice open the door and display the result page.

Declaring the variables:

Javascript

// Declaring global variables
const body = document.getElementById('body');
const instructions = document.getElementById('instructions');
const row1 = document.getElementById('row1');
const row2 = document.getElementById('row2');
const d1 = document.getElementById('d1');
const d2 = document.getElementById('d2');
const d3 = document.getElementById('d3');
const switchChoiceYes = document.getElementById('btn-1');
const switchChoiceNo = document.getElementById('btn-2');
const doorImage1 = document.getElementById('door1');
const doorImage2 = document.getElementById('door2');
const doorImage3 = document.getElementById('door3');
const SwitchAndWin = document.getElementById("switchAndWin");
const SwitchAndLose = document.getElementById("switchAndLose");
const NoSwitchAndWin = document.getElementById("NoSwitchAndWin");
const NoSwitchAndLose = document.getElementById("NoSwitchAndLose");

// Image of Car
const winPath = 
"https://image.flaticon.com/icons/svg/3118/3118467.svg";
// Image of Goat
const losePath = 
"https://image.flaticon.com/icons/svg/836/836069.svg";

// Variables for shuffling the doors
var openDoor1, openDoor2, openDoor3, winner;

Hiding the unnecessary elements:

// Hiding unnecessary elements
row2.hidden = true;
SwitchAndWin.hidden = true;
SwitchAndLose.hidden = true;
NoSwitchAndWin.hidden = true;
NoSwitchAndLose.hidden = true;
d1.hidden = true;
d2.hidden = true;
d3.hidden = true;

Create a function for randomly shuffling the doors every time we play.

// Function to randomly shuffle the doors
function winDoorGenerator() {
    winner = Math.floor(Math.random() * 3);
    if (winner === 1) {
        openDoor1 = winPath;
        openDoor2 = losePath;
        openDoor3 = losePath;
    } else if (winner === 2) {
        openDoor2 = winPath;
        openDoor1 = losePath;
        openDoor3 = losePath;
    } else {
        openDoor3 = winPath;
        openDoor2 = losePath;
        openDoor1 = losePath;
    }
}
// Calling the function
winDoorGenerator();

Event Listener for door1:

// Event listener for door 1
doorImage1.onclick = () => {

    // Revealing necessary elements for dialogue
    row1.hidden = true;
    d1.hidden = false;
    setTimeout(()=>{
        d1.hidden = true;
    },1000);
    setTimeout(()=>{
        row2.hidden = false;
    },1000);

    // Opening a door which has a goat behind it.
    if (openDoor2 === losePath) {
        setTimeout(() => 
        { doorImage2.src = openDoor2; }, 2000);

    } else if (openDoor3 === losePath) {
        setTimeout(() => 
        { doorImage3.src = openDoor3; }, 2000);
    }

    //Event listener if the player opts to switch
    switchChoiceYes.onclick = () => {

        // If the opened door is door2, forming a
        // suitable dialogue.
        if (doorImage2.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg"){
            row2.hidden = true;
            instructions.innerHTML = "You switched to door3";
            setTimeout(()=>{
                instructions.innerHTML = 
                "Revealing your chosen door......";
            },1000);

            // Opening the chosen door
            setTimeout(() => 
            { doorImage3.src = openDoor3; }, 2500);

            //Conditions to display the result page
            if (openDoor3 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        }
        //If the opened door is door3, forming a suitable dialogue.
        else if (doorImage3.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg") {
            row2.hidden = true;
            instructions.innerHTML = "You switched to door2";
            setTimeout(()=>{
                instructions.innerHTML = 
                "Revealing your chosen door......";
            },1000);

            // Opening the chosen door
            setTimeout(() => { doorImage2.src = openDoor2; }, 2500);
            //Conditions to display the result page
            if (openDoor2 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        }
    }
    //Event listener if the player does not opts to switch
    switchChoiceNo.onclick = () => {
        row2.hidden = true;
        instructions.innerHTML = "Your choice is still door1";
        setTimeout(() => 
        { instructions.innerHTML = 
        "Revealing your chosen door......"; }, 1000);

        // Opening the chosen door
        setTimeout(() => { doorImage1.src = openDoor1; }, 2500);

        // Conditions to display the result page
        if (openDoor1 === losePath) {
            setTimeout(() => { noSwitchAndLose(); }, 3500)
        } else {
            setTimeout(() => { noSwitchAndWin(); }, 3500)
        }
    }
}

The switchAndWin(), switchAndLose(), noSwitchAndWin(),noSwitchAndLose() are four functions that display the result of the player based on their choice.

const switchAndWin = () => {
    body.hidden = true;
    SwitchAndWin.hidden = false;
}
const switchAndLose = () => {
    body.hidden = true;
    SwitchAndLose.hidden = false;
}
const noSwitchAndWin = () => {
    body.hidden = true;
    NoSwitchAndWin.hidden = false;
}
const noSwitchAndLose = () => {
    body.hidden = true;
    NoSwitchAndLose.hidden = false;
}

Similarly, for the door2 and door3, add Event listeners when clicked.

doorImage2.onclick = () => {
    row1.hidden = true;
    d2.hidden = false;
    setTimeout(() => { d2.hidden = true; }, 1000);
    setTimeout(() => { row2.hidden = false; }, 1000)

    if (openDoor1 === losePath) {
        setTimeout(() =>
        { doorImage1.src = openDoor1; }, 2000);

    } else if (openDoor3 === losePath) {
        setTimeout(() => 
        { doorImage3.src = openDoor3; }, 2000);
    }

    switchChoiceYes.onclick = () => {
        if (doorImage1.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg") {
            row2.hidden = true;
            instructions.innerHTML = "You switched to door3"
            setTimeout(() => 
            { instructions.innerHTML = 
            "Revealing your chosen door......"; }, 1000);
            setTimeout(() => { doorImage3.src = openDoor3; }, 2500);
            if (openDoor3 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        } else if (doorImage3.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg") {
            row2.hidden = true;
            instructions.innerHTML = "You switched to door1";
            setTimeout(() => { instructions.innerHTML 
            = "Revealing your chosen door......"; }, 1000);
            setTimeout(() => { doorImage1.src = openDoor1; }, 2500);
            if (openDoor1 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        }
    }
    switchChoiceNo.onclick = () => {
        row2.hidden = true;
        instructions.innerHTML = "Your choice is still door2"
        setTimeout(() => { instructions.innerHTML =
        "Revealing your chosen door......"; }, 1000);
        setTimeout(() => { doorImage2.src = openDoor2; }, 2500);
        if (openDoor2 === losePath) {
            setTimeout(() => { noSwitchAndLose(); }, 3500)
        } else {
            setTimeout(() => { noSwitchAndWin(); }, 3500)
        }
    }
}
doorImage3.onclick = () => {
    row1.hidden = true;
    d3.hidden = false;
    setTimeout(() => { d3.hidden = true; }, 1000);
    setTimeout(() => { row2.hidden = false; }, 1000)

    if (openDoor1 === losePath) {
        setTimeout(() => { doorImage1.src = openDoor1; }, 2000);

    } else if (openDoor2 === losePath) {
        setTimeout(() => { doorImage2.src = openDoor2; }, 2000);
    }

    switchChoiceYes.onclick = () => {
        if (doorImage1.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg") {
            row2.hidden = true;
            instructions.innerHTML = "You switched to door2"
            setTimeout(() => { instructions.innerHTML = 
            "Revealing your chosen door......"; }, 1000);
            setTimeout(() => { doorImage2.src = openDoor2; }, 2500);
            if (openDoor2 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        } else if (doorImage2.src === 
        "https://image.flaticon.com/icons/svg/836/836069.svg") {
            row2.hidden = true;
            instructions.innerHTML = "You switched to door1"
            setTimeout(() => { instructions.innerHTML = 
            "Revealing your chosen door......"; }, 1000);
            setTimeout(() => { doorImage1.src = openDoor1; }, 2500);
            if (openDoor1 === losePath) {
                setTimeout(() => { switchAndLose(); }, 3500)
            } else {
                setTimeout(() => { switchAndWin(); }, 3500)
            }
        }
    }
    switchChoiceNo.onclick = () => {
        row2.hidden = true;
        instructions.innerHTML = "Your choice is still door3"
        setTimeout(() => { instructions.innerHTML = 
        "Revealing your chosen door......"; }, 1000);
        setTimeout(() => { doorImage3.src = openDoor3; }, 2500);
        if (openDoor3 === losePath) {
            setTimeout(() => { noSwitchAndLose(); }, 3500)
        } else {
            setTimeout(() => { noSwitchAndWin(); }, 3500)
        }
    }
}

Here's the live version of the game: Live Demo