Chore Door official solution?

Ok, I’ve just spent hours trying to get the Chore Door exercise to work without any success… I’ve talked to other students and even a dev I know and no one was able to figure out what the issue is…

I’m working from my computer, I’ve downloaded the images and I’m trying to make it work completely local/offline. Here are my codes:

My HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Chore Door!</title>
    <link href="./style.css" rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet" type="text/css">
  </head>

  <body>
    <div class="header">
      <img src="./images/logo.svg">
    </div>
    <div class="title-row">
      <img src="images/star.svg">
      <p class="instructions-title">Instructions</p>
      <img src="images/star.svg">
    </div>
    <table class="instructions-row">
      <tr>
        <td class="instructions-number">1</td>
        <td class="instructions-text">Hiding behind one of these doors is the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">2</td>
        <td class="instructions-text">Your mission is to open all of the doors without running into the ChoreBot on the first two doors.</td>
      </tr>
      <tr>
        <td class="instructions-number">3</td>
        <td class="instructions-text">If you manage to avoid the ChoreBot until you open the very last door, you win!</td>
      </tr>
      <tr>
        <td class="instructions-number">4</td>
        <td class="instructions-text">See if you can score a winning streak!</td>
      </tr>
    </table>
    <div class="door-row">
      <img id="door1" class="door-frame" src="images/closed_door.svg">
      <img id="door2" class="door-frame" src="images/closed_door.svg">
      <img id="door3" class="door-frame" src="images/closed_door.svg">
    </div>  
    <div id="start" class="start-row">Good luck!</div>
    <script type="text/javascript" src="scriptB.js"></script>
  </body>
</html>

My CSS:

body {
    background-color: #010165;
    margin: 0px;
  }
  
  .header {
    background-color: #00ffff;
    text-align: center;
  }
  .title-row {
    margin-top: 42px;
    margin-bottom: 21px;
    text-align: center;
  }
  .instructions-title {
    display: inline;
    font-size: 18px;
    color: #00ffff;
    font-family: 'Work Sans';
  }
  .instructions-row {
    margin: 0 auto;
    width: 400px;
  }
  .instructions-number {
    padding-right: 25px;
    font-family: 'Work Sans';
    font-size: 36px;
    color: #00ffff;
  }
  .instructions-text {
    padding: 10px;
    font-family: 'Work Sans';
    font-size: 14px;
    color: #ffffff;
  }
  .door-row {
    text-align: center;
  }
  .door-frame {
    cursor: pointer;
    padding: 10px;
  }
  .start-row {
    margin: auto;
    width: 120px;
    height: 43px;
    font-family: 'Work Sans';
    background-color: #eb6536;
    padding-top: 18px;
    font-size: 18px;
    text-align: center;
    color: #010165;
    margin-bottom: 21px;
    cursor: pointer;
  }

My JavaScript:

const doorImage1 = document.getElementById("door1");
const doorImage2 = document.getElementById("door2");
const doorImage3 = document.getElementById("door3");
const startButton = document.getElementById("start")

const botDoorPath = "images/robot.svg";
const beachDoorPath = "images/beach.svg";
const spaceDoorPath = "images/space.svg";
const closedDoorPath = "images/closed_door.svg";

let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;
let currentlyPlaying = true;

const isBot = (door) => {
  if (door.src === botDoorPath) {
    return true;
  } else {
    return false;
  }
 };

const isClicked = (door) => {
 if (door.src === closedDoorPath) {
   return false;
 } else {
   return true;
 }
};

const playDoor = (door) => {
  numClosedDoors--;
  if (numClosedDoors === 0) {
    gameOver('win')
  } else if (isBot(door)) {
    gameOver()
  }
};

const randomChoreDoorGenerator = () => {
  const choreDoor = Math.floor(Math.random() * numClosedDoors);
  if (choreDoor === 0) {
    openDoor1 = botDoorPath;
    openDoor2 = beachDoorPath;
    openDoor3 = spaceDoorPath;
  } else if (choreDoor === 1) {
    openDoor1 = beachDoorPath;
    openDoor2 = botDoorPath;
    openDoor3 = spaceDoorPath;
  } else {
    openDoor1 = beachDoorPath;
    openDoor2 = spaceDoorPath;
    openDoor3 = botDoorPath;
  }
 }; 

doorImage1.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage1)) {
    doorImage1.src = openDoor1;
    playDoor(openDoor1);
  }
};
doorImage2.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage2)) {
    doorImage2.src = openDoor2;
    playDoor(openDoor2);
  }
};
doorImage3.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage3)) {
    doorImage3.src = openDoor3;
    playDoor(openDoor3);
  }
};

startButton.onclick = () => {
  if(!currentlyPlaying) {
    startRound();
  }
};


const startRound = () => {
  if (currentlyPlaying === false) {
    doorImage1.src = closedDoorPath;
    doorImage2.src = closedDoorPath;
    doorImage3.src = closedDoorPath;
    numClosedDoors = 3;
    startButton.innerHTML = 'Good luck!';
    currentlyPlaying = true;
    randomChoreDoorGenerator()
  }
};

const gameOver = (status) => {
  if (status === 'win') {
    startButton.innerHTML = 'You win! Play again?';
  } else {
    startButton.innerHTML = 'Game over! Play again?';
  }
  currentlyPlaying = false;
};

startRound();

I’m hoping I can find someone here to give me a rubber ducking session because I have really just given up on this by now.

When you say it’s not working, do you just mean the game isn’t playing correctly? Or are things not displaying correctly?

1 Like

The doors don’t change when I click them…
…trying to degub it on Chrome Dev tools I also noticed that openDoor1, 2 and 3 are undefined even though I have ran startRound() that runs randomChoreDoorGenerator() which in turn should set those variables…
…also I think the doors are not working because isClicked is giving the wrong/opposite answer when tested on dev tools…

