Issue with negative scores in a simple JS game - javascript

I've created a simple JS game where it asks the player to add two random numbers together, and gives them three options to select -- one of the answers is correct and the other two are incorrect. The player only gets 10 seconds to answer each question. When the player selects the correct answer their score is incremented by +1, and it all works as expected.
...Until I tried to add a feature to -1 their score when they get a question wrong (by selecting either of the 2x wrong answers). Everything works as expected when the numbers are positive, however if they get into negatives then weird things start happening and I have no idea why: The score decrements by more than 1, and even when the player gets an answer correct the score still decrements.
As a workaround I tried to add a condition where if the score is below 0 it would reset to 0, so it can't go negative -- however if I do that the score will not increment past 1, no matter how many answers the players get right.
The game and code is here: https://codepen.io/tmnsoon/full/XWVWvmb
let score = 0
function startCountdown(seconds) {
let counter = seconds;
const interval = setInterval(() => {
document.getElementById("timer").innerHTML = counter;
counter--;
if (counter < 0 ) {
clearInterval(interval);
game()
startCountdown(10)
}
}, 1000);
}
function game(){
let answer1 = Math.floor(Math.random()*500)
let answer2 = Math.floor(Math.random()*500)
document.getElementById("challenge").innerHTML = `What is ${answer1} plus ${answer2}`
console.log('Ding!');
let number1 = Math.floor(Math.random()*1000)
let number2 = answer1+answer2
let number3 = Math.floor(Math.random()*1000)
let gameNums = [number1, number2,number3]
shuffle(gameNums)
console.log(gameNums)
document.getElementById("button1").innerHTML = gameNums[0]
document.getElementById("button2").innerHTML = gameNums[1]
document.getElementById("button3").innerHTML = gameNums[2]
function handleClick(event) {
if (event.target.tagName !== "BUTTON") {
return;
}
let buttonValue = event.target.innerText;
if (buttonValue == answer1+answer2){
document
.querySelector("#result")
.innerText = "Correct!";
score++
document.getElementById("score").innerHTML = `Score = ${score}`
game()
}
else if (buttonValue == number1 || number3){
document
.querySelector("#result")
.innerText = "Incorrect!";
score--
document.getElementById("score").innerHTML = `Score = ${score}`
}
}
//listner
document
.querySelector(".buttons")
.addEventListener("click", handleClick);
//end
}
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
If anyone could shed light on what I've done wrong it would be greatly appreciated. Thanks!

