Resetting variables is not resetting game? - javascript

I am creating a Simon game and it works on round one, but once your each round two it immediately says incorrect.
jsfiddle
I reset all variables between the rounds, but it still seems to save them as it instantly says "Game Over!"
JS:
function makeGuess() {
...
var checkForComplete = setInterval(function () {
if (yourAnswer.length >= round) {
clearInterval(checkForComplete);
yourString = yourAnswer.toString();
correctString = correctAnswer.toString();
if (yourString === correctString) {
alert('Correct');
round++;
yourAnswer = [];
correctAnswer = [];
yourString = "";
correctString = "";
playSimon();
}
else {
alert("Game Over!");
}
}
}, 500)
Here is the playSimon() function:
function playSimon() {
setTimeout(function () {
color = Math.floor(Math.random() * 4);
if (color == 0) {
correctAnswer.push(0);
$('#redButton').addClass('lightOn');
setTimeout(function () {
$('#redButton').removeClass('lightOn');
}, 500);
}
else if (color == 1) {
correctAnswer.push(1);
$('#blueButton').addClass('lightOn');
setTimeout(function () {
$('#blueButton').removeClass('lightOn');
}, 500);
}
else if (color == 2) {
correctAnswer.push(2);
$('#greenButton').addClass('lightOn');
setTimeout(function () {
$('#greenButton').removeClass('lightOn');
}, 500);
}
else if (color == 3) {
correctAnswer.push(3);
$('#yellowButton').addClass('lightOn');
setTimeout(function () {
$('#yellowButton').removeClass('lightOn');
}, 500);
}
i++;
if (i <= round) {
playSimon();
}
else {
makeGuess();
}
}, 700);
}
Why is it alerting Game Over instantly on round 2?

Because you are binding the click events multiple times:
function makeGuess() {
$('#redButton').click(function() {
yourAnswer.push(0);
});
$('#blueButton').click(function() {
yourAnswer.push(1);
});
$('#greenButton').click(function() {
yourAnswer.push(2);
});
$('#yellowButton').click(function() {
yourAnswer.push(3);
});
...
}
Each time makeGuess() is called, the buttons are bound yet another click event listener. First time it's done (first level), there's only 1 event listener so it's working correctly, but from the second level onward each buttons are bound with 2 identical click listener, and when the player click a button, the function is called twice => yourAnswer is pushed twice immediately, which result in an incorrect answer => game over.
A quick fix is to unbind all click events on the 4 buttons before binding them all again, optimally immediately before the next playSimon() is called.
if (yourString === correctString) {
alert('Correct');
round++;
yourAnswer = [];
correctAnswer = [];
yourString = "";
correctString = "";
$('#redButton').unbind( "click" );
$('#blueButton').unbind( "click" );
$('#greenButton').unbind( "click" );
$('#yellowButton').unbind( "click" );
playSimon();
} else {
alert("Game Over!");
}
JsFiddle: https://jsfiddle.net/dfk2am7e/1/

AVAVT is right, however instead of unbinding, rather just bind the event once off.
I have updated your JSFiddle and optimized your code a little bit.
https://jsfiddle.net/dfk2am7e/3/
// Run this when the page has loaded to ensure HTML is there.
$(function(){
$('#redButton').click(function() {
yourAnswer.push(0);
});
$('#blueButton').click(function() {
yourAnswer.push(1);
});
$('#greenButton').click(function() {
yourAnswer.push(2);
});
$('#yellowButton').click(function() {
yourAnswer.push(3);
});
});

Related

js differ click and double click

I am trying to differentiate click and dblclick events by javascript. I tried stopPropagation in dblclick however did not work. hence I coded my own function using setTimeout tries to avoid calling the other when calling one.
/* dblclick differ click
takes two functions as param and one element
to bind the event listener on
*/
function cdblclick(click, dblclick, el){
el.cooled = true;
el.addEventListener('click', function(){
if(el.cooled){
setTimeout(function(){
if(!el.cdblc){el.cdblc = 0}
el.cdblc++;
if(el.cdblc === 1){
setTimeout(function(){
if(!el.doubled){
console.log('click')
// click();
el.cdblc = 0;
el.cooled = true;
el.doubled = false;
}
}, 300);
}else if(el.cdblc === 2){
console.log('double')
// dblclick();
el.doubled = true;
el.cdblc = 0;
el.cooled = true;
}else{
}
}, 250);
}
});
}
however, it does not work properly. I will be so glad if you ca give me a hand.
Thanks for the suggestions of divide to two elements, however, I must implement both events on the same element
solution
thanks to all the helps.
/* dblclick differ click
takes two functions as param and one element
to bind the event listener on
*/
function cdblclick(click, dblClick, el) {
let clickedTimes = 0;
const incrementClick = () => {
clickedTimes++;
};
const reset = () => {
clickedTimes = 0;
};
el.addEventListener('click', e => {
incrementClick();
setTimeout(() => {
if (clickedTimes === 1) {
click(e);
} else if (clickedTimes >= 2) {
dblClick(e);
}
reset();
}, 300);
});
}
Here's a solution where each 'click counter' is specific to each element, so onclick functions outside the element will not be effected...
const singleOrDouble = ({target}) => {
if (isNaN(target.cn)) {
target.cn = 1
} else {
target.cn++
}
setTimeout(() => {
if (target.cn == 1) {
console.log('once')
target.cn = 0
}
if (target.cn > 1) {
console.log('twice')
target.cn = 0
}
}, 500)
}
<p onclick="singleOrDouble(event)">Click me</p>
If you dont want to execute the single click at all in case of double, you can use a timeout like you did. You just have to reset the counter and the timeout properly. You do not reset el.cdblc on your last empty else.
Be aware, that this delays normal clicks.
/* dblclick differ click
takes two functions as param and one element
to bind the event listener on
*/
function cdblclick(click, dblclick, el){
//REM: Storing the values in an object instead of own element properties
let tObject = {
Clicks: 0,
onClick: click,
onDblClick: dblclick
};
//el.cooled = true;
el.addEventListener('click', function(object){
object.Clicks += 1;
//REM: Starting the click..
if(object.Clicks === 1){
object.Timeout = window.setTimeout(function(){
//REM: Execute click if not stopped
if(typeof object.onClick == 'function'){
object.onClick()
};
//REM: Resetting the click count
object.Clicks = 0
/*if(!el.cdblc){el.cdblc = 0}
el.cdblc++;
if(el.cdblc === 1){
setTimeout(function(){
if(!el.doubled){
console.log('click')
// click();
el.cdblc = 0;
el.cooled = true;
el.doubled = false;
}
*/
}.bind(this, object), 300)
}
//REM: Unless we have triple clicks, there is only double left
else{
//REM: Cancel the single click
window.clearTimeout(object.Timeout);
//REM: Execute double click
if(typeof object.onDblClick === 'function'){
object.onDblClick()
};
//REM: Resetting the click count
object.Clicks = 0
/*
console.log('double')
// dblclick();
el.doubled = true;
el.cdblc = 0;
el.cooled = true;
*/
}
}.bind(el, tObject))
};
document.querySelector('b').onclick = cdblclick(
function(){console.log('onclick')},
function(){console.log('ondblclick')},
document.body
);
<b>Click me</b>
Like this will work.
function cDblClick(click, dblClick, el) {
let clickedTimes = 0;
const incrementClick = () => {
clickedTimes++;
};
const reset = () => {
clickedTimes = 0;
};
el.addEventListener('click', () => {
incrementClick();
setTimeout(() => {
if (clickedTimes === 1) {
click();
} else if (clickedTimes === 2) {
dblClick();
}
reset();
}, 300);
});
}
you can try ondblclick js listner like this :
document.getElementById('click').onclick = function() { console.log("click"); }
document.getElementById('dblclick').ondblclick = function() { console.log("double click"); }
<div>
<button id="click"> click </button>
<button id="dblclick"> double click </button>
</div>
You can try this way to differ click and dbclick:
document.getElementById('click').onclick = function() {
//do something if click
}
document.getElementById('click').ondblclick = function() {
//do something if dbclick
}
<div>
<button id="click"> click or dbclick? </button>
</div>

Propagation issue with jQuery button

I have created a javascript / jquery simple game actioned by two buttons.
Button 1: "Play". The game is played ten times, and increments using a variable that I store in local storage. If the increment matches a random number between one and 10, then console.log("match!"), otherwise console,log("no match");
Button 2: "Restart the game". Once the increment is bigger than 10, then the game starts over by clicking the button.
The problem is, if you look into the console, that the second time you play the game, the game jumps by two increments at a time. The third time, by three increments... Why is that? There is a propagation issue here. How do I solve it?
Jsfiddle is here. Code I paste below, as it's very small:
start_game_over()
function start_game_over(event) {
$("#button1").show();
$("#button2").hide();
localStorage.setItem("progress", 0)
$("#button1").on("click", function() {
if (parseInt(localStorage.getItem("progress")) < 11) {
var random_number = Math.floor(Math.random() * (10 - 0) + 0);
console.log(parseInt(localStorage.getItem("progress")));
if (parseInt(localStorage.getItem("progress")) === random_number) {
console.log("match!")
} else {
console.log("no match")
}
localStorage.setItem("progress", parseInt(localStorage.getItem("progress")) + 1);
} else {
$("#button1").hide();
$("#button2").show();
$("#button2").on("click", function() {
start_game_over();
});
}
})
}
When you start_game_over you assign an event listener to the button click, but you never remove it, so when you call the function again it attaches a new one. restructuring the code a bit to handle the clicks outside of that function would be a good idea.
function start_game_over(event) {
$("#button1").show();
$("#button2").hide();
localStorage.setItem("progress", 0)
}
$("#button1").on("click", function() {
if (parseInt(localStorage.getItem("progress")) < 11) {
var random_number = Math.floor(Math.random() * (10 - 0) + 0);
console.log(parseInt(localStorage.getItem("progress")));
if (parseInt(localStorage.getItem("progress")) === random_number) {
console.log("match!")
} else {
console.log("no match")
}
localStorage.setItem("progress", parseInt(localStorage.getItem("progress")) + 1);
} else {
$("#button1").hide();
$("#button2").show();
}
})
$("#button2").on("click", function() {
start_game_over();
});
You are declaring your event listeners inside a function, so every time the function is called, you are creating a new listener. Put them out of the function and the problem is fixed.
You have to clear your $('#button1') event at the end by using $('#button1').off('click');. This will clear the event listener you create every time in your function.
SE doesn't allow localStorage so run this on JSFiddle or local machine.
start_game_over()
function start_game_over(event) {
$("#button1").show();
$("#button2").hide();
localStorage.setItem("progress", 0)
$("#button1").on("click", function() {
if (parseInt(localStorage.getItem("progress")) < 11) {
var random_number = Math.floor(Math.random() * (10 - 0) + 0);
console.log(parseInt(localStorage.getItem("progress")));
if (parseInt(localStorage.getItem("progress")) === random_number) {
console.log("match!")
} else {
console.log("no match")
}
localStorage.setItem("progress", parseInt(localStorage.getItem("progress")) + 1);
} else {
$("#button1").hide();
$("#button2").show();
$("#button2").on("click", function() {
$("#button1").off("click");
$("#button2").off("click");
start_game_over();
});
}
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button1">Play</button>
<button style="display:none" id="button2">Restart the Game</button>
The problem is that each time you invoke start_game_over you are adding additional click handlers to #button1 and #button2. What you want to do is set up the click handlers once and use a function to reset your game state when #button2 is clicked (or just reset the game state in #button2's callback). For example:
var $button1 = $('#button1');
var $button2 = $('#button2');
var start_game_over = function () {
$button1.show();
$button2.hide();
localStorage.setItem('progress', 0)
};
$button1.on('click', function () {
var progress = parseInt(localStorage.getItem('progress'), 10 /*always include radix!*/);
if (progress < 11) {
//... game logic here
} else {
$button1.hide();
$button2.show();
}
});
$button2.on('click', function () {
start_game_over();
});

Reset my click function

I have the following click function. I'm looking for a way so that when it is compleated, it will reset, and is ready to run again. How should i do that?
$('body').on('click', '#ConfirmBet', function () {
function randomImg() {
var imgs = $('.CoinImages');
var randomOne = Math.floor(imgs.length * Math.random());
$('#winner').fadeIn().attr('src', $(imgs[randomOne]).attr('src'));
$('#winner').addClass("WinImage");
if ($('#winner').attr('src') === $('.selected').attr('src')) {
alert('You Win!');
} else {
alert('You Lose!');
}
}
var counter = 5;
var c = setInterval(function () {
if (counter > 0) {
counter--;
$('#counter').html(counter);
$("#BetInput").val("");
$("#BetInput").prop("readonly", false);
$("#tCoin").removeClass("selected");
$("#ctCoin").removeClass("selected");
$(".CustomTextT").html("");
$(".CustomTextCT").html("");
$("#winner").removeClass("hidden");
} else {
clearInterval(c);
randomImg();
}
}, 1000);
});
Codepen
This codepen show's what my script does, but as you see, it keeps saying lose. no matter what image you hit.
In your setInterval handler function, you are removing the selected class in the counter > 0 case. Then in randomImg you are looking for an element with the selected class to determine which image was selected. Since you already removed the class, the check always fails.
I think you want to redo your setInterval handler logic like this:
if (counter > 0) {
counter--;
$('#counter').html(counter);
} else {
clearInterval(c);
randomImg();
$("#BetInput").val("");
$("#BetInput").prop("readonly", false);
$("#tCoin").removeClass("selected");
$("#ctCoin").removeClass("selected");
$(".CustomTextT").html("");
$(".CustomTextCT").html("");
$("#winner").removeClass("hidden");
}

Autostart jQuery slider

I'm using a script that animates on click left or right to the next div. It currently works fine but I'm looking to add two features to it. I need it to repeat back to the first slide if it is clicked passed the last slide and go to the last slide if click back from the first slide. Also, I'm interested in getting this to autostart on page load.
I've tried wrapping the clicks in a function and setting a setTimeout but it didn't seem to work. The animation is currently using CSS.
Here's the current JS:
<script>
jQuery(document).ready(function() {
var boxes = jQuery(".box").get(),
current = 0;
jQuery('.right').click(function () {
if (current == (-boxes.length + 1)){
} else {
current--;
updateBoxes();
}
console.log(-boxes.length + 1);
console.log(current);
});
jQuery('.left').click(function () {
if (current === 0){
} else{
current++;
updateBoxes();
}
});
function updateBoxes() {
for (var i = current; i < (boxes.length + current); i++) {
boxes[i - current].style.left = (i * 100 + 50) + "%";
}
}
});
</script>
Let me know if I need a jsfiddle for a better representation. So far, I think the code is pretty straightforward to animate on click.
Thanks.
Try
jQuery(document).ready(function () {
var boxes = jQuery(".box").get(),
current = 0,
timer;
jQuery('.right').click(function () {
if (current == (-boxes.length + 1)) {
current = 0;
} else {
current--;
}
updateBoxes();
}).click(); //initialize the view
jQuery('.left').click(function () {
if (current === 0) {
current = -boxes.length + 1;
} else {
current++;
}
updateBoxes();
});
function updateBoxes() {
//custom implementation for testing
console.log('show', current)
$(boxes).hide().eq(-current).show();
autoPlay();
}
function autoPlay() {
clearTimeout(timer);
//auto play
timer = setTimeout(function () {
jQuery('.right').click();
}, 2500)
}
});
Demo: Fiddle
Here's an example based on my comment (mostly pseudocode):
$(function(){
var boxes = $('.box'),
current = 0,
timer;
// Handler responsible for animation, either from clicking or Interval
function animation(direction){
if (direction === 1) {
// Set animation properties to animate forward
} else {
// Set animation properties to animate backwards
}
if (current === 0 || current === boxes.length) {
// Adjust for first/last
}
// Handle animation here
}
// Sets/Clears interval
// Useful if you want to reset the timer when a user clicks forward/back (or "pause")
function setAutoSlider(set, duration) {
var dur = duration || 2000;
if (set === 1) {
timer = setInterval(function(){
animation(1);
}, dur);
} else {
clearInterval(timer)
}
}
// Bind click events on arrows
// We use jQuery's event binding to pass the data 0 or 1 to our handler
$('.right').on('click', 1, function(e){animation(e.data)});
$('.left').on('click', 0, function(e){animation(e.data)});
// Kick off animated slider
setAutoSlider(1, 2000);
Have fun! If you have any questions, feel free to ask!

JQuery - bind() again when count is reset

In my game I want to make sure the start button is only clicked once each time it appears to stop it loading the function more than once.
I have written some code that counts the clicks and unbinds if the count is greater than zero.
var oneClick = 0;
$(".start-btn-wrapper").bind("click", function () {
oneClick++;
if (oneClick > 0) {
$(this).unbind("click");
}
newGame();
});
This works fine but I need a way to bind it again ready for the next time it appears (When the restart-btn is clicked) so I have written this to reset the count.
$(".restart-btn").click(function () {
resetGame();
oneClick = 0;
});
For some reason this doesn't do the job and I am looking to SO for a soloution
You're not binding again but just changing oneClick, which isn't even tested as the event handler to $(".start-btn-wrapper") isn't binded anymore.
But instead of unbinding/rebinding, which is costly, why not just test oneClick :
$(".start-btn-wrapper").bind("click", function () {
if (oneClick++ > 0) return;
newGame();
}
Note that if you just need two states, a boolean would be clearer :
var clickable = true;
$(".start-btn-wrapper").bind("click", function () {
if (!clickable) return;
newGame();
clickable = false;
}
$(".restart-btn").click(function () {
resetGame();
clickable = true;
});
jQuery has a built in method for exactly this use. It is .one()
So all you have to do is
$(".start-btn-wrapper").one('click',newGame);
and for the restart
$(".restart-btn").click(function () {
resetGame();
$(".start-btn-wrapper").one('click',newGame);
});
simple
var oneClick = 0;
$(".start-btn-wrapper").bind("click", function () {
if (oneClick > 0) {
return false;
}
oneClick++;
newGame();
});
$(".restart-btn").click(function () {
resetGame();
oneClick = 0;
});
var oneClick = 0;
function clickHandler() {
oneClick++;
if (oneClick > 0) {
$(".start-btn-wrapper").unbind("click");
}
newGame();
}
$(".start-btn-wrapper").bind("click", clickHandler);
$(".restart-btn").click(function () {
resetGame();
oneClick = 0;
$(".start-btn-wrapper").bind("click", clickHandler);
});

Categories