See I copy and pasted your code into my test, and the only thing I changed was the image references to the links and it worked perfectly! So I have to think it’s the image references in your javascript file.

1 Like

I have done the same thing and the very first time you try the game the images don’t load up properly instead display a broken jpg thumbnail icon. After that you click the ‘You win’ and then it starts to work as it should… until you hit save/refresh again… so the very first has something broken…

…shouldn’t these be the same?

Yeah it’s pretty odd I can’t quite figure it out, especially since it seems to work after clicking ‘You Win’. My thinking is that something must be the issue in how the HTML is setting the images vs the JS. What is your folder structure like, is it definitely the correct relative link? (i.e. should it maybe be './../images/closed_door.svg'?)

Screen Shot 2020-07-16 at 19.21.54

My guess is there’s some rule/proper way to work relative paths in the DOM or Javasript that I don’t know about…

Hmm generally ./images/closed_door.svg should work here. Maybe try adding in the ./, I don’t remember how specific you need to be for the DOM.

I had it like that first… the dev I spoke to told me to try without it…

I got it to work with the following changes:

// For the isClicked function, created a new closedDoorPath with full path and replace the variable on the IF statement
const closedDoorPath2 = "file:///Users/brunovieira/Documents/Coding%20Projects/Codecademy/6-Building%20Interactive%20JavaScript%20Websites/1-Chore%20Door/images/closed_door.svg";

//For the isBot function, removed the .src from door (but not from the isClicked!)
const isBot = door => door === botDoorPath ? true : false;

Would love if someone could tell me why…

I used a program called http-server on my computer to run the directory as if it were a website and I discovered that your paths are not exactly equal:

doorImage1.src == closedDoorPath
false

In the console the results of each are:
http://localhost:8080/images/closed_door.svg
“images/closed_door.svg”

They must match EXACTLY in order for it to work. The solution is the full path compared to the full path. I tried using relative paths, but JS just did not read that correctly in a local environment. I added the full path, as you did and the code compared correctly. However since I was running http-server I did not need to enter file:/// etc. I was able to prefix the images with http://localhost:8080/

One error I had to fix in order for it to work was you called playDoor() with openDoor1,etc when it works only with doorImage1,etc

And lastly, I fixed your startRound() because it was not running the first time through. It said to only run if currentlyPlaying was false, but first time through it is true. You already had the correct answer at the startButton.onclick() call.

Here is the final code. This works 100% as is now:

const doorImage1 = document.getElementById("door1");
const doorImage2 = document.getElementById("door2");
const doorImage3 = document.getElementById("door3");
const startButton = document.getElementById("start")

const botDoorPath = "http://localhost:8080/images/robot.svg";
const beachDoorPath = "http://localhost:8080/images/beach.svg";
const spaceDoorPath = "http://localhost:8080/images/space.svg";
const closedDoorPath = "http://localhost:8080/images/closed_door.svg";

let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;
let currentlyPlaying = true;

const isBot = (door) => {
    if (door.src === botDoorPath) {
      return true;
    } else {
      return false;
    }
   };

const isClicked = (door) => {
 if (door.src === closedDoorPath) {
   return false;
 } else {
   return true;
 }
};

const playDoor = (door) => {
    numClosedDoors--;
    if (numClosedDoors === 0) {
      gameOver('win')
    } else if (isBot(door)) {
      gameOver()
    }
  };

const randomChoreDoorGenerator = () => 
    {
        const choreDoor = Math.floor(Math.random() * numClosedDoors);
        if (choreDoor === 0) {
            openDoor1 = botDoorPath;
            openDoor2 = beachDoorPath;
            openDoor3 = spaceDoorPath;
        } else if (choreDoor === 1) {
            openDoor1 = beachDoorPath;
            openDoor2 = botDoorPath;
            openDoor3 = spaceDoorPath;
        } else {
            openDoor1 = beachDoorPath;
            openDoor2 = spaceDoorPath;
            openDoor3 = botDoorPath;
        }
    }; 

doorImage1.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage1)) 
  {
    doorImage1.src = openDoor1;
    playDoor(doorImage1);
  }
};
doorImage2.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage2)) {
    doorImage2.src = openDoor2;
    playDoor(doorImage2);
  }
};
doorImage3.onclick = () => {
  if (currentlyPlaying && !isClicked(doorImage3)) {
    doorImage3.src = openDoor3;
    playDoor(doorImage3);
  }
};

startButton.onclick = () => {
    if(!currentlyPlaying) {
      startRound();
    }
  };

const startRound = () => {
    doorImage1.src = closedDoorPath;
    doorImage2.src = closedDoorPath;
    doorImage3.src = closedDoorPath;
    numClosedDoors = 3;
    startButton.innerHTML = 'Good luck!';
    currentlyPlaying = true;
    randomChoreDoorGenerator();
  };

const gameOver = (status) => {
  if (status === 'win') {
    startButton.innerHTML = 'You win! Play again?';
  } else {
    startButton.innerHTML = 'Game over! Play again?';
  }
  currentlyPlaying = false;
};

startRound();

I hope this helps explain why you were having a little bit of troubles! Happy Coding!
~nia

PS
For the record, the reason I hit the forums was because I was having trouble figuring out how to add the currentlyPlaying check correctly, which is why I spotted the issue here when I found the answer here as well. ~nia

The answer to this was the IF statement in the startRound() call. The IF statement was correctly added to the .onclick() call for the button, however it would not run the first time because on page load it is true, therefore the random chores are never chosen. (oops, initially posted this answer to someone else instead of who it was meant for!)

~nia