My askQuestion() function in Javascript is always marking the answeras wrong - javascript

The link to my pen in CodePen - http://codepen.io/PartTimeCoder/pen/WwMxEX?editors=0010
The Javascript is here:
function randomNum(digits) {
return Math.floor(Math.pow(10, digits - 1) + Math.random() * 9 * Math.pow(10, digits - 1));
}
function askQuestion(digits) {
$(".result").html("");
var factor1 = randomNum(digits);
var factor2 = randomNum(digits);
var correctanswer = factor1 * factor2;
var answer = parseInt($(".answer").val(), 10);
console.log(correctanswer);
$(".question").html(factor1 + " × " + factor2);
var score = 0;
//Problem Starts Here
$(".check").click(function() {
if (correctanswer == answer) {
$(".result").html("Correct");
score += 1;
$(".score").html(score);
askQuestion(digits);
} else {
$(".result").html("Wrong");
score -= 1;
$(".score").html(score);
}
});
//Problem Ends Here
}
$(document).ready(function() {
$(".answer").hide();
$(".check").hide();
var digits = 0;
$(".digits-1").click(function() {
digits += 1;
});
$(".digits-2").click(function() {
digits += 2;
});
$(".digits-3").click(function() {
digits += 3;
});
$(".btn").click(function() {
$(".btn").hide();
$(".answer").show();
$(".check").show();
askQuestion(digits);
});
});
In between the comments is where I think the problem is. For example when it asks 4 x 9 and i input 36, it still marks it as wrong. I don't know why this is doing this. At first I though that the inputted information might still be a string so I used parseInt on it and it still didn't work. All help is appreciated. Thanks in advance!

The problem is that you're caching the initial value of the $('.answer') element in your answer variable. When you do $('.answer').val(), it saves what is there at that time, so if the user changes their answer afterwards, it won't be reflected in your variable. What you want to do is something like this:
// Rest of your code above
var answer = $(".answer");
console.log(correctanswer);
$(".question").html(factor1 + " × " + factor2);
var score = 0;
//Problem Starts Here
$(".check").click(function() {
// Don't check what is in the input until you're ready to use the value.
if (correctanswer == parseInt(answer.val(), 10)) {
$(".result").html("Correct");
score += 1;
$(".score").html(score);
askQuestion(digits);
} else {
$(".result").html("Wrong");
score -= 1;
$(".score").html(score);
}
});

The click handler has a reference to the old answer value. You must get the value from the input everytime. Something like this:
$(".check").click(function() {
var answer = parseInt($(".answer").val(), 10);
if (correctanswer == answer) {
$(".result").html("Correct");
score += 1;
$(".score").html(score);
askQuestion(digits);
} else {
$(".result").html("Wrong");
score -= 1;
$(".score").html(score);
}
});

Related

JavaScript local storage value NaN

