Chore Door - Update Current Streak and Best Streak

Chore Door was a fun project - however I was a little bit frustrated to see that it was not including how to implement the functionalities to update the current streak and best streak, as presented in the final version of the game at the beginning of the project.

Therefore I challenged myself into adding them and since I couldn’t find any topic on this, I thought I would share my solution here.

Because it has its importance for the JS part, I’ll copy here the HTML addition - an extra table to insert after the start div and before the script tag:

    <table class="score-row">
      <tr>
        <th class="score-text">Current Streak:</th>
        <th class="score-text">Best Streak:</th>
      </tr>
      <tr>
        <th id="current-streak" class="score-box">0</th>
        <th id="highest-streak" class="score-box">0</th>
      </tr>
    </table>

And here is my JS code:

let doorImage1 = document.getElementById('door1');
let doorImage2 = document.getElementById('door2');
let doorImage3 = document.getElementById('door3');

let botDoorPath = 'https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg';

let beachDoorPath = 'https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg';

let spaceDoorPath = 'https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg';

let closedDoorPath = 'https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg';

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

let startButton = document.getElementById('start');

let currentlyPlaying = true;

let currentStreak = 0;
let bestStreak = 0;

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');
    updateScore();
    updateBestStreak();
  } else if (isBot(door)) {
    gameOver();
  }
}

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

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

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

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

const startRound = () => {
  doorImage1.src = closedDoorPath;
  doorImage2.src = closedDoorPath;
  doorImage3.src = closedDoorPath;
  numClosedDoors = 3;
  startButton = document.getElementById('start');
  currentStreak = 0;
  document.getElementById('current-streak').innerHTML = currentStreak;
  currentlyPlaying = true;
  randomChoreDoorGenerator();
}

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

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

const updateScore = () => {
    currentStreak++;
    document.getElementById('current-streak').innerHTML = currentStreak;
}

const updateBestStreak = () => {
  if (currentStreak) {
    bestStreak++;
  }
  document.getElementById('highest-streak').innerHTML = bestStreak;
}


startRound(); 

In short, I:

  • Declared two more ‘counter’ variables currentStreak and bestStreak
  • Created updateScore() to increment the currentStreak by 1 and change the innerHTML accordingly
  • Called updateScore() inside playDoor() by wrapping it inside the ‘winning’ condition
  • Created updateBestStreak() to increment the bestStreak by 1 every time the currentStreak is not 0, and change the innerHTML accordingly
  • Called updateBestStreak() after updateScore() inside playDoor() by wrapping it inside the ‘winning’ condition
  • Reset the currentStreak to 0 and the innerHTML of that element in startRound()

After some hiccups and testing, it works as expected :slightly_smiling_face:
However I suppose the code could be made more synthetic and readable in some places, but all my attempts at trying to shorten it or use more variables resulted in breaking something in the game, so I left it at that!

Not too dissimilar to my own. Though I noticed with yours, a problem I also encountered, in that the best streak increases when you win another game after losing when it shouldn’t

For example:

You get to 2 current, 2 best but then lose resulting in 0 current, 0 best.
You then get to 1 current, 2 best but then you win another game which results in:
2 current, 3 best.

My index.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>

    <header>
        <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/logo.svg" />
    </header>


    <main>
        <section class="title-row">
            <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/star.svg" />
            <p class="instructions-title">Instructions</p>
            <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/star.svg" />
        </section>
        <section>
            <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.</td>
                </tr>
                <tr>
                    <td class="instructions-number">3</td>
                    <td class="instructions-text">If you manage to avoid the ChoreBot until 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>
        </section>
        <section class="door-row">
            <img id="door1" class="door-frame"
                src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" />
            <img id="door2" class="door-frame"
                src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" />
            <img id="door3" class="door-frame"
                src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" />
        </section>
        <section id="start" class="start-row">
            Good luck!
        </section>
        <section class='streak-row'>
            <table>
                <tbody>
                    <tr>
                        <td class="streak-text">Current streak:</td>
                        <td class="streak-text">Best streak:</td>
                    </tr>
                    <tr>
                        <td id="current" class="streak-number">0</td>
                        <td id="best" class="streak-number">0</td>
                    </tr>
                </tbody>
            </table>
        </section>
    </main>

    <script src="./script.js" type="text/javascript"></script>