The problem is in your else if condition for decreasing the score: else if (buttonValue == number1 || number3).
You're telling the compiler that it should enter that block if the previous if condition is not true AND (if the buttonValue == number1 OR if number3 is truthy).
You probably wanted to write else if (buttonValue == number1 || buttonValue == number3).
Some additional advice: you don't need the condition in the else statement at all, it's enough that the buttonValue isn't the correct answer, there's no need to check which incorrect answer it is.
You can just have else {.

Related

House Robber 2 Leetcode problem giving incorrect output

I am solving the Leetcode problem House Robber II. The problem says,
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police. The constraint is you can not rob two adjacent houses. Also, the houses in that place are arranged in a circle, so the first and last houses are also adjacent.
Here is the link: https://leetcode.com/problems/house-robber-ii/
I have used the top-down approach to solve it. This is function definition: dp(index, isFirstHouseRobbed) In the function body, I am checking if(index === nums.length - 1 && isFirstHouseRobbed === true) return 0;. Here is the complete function:
var rob = function(nums) {
const dp = (index, isFirstHouseRobbed) => {
if (index >= nums.length) {
return 0;
}
if (index === nums.length - 1 && isFirstHouseRobbed === true) {
return 0;
}
if (index === 0) {
// Two choice: rob or not rob
// rob
let max1 = dp(index + 2, true) + nums[index];
// not rob
let max2 = dp(index + 1, false);
return Math.max(max1, max2);
} else {
// Two choice: rob or not rob
// rob
let max1 = dp(index + 2, false) + nums[index]; // This does not work
// --->(line 20) let max1 = dp(index + 2, isFirstHouseRobbed) + nums[index]; // But this works.
// not rob
let max2 = dp(index + 1, false); // This does not work
// --->(line23) let max2 = dp(index + 1, isFirstHouseRobbed); // But This works.
return Math.max(max1, max2);
}
}
return dp(0, false);
};
This solution works only if I use line20 and line23. The only difference between those two lines and their previous lines is I am using the variable isFirstHouseRobbed instead of passing false. My question is, in the main function call I am calling dp(0, false). So, the value of isFirstHouseRobbed should be set to false. My question is, why using false instead of isFirstHouseRobbed not working, where the value of isFirstHouseRobbed is set to false anyway. Maybe I am missing something easy, but could not figure it out. Any help would be greatly appreciated.
It's not always false; one of your recursive cases passes true for the second parameter. This makes sense — there wouldn't be much point in having it be a parameter if it never changed.

Codewars problem 'Happy numbers' how can i make some changes on my code to make it works?

I am working Codewars problem' Happy Numbers ' here is the link https://www.codewars.com/kata/happy-numbers-5/train/javascript Here is the problem, when I am running the code when n > 98 the maximum call stack size is reached. How can I make some changes on my code to fix this problem?
function happyNumbers(x){
var res = [];
for (let i = 1; i <= x; i++){
var str = [];
if (helper(str,i)){res.push(i)}
}
return res
}
function helper(str,n){
var num = 0;
if (n === 1){return true}
if (str.indexOf(n) > -1){return false}
str.push(n);
if (n.toString().length === 1){num = Math.pow(n,2).toString()}
if (n.toString().length >= 2){
num = n.toString().split('')
.reduce((a,b) => Math.pow(a,2)+ Math.pow(b,2)).toString();
}
return helper(str,Number(num))
}
Maybe some more simplyfing would help by
using a Set for visited value to prevent circular loop which never ends (Memoization),
taking numerical values at all, only for splitting into single digits, a string is taken,
summing up by using a simple multiplication,
now some exit function:
check if sum is 1, exit the function with true,
check if sum is already visited and if so, exit with false,
return by calling the function again with sum and updated set visited with sum.
function happyNumbers(x, visited = new Set) {
var sum = 0, value;
for (value of String(x)) sum += value * value;
if (sum === 1) return true;
if (visited.has(sum)) return false;
return happyNumbers(sum, visited.add(sum));
}
console.log(happyNumbers(123));

JS Function Calls from HTML + Reactive display

The game is WAR, or Get Your Neighbour, a traditional game utilising a standard deck of 52 cards, no jokers. Currently the code recognises when a card is above 10 and so the rules of the game are being followed, all that is great, I've designed a timer that takes the value of the card 2-14, subtracts 10, then uses that number for the round of turns the other player has to draw above 10 before you win. Still building the cooperative/multiplayer element but for now, I'd just like to get this bloody button working!
When I click it, it does nothing. Before, it would tell me that "'timerf' is not a function". I'm probably doing something very obvious like problems with the order that things are loaded/data is parsed, but I'm still learning so I'd appreciate any help! Any questions, let me know.
var card = null; // setem 160517
var timer = null; //
window.onload = function() {
function draw(min, max) { // draw a card between 2-14
card = document.getElementById("draw").innerHTML = Math.floor(Math.random()*((max - min)+1) + min); // min 2, max 14
if (card > 10) {
timer = card - 10;
timerf(timer);
} else if (card < 11 && timer > 0) {
timer = timerf(timer-1);
}
} // draw
//draw(2,14);
document.getElementById("clickMe").onclick = draw(2,14);
} // window.onload
function timerf(timer) { // print turns to win
if (timer > 0 && timer < 5 && timer != 1) { // print turns to win
console.log("you have " + timer + " turns to win!");
} else if (timer == 1) {
console.log("you have " + timer + " turn to win!");
}
}
<div id="draw"></div>
<button id="clickMe">WAR!</button>
The return value of the draw function is undefined because it has no return statement.
document.getElementById("clickMe").onclick = draw(2,14);
… so you are assigning undefined to the onclick property.
You have to assign the function you want to call.

Whats wrong with my code? - dice rolling

I am trying to log to the console a message saying : Gratz! You gained 5 points!' after you rolled two the same numbers after each other.
can someone explain me what is wrong with my code?
<script>
var d1 = Math.floor(Math.random()*6) +1;
var diceRolls = [];
function rollDice() {
var die1 = document.getElementById("die1");
var status = document.getElementById("status");
var d1 = Math.floor(Math.random()*6) +1;
console.log("You rolled "+d1+".");
diceRolls.push(d1);
}
if(diceRolls[diceRolls.length - 1] === d1) {
console.log("You won 5 points!");
}
</script>
The problem with your code is that you're checking outside the function, and the condition is not correct. First you need to make sure that the dice has been rolled at least two times, then you compare the two last values. And as #Bergi noted, you also need to call the function, although I guess you're already doing that. Below is the correct solution:
var diceRolls = [];
var totalDiceRolls = 0;
// you set this to whatever you want the limit to be
var maxDiceRolls = 10;
function rollDice() {
if (++totalDiceRolls > maxDiceRolls)
{
alert(maxDiceRolls + " dice rolls allowed at max!");
return;
}
var die1 = document.getElementById("die1");
var status = document.getElementById("status");
var d1 = Math.floor(Math.random()*6) +1;
console.log("You rolled "+d1+".");
diceRolls.push(d1);
if(diceRolls.length > 1 && diceRolls[diceRolls.length - 2] == d1) {
console.log("You won 5 points!");
}
}
You never loop the result, and you assign d1 with a random number, but do nothing with it.
You need to roll the dice and each time, loop the array to find if 2 numbers are the same, at the moment you don't loop, so there is no way to know if 2 numbers are equals.

Javascript countdown then count-up from a prompted variable?

Please Help! I'm new to Javascript, so there's probably an easier solution to this. Basically, I need it to prompt for a number and then count down from that number to zero. Once it reaches zero, I need it to count-up and stop at the same prompted number.
I got it to count down at first, then I completely butchered it, I have no clue what to do.
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var counter = setInterval(timer, 1000);
console.log(startNum);
function timer() {
startNum--; // reduce number by 1
console.log(startNum);
if (startNum <= 0) {
clearInterval(counter);
}
}
var counter = setInterval(timer2, 1000);
var endNum = 0
function timer2() {
console.log(endNum)
endNum++; // add number by 1
console.log(endNum);
if (endNum >= startNum) {
clearInterval(counter);
}
}
</script>
You've got a couple issues here. the first one was pointed out by Rob in the comments. You're running both functions at the same time.
The other issue you have is that you're never storing the number. You're just subtracting and adding to nothing essentially.
So -
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var currentNum = startNum;
var counter = setInterval(timer, 1000);
function timer() {
console.log(currentNum);
currentNum -= 1; // reduce number by 1
console.log(currentNum);
if (currentNum == 0) {
clearInterval(counter);
counter = setInterval(timer2, 1000);
}
}
function timer2() {
console.log(currentNum)
currentNum += 1; // add number by 1
console.log(currentNum);
if (currentNum == startNum) {
clearInterval(counter);
}
}
</script>
Something like this should do the trick. Basically creating another variable to hold your start number and consider that the current number and the value that is going to change.
here's a fiddle - http://jsfiddle.net/w5FM6/
cheers

Categories