function doesn't register variable change - javascript

I'm trying to make a small game with Javascript where the user has to enter the sum of two random numbers (a and b).When you click on a button or when you press enter, it calls a function which checks if the sum is the same as what you entered. If that's the case, the function play() is called again and a and b change. It works fine the first time, but the second time, unless the second sum is equal to the first one, it doesn't work. What does my answer() function acts as if a and b didn't change ?
let count = 0;
function play() {
if (count < 10) {
// setTimeout(loss, 30000);
count += 1;
document.getElementById("user-answer").value = "";
var a = Math.floor(Math.random() * 20) + 1;
var b = Math.floor(Math.random() * 20) + 1;
var question = document.getElementById("question");
question.textContent = a + " + " + b;
function answer() {
var result = a + b;
var userAnswer = document.getElementById("user-answer").value;
if (userAnswer == result) {
sound.play();
//clearTimeout();
play();
}
if (userAnswer != result) {
document.getElementById("user-answer").classList.add("wrong");
// document.getElementById("user-answer").disabled = true;
console.log(result);
console.log(userAnswer);
// setTimeout(remove, 1000);
}
}
window.addEventListener("keypress", function(event) {
if (event.key == "Enter") {
answer();
}
})
document.getElementById("send-answer").addEventListener("click", answer);
} else {
document.getElementById("win").textContent = "You won!";
}
}

Well, calling play repeatedly will create new local variables a and b and new instances of answer function closing over those a, b and will add new event listeners every time. You could:
move the declaration of answer outside play
share a,b across answer and play
add event listeners only once
Here is somewhat refactored version for a start:
(function () {
let count = 0;
let a = 0, b= 0;
function play() {
if (count < 10){
// setTimeout(loss, 30000);
count += 1;
document.getElementById("user-answer").value = "";
a = Math.floor(Math.random() * 20) + 1;
b = Math.floor(Math.random() * 20) + 1;
var question = document.getElementById("question");
question.textContent = a + " + " + b;
} else {
document.getElementById("win").textContent = "You won!";
}
}
function answer(){
var result = a + b;
var userAnswer = document.getElementById("user-answer").value;
if(userAnswer == result){
//sound.play();
//clearTimeout();
play();
}
if(userAnswer != result) {
document.getElementById("user-answer").classList.add("wrong");
// document.getElementById("user-answer").disabled = true;
console.log(result);
console.log(userAnswer);
// setTimeout(remove, 1000);
}
}
window.addEventListener("keypress", function(event){
if (event.key == "Enter"){
answer();
}
})
document.getElementById("send-answer").addEventListener("click", answer);
play();
})()
<div>
<div id="question">
</div>
<input type="text" id="user-answer"/>
<input type="button" id="send-answer" value="Send answer"></input>
<div id="win">
</div>
</div>

Related

javascript I have a sequence that runs continuously, but need it to stop when an image is clicked

I have very little to no knowledge when it comes to using JavaScript. I have 24 of the same image given an id from q1 - q24. my code allows for the 24 images to be changed to image2 one at a time, but I need for it to stop and display a text/alert when image2 is clicked.
<script>
{
let num = 1;
function sequence()
{
let back = 1;
while (back < 25)
{
if(back == 1)
{
document.getElementById("q24").src = "question.jpg";
}
else
{
document.getElementById("q" + (back-1)).src = "question.jpg";
}
back++
}
document.getElementById("q" + num).src = "question2.png";
num = num + 1;
if(num > 24){num = 1;}
}
setInterval(sequence, 500);
}
</script>
Save the interval timer to a variable. Then add a click listener to all the images that stops the timer if the current image is the one showing question2.jpg.
{
let num = 1;
for (let i = 1; i <= 24; i++) {
document.getElementById(`q${i}`).addEventListener("click", function() {
if (i == num) {
clearInterval(interval);
}
});
}
let interval = setInterval(sequence, 500);
function sequence() {
for (let i = 1; i <= 24; i++) {
if (i == num) {
document.getElementById(`q${i}`).src = "question2.jpg";
} else {
document.getElementById(`q${i}`).src = "question.jpg";
}
num = num + 1;
if (num > 24) {
num = 1;
}
}
}
}
While I don't fully understand your use case, you could create a click event listener on the document and check the target's src in it.
document.addEventListener('click', function(e) {
if (e.target.src === 'question2.png') {
alert('Clicked question 2');
}
});