</body>

</html>

script.js:

const doorImage1 = document.getElementById('door1');
const doorImage2 = document.getElementById('door2');
const doorImage3 = document.getElementById('door3');
const startButton = document.getElementById('start');
const currentStreakValue = document.getElementById('current');
const bestStreakValue = document.getElementById('best');

const botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";
const beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg";
const spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg";
const closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg";

let numClosedDoors = 3;
let currentStreak = 0;
let bestStreak = 0;

let currentlyPlaying = true;

let door1;
let door2;
let door3;

const randomChoreDoorGenerator = () => {
    const randomNum = () => Math.floor(Math.random() * numClosedDoors);
    let imgArray = [botDoorPath, beachDoorPath, spaceDoorPath];
    door1 = imgArray[randomNum()];
    door2 = imgArray[randomNum()];
    door3 = imgArray[randomNum()];
    while (door2 === door1) {
        door2 = imgArray[randomNum()];
    }
    while (door3 === door1 || door3 === door2) {
        door3 = imgArray[randomNum()];
    }
};


const isBot = door => (door.src === botDoorPath) ? true : false;

const isClicked = door => (door.src === closedDoorPath ? false : true);

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

const gameOver = status => {
    if (status === "win") {
        startButton.innerHTML = "You win! Play again?"
        if (bestStreak <= currentStreak) bestStreak++;
        currentStreak++;
    } else {
        startButton.innerHTML = "Game over! Play again?"
        if (bestStreak <= currentStreak) bestStreak = currentStreak;
        currentStreak = 0;
    }
    currentlyPlaying = false;
    currentStreakValue.innerHTML = currentStreak;
    bestStreakValue.innerHTML = bestStreak;
}

doorImage1.onclick = () => {
    if (!isClicked(doorImage1) && currentlyPlaying === true) {
        doorImage1.src = door1;
        playDoor(doorImage1);
    }
}

doorImage2.onclick = () => {
    if (!isClicked(doorImage2) && currentlyPlaying === true) {
        doorImage2.src = door2;
        playDoor(doorImage2);
    }
}

doorImage3.onclick = () => {
    if (!isClicked(doorImage3) && currentlyPlaying === true) {
        doorImage3.src = door3;
        playDoor(doorImage3);
    }
}

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

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

startRound();

So I implemented the streak scores but I also refactored the randomChoreDoorGenerator() function to make the doors more random, as with the original implementation, assuming you didn’t get the robot on the first door you would know where the other good door is.

Only thing I’m not happy with is my css styling is rubbish :sweat_smile: I need to go back to the CSS modules and refresh myself.

Thank you, you gave me a starting point! I was definitely heading the wrong way,


let doorImage1 = document.getElementById('door1');
let doorImage2 = document.getElementById('door2');
let doorImage3 = document.getElementById('door3');
let startButton = document.getElementById('start-row');
let streakCounter = document.getElementById('streakCounter');
let highestStreak = document.getElementById('highestStreak');

let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg"
let beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg"
let spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg"
let closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg"

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

let currentStreak = 0;
let bestStreak = 0;

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');
        updateScore();
        updateBestStreak();
    } else if (isBot(door)) {
        gameOver();
        resetStreak();
           }
        }

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


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

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

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

const updateScore = () => {
  currentStreak++;
  streakCounter.innerHTML = 'Current Streak: ' + currentStreak;
}

const updateBestStreak = () => {
  if (currentStreak > bestStreak) {
    bestStreak++;
  }
    highestStreak.innerHTML = 'Best Streak: ' + bestStreak;
}

const resetStreak = () => {
  currentStreak = 0;
  streakCounter.innerHTML = 'Current Streak: ' + currentStreak;
  highestStreak.innerHTML = 'Best Streak: ' + bestStreak;
}

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