My problem is the JavaScript Error NaN. Everything works perfectly in my LocalHost (file: ///), but as soon as I upload it, it says "NaN" everywhere. I don't understand what could be the cause, this is my first project with JavaScript.
I left out a lot of the HTML code, but that is also explained in the JavaScript.
HTML:
<div class="coinsdisplay">
<input id="coins" type="text" disabled name="" value="0" class="coinInput">
</div>
<div class="cps">
<p id="cps">0 Coins/s</p>
</div>
<script src="public/js/main.js"></script>
<script>
window.onload= loadGame();
</script>
JS:
var coincount = 0;
var autoClick = 0;
var computer = 0;
var multiplier = 1;
// Single Click
function addCoin() {
coincount = coincount + 1
update()
}
// Updater
function update() {
document.getElementById('coins').value = coincount;
document.getElementById('cps').innerHTML = (((autoClick) + (computer*2))*multiplier) + " Coins/s";
//AutoClicker
document.getElementById('amountAutoClick').innerHTML = autoClick;
document.getElementById('cosAutoClick').innerHTML = ((autoClick+1) * 12) + " Coins";
//Computer
document.getElementById('amountComputer').innerHTML = computer;
document.getElementById('cosComputer').innerHTML = ((computer+1) * 15) + " Coins";
}
function timer() {
coincount = coincount + autoClick;
coincount = coincount + computer*2;
update()
}
setInterval(timer, 1000)
// AutoClicker
function buyAutoClick() {
if (coincount >= ((autoClick+1) * 12)) {
coincount = coincount - ((autoClick+1) * 12);
autoClick = autoClick + 1;
update()
}
}
// Computer
function buyComputer() {
if (coincount >= ((computer+1) * 100)) {
coincount = coincount - ((computer+1) * 50);
computer = computer + 1;
update()
}
}
// SaveGame
function saveGame() {
localStorage.setItem("coincount", coincount);
localStorage.setItem("autoClick", autoClick);
localStorage.setItem("computer", computer);
}
setInterval(saveGame, 1000)
function loadGame() {
coincount = localStorage.getItem("coincount");
coincount = parseInt(coincount);
autoClick = localStorage.getItem("autoClick");
autoClick = parseInt(autoClick);
computer = localStorage.getItem("computer");
computer = parseInt(computer);
update()
}
I hope someone can help me, I wish you all a nice day.
do you call the function loadGame before the saveGame function? If so, the issue is probably that there is not yet anything saved in the localStorage. So localStorage.getItem("something") just returns null, and the parseInt() converts it into NaN. Make sure that you're localStorage is filled, or that you have default values like so (notice the || 0):
function loadGame() {
coincount = localStorage.getItem("coincount") || 0;
coincount = parseInt(coincount);
autoClick = localStorage.getItem("autoClick") || 0;
autoClick = parseInt(autoClick);
computer = localStorage.getItem("computer") || 0;
computer = parseInt(computer);
update()
}

Issue linking images to dynamically created jquery elements

So, I'm very new, so apologies if this is a silly question. I have worked out a Trivia Quiz for my learning to code classes I'm taking. I want to display an image on the confirmation screen that shows whether the user was right or wrong. I think the code is correct-ish? I'm not sure what isn't working.
I left out the main Question and answer object for space. Sorry if I didn't format this ideally? I'm still kinda figuring out how things work here.
Here is my code for reference:
//array to help me iterate and insert images
var imgArray = ["question1", "question2", "question3", "question4", "question5", "question6", "question7", "question8", "question9", "question10", "question11", "question12", "question13"];
var currentQuestion = 0;
var win = 0;
var lose = 0;
var unanswered = 0;
var time = 30;
//set up divs to contain our info
var rightDiv = $("<div class='rightAns'></div>");
var timerDiv = $("<div class='countdown'><h3></h3></div>");
var questionDiv = $("<div class='question'><h1></h1></div><br>");
var answerDiv = $("<div class='answers'></div>");
//object keys to return questions in order
var keys = Object.keys(questions);
var key = keys[n];
var n = 0;
//function to setup and restart game
function reset() {
$("#start-button").hide("slow");
$("#start-here").hide("slow");
win = 0;
lose = 0;
unanswered = 0;
n = 0;
key = keys[n];
currentQuestion = 0;
$("#question-block").empty();
var reset = function () {
time = 30;
$(".rightAns").empty();
$(".rightAns").remove();
// $("#image").empty();
$("#time-remaining").append(timerDiv);
$(".countdown h3").html("Time Remaining: " + time);
$("#question-block").append(questionDiv);
$("#question-block").append(answerDiv);
}
reset();
//function to show questions
function showQuestion() {
$(".question h1").html(questions[key].question);
for (var i = 0; i < questions[key].answers.length; i++) {
$(".answers").append("<button class='answer btn btn-danger btn-lg m-1'>" + questions[key].answers[i] + "</button>");
}
$(".answers button").on("click", function () {
var selected = $(this).text();
//if then to check question correctness
if (selected === questions[key].correct) {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$(answerDiv).remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").text("That's Correct!!");
$("#image").html('<img src = ".assets/images/' + imgArray[currentQuestion] + '" width = "400px">');
win++;
currentQuestion++;
} else {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$(answerDiv).remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").text("Nope! The correct answer was: " + questions[key].correct);
$("#image").html('<img src = ".assets/images/' + imgArray[currentQuestion] + '" width = "400px">');
lose++;
currentQuestion++;
}
n++;
key = keys[n];
//checking to see if there are more questions left
if (checkForLast()) {
finalScore();
} else {
setTimeout(countReset, 3 * 1000);
setTimeout(reset, 3 * 1000);
setTimeout(showQuestion, 3 * 1000);
}
});
}
showQuestion();
var counter = setInterval(count, 1000);
//show time remaining for each question
function count() {
time--;
$(".countdown h3").html("Time Remaining: " + time);
if (time < 1) {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").html("You took too long! The correct answer was: " + questions[key].correct);
unanswered++;
n++;
key = keys[n];
if (checkForLast()) {
finalScore();
} else {
setTimeout(countReset, 3 * 1000);
setTimeout(reset, 3 * 1000);
setTimeout(showQuestion, 3 * 1000);
}
}
}
function checkForLast() {
if (key === undefined) {
return true;
}
return false;
}
//timer for the message after you choose your answer
function countReset() {
counter = setInterval(count, 1000);
}
//showthe final score screen
function finalScore() {
$(".rightAns").remove();
$("#image").empty();
$("#question-block").prepend("<h2>Unanswered: " + unanswered + "</h2>");
$("#question-block").prepend("<h2>Incorrect: " + lose + "</h2>");
$("#question-block").prepend("<h2>Correct: " + win + "</h2>");
$("#start-button").show();
$("#start-here").show();
}
};
//function to start game on button click
$(document).on("click", "#start-button", reset);
});
After tinkering for a bit, I dropped the "." at the beginning of the call and added the .jpg to the section after imgArray[currentQuestion]. That solved it. Thanks for the suggestions.