How can I get setInterval() to increase by 1 instead of 12?

My game has two players that get random numbers, and the person who has the bigger number gets 1 "win". My while loop is for the "auto-roll" button, and instead of clicking "roll dice" each time, auto-roll will do it for you until one player has wins == game limit # (bestof.value). No matter where I put my setInterval it increases by a bunch at a time. If bestof.value = 10 then each interval displays at least 10 wins for one player at a time.
checkBox.checked = input checkmark that enables auto-roll feature. So this setInterval will only be active while the auto-roll loop is active.
Anyways, what am I doing wrong?
button.addEventListener("click", myFunction);
function myFunction() {
let random = Math.floor((Math.random() * 6) + 1);
let random2 = Math.floor((Math.random() * 6) + 1);
screenID.innerHTML = random;
screenIDD.innerHTML = random2;
if (random > random2){
winNumber.innerHTML = ++a;
} else if(random2 > random){
winNumba1.innerHTML = ++b;
} else {
console.log("Draw");
}
if (a > b){
winNumber.style.color = 'white';
winNumba1.style.color = 'black';
} else if(b > a){
winNumba1.style.color = 'white';
winNumber.style.color = 'black';
} else {
winNumber.style.color = 'black';
winNumba1.style.color = 'black';
}
if (checkBox.checked){
setInterval(myFunction, 2000)
while(a < bestof.value && b < bestof.value){
myFunction();
}};
if (winNumba1.innerHTML == bestof.value){
winAlert.style.display = "flex";
console.log('winNumba1 wins!');
} else if (winNumber.innterHTML == bestof.value){
winAlert.style.display = "flex";
console.log('winNumber wins!');
} else {}
};
I wrote a simplified js only version of your game here since I don't have html at hand, but I am sure you can adjust it to your environment.
Main difference: I check if someone won and use return to stop the function
If no one won and autoplay is activated I autoplay after 500ms again.
let playerA = 0
let playerB = 0
let autoPlay = true
let bestOf = 3
function myFunction() {
let random = Math.floor((Math.random() * 6) + 1);
let random2 = Math.floor((Math.random() * 6) + 1);
console.log("New Round " + random + " vs " + random2)
if (random > random2) {
playerA++
} else if (random2 > random) {
playerB++
} else {
console.log("Draw");
}
if (playerA > playerB) {
console.log("a is winning")
} else if (playerB > playerA) {
console.log("b is winning")
} else {
console.log("There has been a draw")
}
if (playerA == bestOf) {
console.log('A won');
return
} else if (playerB == bestOf) {
console.log('B won');
return
}
if (autoPlay) {
setTimeout(myFunction, 500)
};
};
myFunction()

Delete user input if higher than assigned variable javascript