startRound();
1 Like

Thank you for sharing. This post inspired me to add current and best streaks as game stats as well, however, I like to problem solve before I read others’ solutions, so I solved this by updating everything inside of the gameOver function, but it’s interesting to see how you utilized updateScore and updateBestStreak functions and called them inside of the playDoor function, I didn’t think of that!

Here’s my HTML structure:

<head>

    <title>Chore Door!</title>

    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet" type="text/css">

    <link href="resources/css/style.css" rel="stylesheet" type="text/css">

</head>

<body>

    <header>

        <img src="https://content.codecademy.com/projects/chore-door/images/logo.svg">

    </header>

    <section class="title-row">

        <img src="https://content.codecademy.com/projects/chore-door/images/star.svg">

        <p class="instructions-title">Instructions</p>

        <img src="https://content.codecademy.com/projects/chore-door/images/star.svg">

    </section>

    <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.</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>

    <section class="door-row">

        <img id="door1" class="door-frame" src="https://content.codecademy.com/projects/chore-door/images/closed_door.svg">

        <img id="door2" class="door-frame" src="https://content.codecademy.com/projects/chore-door/images/closed_door.svg">

        <img id="door3" class="door-frame" src="https://content.codecademy.com/projects/chore-door/images/closed_door.svg">

    </section>

    <button id="start" class="start-row" type="button">Good luck!</button>

    <section class="streaks">

        <div class="current streak">

            <p>Current streak:</p>

            <div id="current-streak-num" class="streak-nums">0</div>

        </div>

        <div class="best streak">

            <p>Best streak:</p>

            <div id="best-streak-num" class="streak-nums">0</div>

        </div>

    </section>

    <script src="resources/js/script.js" type="text/javascript"></script>

</body>

And here’s my JavaScript code:

const doorImage1 = document.getElementById(‘door1’);

const doorImage2 = document.getElementById(‘door2’);

const doorImage3 = document.getElementById(‘door3’);

const startButton = document.getElementById(‘start’);

const currentStreak = document.getElementById(‘current-streak-num’);

const bestStreak = document.getElementById(‘best-streak-num’);

const botDoorPath = “https://content.codecademy.com/projects/chore-door/images/robot.svg”;

const beachDoorPath = “https://content.codecademy.com/projects/chore-door/images/beach.svg”;

const spaceDoorPath = “https://content.codecademy.com/projects/chore-door/images/space.svg”;

const closedDoorPath = “https://content.codecademy.com/projects/chore-door/images/closed_door.svg”;

let currentlyPlaying = true;

let numClosedDoors = 3;

let currentStreakNum = 0;

let bestStreakNum = 0;

let openDoor1;

let openDoor2;

let openDoor3;

function isBot(door) {

if(door.src === botDoorPath) {

    return true;

}

else {

    return false;

}

}

const isClicked = (door) => {

if(door.src === closedDoorPath) {

    return false;

}

else {

    return true;

}

}

function 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 if (choreDoor === 2) {

    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);

}

}

function startRound() {

doorImage1.src = closedDoorPath;

doorImage2.src = closedDoorPath;

doorImage3.src = closedDoorPath;

numClosedDoors = 3;

currentlyPlaying = true;

startButton.innerHTML = 'Good luck!';

randomChoreDoorGenerator();

}

startButton.onclick = () => {

if(!currentlyPlaying) {

    startRound();

}

}

function gameOver(status) {

if(status === 'win') {

    startButton.innerHTML = 'You win! Play again?';

    currentStreakNum++;

    currentStreak.innerText = currentStreakNum;

    if(currentStreakNum > bestStreakNum) {

        bestStreakNum++;

        bestStreak.innerText = bestStreakNum;

    }

}

else {

    startButton.innerHTML = 'Game over! Play again?';

    currentStreakNum = 0;

    currentStreak.innerText = currentStreakNum;

}

currentlyPlaying = false;

}

startRound();

Also, I redesigned the color scheme a little:

1 Like