Creating a next and previous button with simple JavaScript? If statement?

So I'm trying to do a simple back forward with a picture slider. I have gotten the next on the button, but need to create the function for back.
I cannot seem to get it and cannot remember with simple pure javascript. What would the if statement be? I assume the position needs to be changed to 0. Thank you for the advice.
For the forward I have:
function Forward()
xxxx[arrayPosition].className = "thumb";
mm[arrayPosition].className = "yyy";
if(arrayPosition == xxxx.length - 1){
arrayPosition = 0; }
else{
arrayPosition = arrayPosition + 1; in memory }
xxxx[arrayPosition].className = "thumb active";
mm[arrayPosition].className = "yyy active"; }
When going back, you would want to check if the current arrayPosition is 0. If so, the array position should be updated to be the last index. For example:
if(arrayPosition === 0) {
arrayPosition = xxxx.length - 1;
} else {
arrayPosition -= 1;
}
try this
function Forward(){
xxxx[arrayPosition].className = "thumb";
mm[arrayPosition].className = "yyy";
if((arrayPosition == xxxx.length - 1)||
(arrayPosition == 0)){
arrayPosition = 0;
}else{
arrayPosition = arrayPosition + 1;
}
xxxx[arrayPosition].className = "thumb active";
mm[arrayPosition].className = "yyy active";
}

Looping JS Function Until if or else Condition is Met