I'm a new programmer learning HTML/CSS/Javascript, and was fiddling around with it until I came across a bug. I was making the computer guess my number (0-5), but then realized if I put in a number higher than 5, the website just crashes. Is there any way I can make it so that if the user puts in a number higher than 5 it will just delete it automatically? Or is that not Javascript. Thanks in advance :)
document.getElementById("guess").onclick=function() {
var gotit=false;
var guesses=1;
var x;
while(gotit==false) {
x=Math.random();
x=6*x;
x=Math.floor(x);
if(document.getElementById("myNumber").value==x) {
gotit=true;
} else {
guesses++;
}
}
alert("Got it! It was a " + x + ". It only took me " + guesses + " guesses!");
}
Try this :
document.getElementById("guess").onclick=function() {
if(document.getElementById("myNumber").value > 5) {
document.getElementById("myNumber").value = "";
alert("Please provide a number that is with in 0 to 5");
} else {
var gotit=false;
var guesses=1;
var x;
while(gotit==false) {
x=Math.random();
x=6*x;
x=Math.floor(x);
if(document.getElementById("myNumber").value==x) {
gotit=true;
} else {
guesses++;
}
}
alert("Got it! It was a " + x + ". It only took me " + guesses + " guesses!");
}
Than define a onchange function to check length:
document.getElementById("myNumber").onchange = function (ev){
try{
var target = document.getElementById("myNumber");
if(parseInt(target.value) > x) { // can throw exception, when given a non number
target.value="";
}
} catch(ex) {
alert('Not a number');
}
};
IMPORTANT:
You have a greater problem here: You are generating a random number, and then comparing it to input( that does not change). This is an infinite loop. Because this is a random operation, and you can hit same number more than once.
You need to generate your number first (before click event on 'guess' button), before clicking on quess button. Like so:
var luckyNumber = x;
var guesses=1;
document.getElementById("start").onclick=function(){ //init counters once
guesses=0;
x=Math.floor(Math.random()*6);
gotit = false;
}
document.getElementById("guess").onclick=function() { // guess as many times as you want
if(document.getElementById("myNumber").value==x) {
gotit=true;
}
guesses++;
if(gotit){
alert("Got it! It was a " + x + ". It only took me " + guesses + " guesses!");
}
}
But if you want to computer to quess your number, than you need to limit number of guesses (add a counter), or it will hang eventualy.
I took this as a little challenge and just went ahead and re-did your little game. Hope this helps.
Demo here
(function (guess, tryy, message) {
var comp = function () {
return Math.floor(Math.random() * 6)
};
var number = comp();
var count = 0;
var test = function () {
var val = guess.value;
if (!Number.isNaN(val) && val >= 0 && val <= 5) {
switch (true) {
case val > number:
message.innerHTML = 'Your guess was too high!';
count++;
break;
case val < number:
message.innerHTML = 'Your guess was too low!';
count++;
break;
case val == number:
count++;
message.innerHTML = 'Congratulations you found the number! It took you ' + count + ' guesses';
//Reseting game here
setTimeout(function(){
count = 0;
number = comp();
guess.value = '';
message.innerHTML = 'Your game has been reset';
}, 2000);
break;
};
}
};
tryy.onclick = test;
guess.onkeyup = function (e) {
if (e.keyCode == 13) {
test();
}
}
})(document.getElementById('guess'), document.getElementById('tryy'), document.getElementById('message'));

curious css setting issue using setInterval

I'm trying to make a palindrome checker that changes the currently compared letters as it recurs.
Essentially, callback will do:
r aceca r
r a cec a r
ra c e c ar
rac e car
My JS Bin shows that the compared letters change green sometimes, but if you run it again, the letters won't change. Why is there a difference in results? It seems to sometimes run in Chrome, more often in FireFox, but it's all intermittent.
Code if needed (also available in JS Bin):
var myInterval = null;
var container = [];
var i, j;
var set = false;
var firstLetter, lastLetter;
$(document).ready(function(){
$("#textBox").focus();
$(document).click(function() {
$("#textBox").focus();
});
});
function pal (input) {
var str = input.replace(/\s/g, '');
var str2 = str.replace(/\W/g, '');
if (checkPal(str2, 0, str2.length-1)) {
$("#textBox").css({"color" : "green"});
$("#response").html(input + " is a palindrome");
$("#palindromeRun").html(input);
$("#palindromeRun").lettering();
if (set === false) {
callback(str2);
set = true;
}
}
else {
$("#textBox").css({"color" : "red"});
$("#response").html(input + " is not a palindrome");
}
if (input.length <= 0) {
$("#response").html("");
$("#textBox").css({"color" : "black"});
}
}
function checkPal (input, i, j) {
if (input.length <= 1) {
return false;
}
if (i === j || ((j-i) == 1 && input.charAt(i) === input.charAt(j))) {
return true;
}
else {
if (input.charAt(i).toLowerCase() === input.charAt(j).toLowerCase()) {
return checkPal(input, ++i, --j);
}
else {
return false;
}
}
}
function callback(input) {
$("#palindromeRun span").each(function (i, v) {
container.push(v);
});
i = 0;
j = container.length - 1;
myInterval = setInterval(function () {
if (i === j || ((j-i) === 1 && input.charAt(i) === input.charAt(j))) {
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
$(container[i]).css({"color": "green"});
$(container[j]).css({"color": "green"});
i++;
j--;
}, 1000);
}
HTML:
<input type="text" id="textBox" onkeyup="pal(this.value);" value="" />
<div id="response"></div>
<hr>
<div id="palindromeRun"></div>
I directly pasted the jsLettering code in the JSBin, but here is the CDN if needed:
<script src="http://letteringjs.com/js/jquery.lettering-0.6.1.min.js"></script>
Change:
myInterval = setInterval(function () {
if (i === j) {
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
to:
myInterval = setInterval(function () {
if (i >= j) {//Changed to prevent infinite minus
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
demo

Adding price to total when checkbox is selected

I would like to add a $5.00 charge whenever the txtBwayEDUGift checkbox is selected. The javascript code I currently have is reducing the amount when checkbox is unchecked, but not applying the charge when selected. I can provide additonal code if needed.
Here is my input type from my aspx page:
<input type="checkbox" name="txtBwayEDUGift" id="txtBwayEDUGift" onchange="checkboxAdd(this);" checked="checked" />
Here is my javascript:
{
var divPrevAmt;
if (type == 0)
{
divPrevAmt = document.getElementById("divBwayGiftPrevAmt");
}
else if (type == 1)
{
divPrevAmt = document.getElementById("divBwayEDUGiftPrevPmt");
}
var txtAmt = document.getElementById(obj);
var amt = txtAmt.value;
amt = amt.toString().replace("$","");
amt = amt.replace(",","");
var prevAmt = divPrevAmt.innerHTML;
try
{
amt = amt * 1;
}
catch(err)
{
txtAmt.value = "";
return;
}
if (amt >= 0) //get the previous amount if any
{
if (type == 0)
{
if (prevAmt.toString().length > 0)
{
prevAmt = prevAmt * 1;
}
else
{
prevAmt = 0;
}
}
else if (type == 1)
{
if (prevAmt.toString().length > 0)
{
prevAmt = prevAmt * 1;
}
else
{
prevAmt = 0;
}
}
//now update the master total
var total = document.getElementById("txtTotal");
var dTotal = total.value.toString().replace("$","");
dTotal = dTotal.replace(",","");
dTotal = dTotal * 1;
var newTotal = dTotal - prevAmt;
newTotal = newTotal + amt;
divPrevAmt.innerHTML = amt.toString();
newTotal = addCommas(newTotal);
amt = addCommas(amt);
txtAmt.value = "$" + amt;
total.value = "$" + newTotal;
}
else
{
txtAmt.value = "";
return;
}
}
function disable()
{
var txtTotal = document.getElementById("txtTotal");
var txt = txtTotal.value;
txtTotal.value = txt;
var BwayGift = document.getElementById("txtBwayGift");
BwayGift.focus();
}
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
var newTotal = x1 + x2;
if (newTotal.toString().indexOf(".") != -1)
{
newTotal = newTotal.substring(0,newTotal.indexOf(".") + 3);
}
return newTotal;
}
function checkChanged()
{
var cb = document.getElementById("cbOperaGala");
if (cb.checked == true)
{
var tableRow = document.getElementById("trCheckbox");
tableRow.style.backgroundImage = "url('images/otTableRowSelect.jpg')";
}
else if (cb.checked == false)
{
var tableRow = document.getElementById("trCheckbox");
tableRow.style.backgroundImage = "";
}
}
function alertIf()
{
var i = 0;
for (i=5;i<=10;i++)
{
try{
var subtotal2 = document.getElementById("txtSubTotal" + i);
var dSubtotal2 = subtotal2.value;
dSubtotal2 = dSubtotal2.replace("$","");
dSubtotal2 = dSubtotal2 * 1;}
catch (Error){dSubtotal2 = 0}
if (dSubtotal2 > 0)
{
alert("You have selected the I want it all package, \n however you have also selected individual tickets to the same events. \n If you meant to do this, please disregard this message.");
break;
}
}
}
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
return (key != 13);
}
//Add $5.00 donation to cart
function checkboxAdd(ctl) {
if (ctl.checked == true) {
// alert("adding $5");
calculateTotal(5, "A");
} else {
// alert("deducting $5");
calculateTotal( 5, "S");
}
}
</script>
I do not understand the context of the scenario. When a user clicks the checkbox are you making an HTTP request to the server? Or is this a simple form POST page? What is calculateTotal() doing?
I figured it out. So the functionality I had in place was fine.
//Add $5.00 donation to cart
function checkboxAdd(txtBwayEDUGift) {
if (txtBwayEDUGift.checked == true) {
// alert("adding $5");
calculateTotal(5, "A");
} else {
// alert("deducting $5");
calculateTotal(5, "S");
}
}
But I needed to add a load function:
function load() {
calculateTotal(5, "A");
}
<body onload="load()">
Along with adding a reference to my c# page:
if (txtBwayEDUGift.Checked)
{
addDonations(5.00, 93);
}
You can use jQuery :)
$(txtBwayEDUGift).change(calculateTotal(5, "S"));

Categories