I have created a function that when called with certain parameters will play out and then either tell the player they won or died based on the math. I have tested the function and it properly works, I set the parameters in the function calling so that the player would win and it displayed the win message alert. But if I increase the monster health to where the player will not win the first time the function is called, the function will not repeat itself as I tried to set up with the "else fight()" (as seen below).
My question is this, how to loop the function with the same parameters as before until the else or else if arguments are met?
Calling the function in HTML:
<a class="button" onclick="javascript:fight(8, 5, 1, 10, 3);">Test fight</a><br>
JS Function:
var playerHealth = 100;
function fight(monsterHealth, monsterDmg, monsterArmor, itemDmg, armorSts) {
newPlayerHealth = playerHealth - monsterDmg / armorSts + 2;
newMonsterHealth = monsterHealth - itemDmg / monsterArmor + 2;
if (playerHealth <= 0) {
alert('You died...');
}
else if (newMonsterHealth <= 0) {
alert('You won!');
}
else
{
var newPlayerHealth = playerHealth;
fight(newMonsterHealth, monsterDmg, monsterArmor, itemDmg, armorSts);
}
}
EDIT: Updated function and it says you win no matter how high the monster's damage or health is.
In your code playerHealth was intialize inside function which was resetting players health to 100 in recursive call.
newMonsterHealth was also not persisted considering recursive calls.
<html>
<head>
<script>
var playerHealth = 100;
function fight(monsterHealth, monsterDmg, monsterArmor, itemDmg, armorSts) {
playerHealth = playerHealth - Math.floor(monsterDmg / armorSts) ;
console.log("player helath"+playerHealth);
monsterHealth = monsterHealth - Math.floor(itemDmg / monsterArmor) ;
console.log("monster helath"+monsterHealth);
if (playerHealth <= 0) {
alert('You died...');
}
else if (monsterHealth <= 0) {
alert('You won!');
}
else fight(monsterHealth, monsterDmg, monsterArmor, itemDmg, armorSts);
}
</script>
</head>
<body>
<a class="button" onclick="javascript:fight(100, 40, 1, 10, 3);">Test fight</a><br>
</body>
</html>
P.S. I removed your +2 logic (I won't understood why you were adding)
You probably need for a recursive function that ends when certain condition will be met.
here is an example:
function recursive(target, i) {
target.innerHTML += '<br>' + i;
console.log('index is', i);
if(i > 100) {
return target.innerHTML += '<br>' + 'END';
}
return recursive(target, ++i);
}
document.addEventListener('DOMContentLoaded', function() {
recursive(document.getElementById('test'), 0)
});
<h1 id="test"></h1>

Resetting jquery varible to lowest possible value that doesn't exist

This script generate divs with cloud images that fly from left to right with random height and intervals. It generally works but it keeps incrementing divs "id" infinitely. I can't figure out how to reset the counter being safe that never two identical "id"s will exist in the same time.
function cloudgenerator(){
var nr=1;
var t1 = 20000;
var t2 = 50000;
function cloud(type,time,nr){
$("#sky").append("<div id=\"cloudFL"+nr+"\" class=\"cloud"+type+"\" ></div>");
setTimeout(function() {
$("#cloudFL"+nr).css({top:Math.floor(Math.random() * 400)+'px'}).animate({
left:'100%',
},time,'linear',function(){$(this).remove();
});
}, Math.floor(Math.random() * t1));
};
function wave(){
var tx = 0;
setInterval(function(){
cloud(1,t1,nr);
nr++;
var n = $( "div.cloud1" ).length;
$( "span" ).text( "There are " + n +" n and "+ tx +" tx")
if(tx < n){tx = n}
else(tx = 1)
},500);
};
wave()};
cloudgenerator()
In the bottom, there is an instruction that checks if number of divs is starting to drop and presents those values in span for debugging.
Quick and easy solutionYou could loop through the id's in JQuery, starting from the lowest number, until you find a JQuery selector that yields 0 results...
var newid = 0;
var i = 1;
while(newid == 0) {
if( $('#cloudFL' + i).length == 0 ) { newid = i; }
else { i++; }
}
JSFIDDLE DEMO
Alternative solution (scalable)
Given that you may have many clouds onscreen at one time, you could try this alternative approach.
This approach creates an array of 'used ids' and the wave function then checks if any 'used ids' are available before creating a new id for the cloud function. This will run quite a bit more efficiently that then above 'quick fix solution' in situations where many clouds appear on screen.
function cloudgenerator(){
var nr=1;
var t1 = 20000;
var t2 = 50000;
var spentids = [];
function cloud(type,time,id){
$("body").append('<div id="' + id + '" class="cloud' + type + '" >' + id + '</div>');
setTimeout(function() {
$('#'+id).css({top:Math.floor(Math.random() * 400)+'px'}).animate({
left:'100%',
},time,'linear',function(){
spentids.push( $(this).attr('id') );
$(this).remove();
});
}, Math.floor(Math.random() * t1));
};
function wave(){
setInterval(function(){
if(spentids.length == 0) {
cloud(1,t1,"cloudFL" + nr);
nr++;
} else {
spentids = spentids.sort();
cloud(1,t1,spentids.shift());
}
},500);
};
wave()};
cloudgenerator()
JSFIDDLE DEMO - ALTERNATIVE
Why not get the timestamp and add this to your id?
If you don´t need the ids i would stick to #hon2a and just add the styling to the class and remove the ids.
And another solution:
You could make a check if ID xyz is used. Like this e.g.
var cloudCount = jQuery('.cloud20000').length + jQuery('.cloud50000').length + 10;
for(var i = 0; i <= cloudCount; i++) {
if(jQuery('#cloudFL' + i).length <= 0) {
nr = i;
return false;
}
}
cloud(1,t1,nr);

Categories

Resources