Simon Game in javascript - javascript

this is a javascript problem.
So this is what I did. I created 2 arrays. 1 for the computer and one for the player. In the computerTurn function The computer creates a random number and places it into an array. It will output the number from the array which will play a button. If the counter equals the length of the array then it will switch to the players turn. In the playerTurn function the player has 5 seconds to follow the buttons that the computer chose. The problem occurs after the second round when there are 2 random elements in the array. For some reason it doesn't clear my playerArray and just adds up numbers to it.
What am I doing wrong?
The project can be found here:
https://codepen.io/roger1891/full/vmYqwx/
I assume the problem lies here:
var playerTurn = function() {
if(currentPlayerTurn == "human" && onGoingGame == false) {
playerArray = [];
$(".my-btn").click(function(){
var $input = $(this);
var attrString = $input.attr("id");
//only get number from id attribute
var strNum = attrString.replace( /^\D+/g, '');
//convert theNumber from string to number
var theNum = parseInt(strNum);
playerArray.push(theNum);
console.log("this is the num the player picked " + theNum);
console.log(playerArray);
});
setTimeout(function () {
var is_same = playerArray.length == sequenceArray.length && playerArray.every(function(element, index) {
return element === sequenceArray[index];
});
is_same;
console.log(is_same);
if(is_same == true) {
onGoingGame = true;
currentPlayerTurn = "computer";
computerTurn();
}
}, 5000);
}
}
setTimeout(function () {
var is_same = playerArray.length == sequenceArray.length && playerArray.every(function(element, index) {
return element === sequenceArray[index];
});
is_same;
console.log(is_same);
if(is_same == true) {
onGoingGame = true;
currentPlayerTurn = "computer";
computerTurn();
}
}, 5000);
}
}

The main issue is that you should not define the click handler within a function that gets called several times (playerTurn), since that will accumulate the click handlers that will be executed at a single click. As a consequence there is a growing increase in the length of playerArray. Instead define the click handler outside that function, and repeat the condition in that click handler like you have in playerTurn:
$(".my-btn").click(function(){
if(currentPlayerTurn != "human" || onGoingGame) return; // exit
// rest of the click handler...
});
var playerTurn = function() {
if(currentPlayerTurn != "human" || onGoingGame) return; // exit
playerArray = [];
setTimeout(function () {
// etc....
}, 5000);
}
// ... etc
NB: The variable onGoingGame seems unnecessary, as it always corresponds to the expression currentPlayerTurn == "computer"

Related

World's most persistent bouncing

I used the same algorithm for an earlier part of the code, used a basic de-bouncer on the functions, and it worked, like so:
var lastClick = 0;
var delay = 20;
function l_mage_menu(){
if (lastClick >= (Date.now() - delay))
return;
lastClick = Date.now()
But for this it refuses to work and everything is running 3+ times, whether it's the alert window or the function being called. Cannot for the life of me figure out why.
document.addEventListener("DOMContentLoaded", (function(event) {
var buttons = document.querySelectorAll('.btn');//this acts like an array
if (buttons){
buttons.forEach(function getIndex(curVal2, LIndex2){ //current value and index in the list
curVal2.addEventListener('click', function() {
curVal2.classList.toggle("active2");
buttons.forEach(function(x, sL2){
if(LIndex2 !== sL2) { //if list index is NOT equal to the selected list element, aka one has already been picked
x.classList.remove('active2');
};
current_index2 = LIndex2;
switch(current_index2){
case(0): //basic attack.
console.log("test1") //from here, call the menus
break;
case(1): //this one is spells
//use listener to execute the matching spell
let btn1 = document.getElementById("btn_1");
btn1.addEventListener("click", function(){
if(btn1.innerHTML == "Supreme Altar"){
let ultima = document.getElementById('ultima_charge');
if (ultima.value != 100){
window.alert("Ultima not charged!");
}else{
SupremeAltar()
}
}
else if (btn1.innerHTML == "Radiant Supernova"){
let ultima = document.getElementById('ultima_charge');
if (ultima.value != 100){
window.alert("Ultima not charged!");
}else{
RadiantSupernova()
}
}else if (btn1.innerHTML == "Thousand Men"){
let ultima = document.getElementById('ultima_charge');
if (ultima.value != 100){
window.alert("Ultima not charged!");
}else{
ThousandMen()
};
};
})
};
});
});
});
};
}));

My tic tac toe game (jquery) is not working properly. Lost Part is not working properly

The 'Win' and 'Draw' parts are showing up on time, but the 'Lost' part doesn't show the message 'you lost'until I click on an empty cell once again. Please check out my code and help me find any errors.
Below is my code:
Marked is a class that changes the opacity of the clicked cell.
1,2,3...are the id's of respective cells in the table(html).
I tried delay() too instead of setTimeout(), but it didn't work as well.
$(document).ready(function() {
var timer;
var x = 0;
$("td").click(function() {
if($(this).text()=='') {
$(this).text("0").addClass("marked");
x = 1;
}
}).click(function() {
if(x==1) {
timer = setTimeout(function() {
var choose = $("td").not(".marked");
var random = choose[Math.floor(Math.random()*choose.length)];
$(random).text("X").addClass("marked");
},1000);
x=0;
showResult();
}
});
function showResult() {
var one = $("#1").text();
var two = $("#2").text();
var three = $("#3").text();
var four = $("#4").text();
var five = $("#5").text();
var six = $("#6").text();
var seven = $("#7").text();
var eight = $("#8").text();
var nine = $("#9").text();
if(one==two && two==three)
result(one)
else if (four==five && five==six)
result(four)
else if(seven==eight && eight==nine)
result(seven)
else if (one==four && four==seven)
result(one)
else if (two==five && five==eight)
result(two)
else if (three==six && six==nine)
result(three)
else if (one==five && five==nine)
result(one)
else if(three==five && five==seven)
result(three);
else {
var z = $("td").not(".marked");
if(z.length == 0) {
$("p").text("Draw!");
$("td").removeClass("marked");
$("td").text("");
$("#demo1").append('<img src="https://media.tenor.com/images/54c63f726505bfdb455eb4c29e626ad8/tenor.gif">');
clearTimeout(timer);
}
}
}
function result(y) {
var result = y;
if(result=="X"){
clearTimeout(timer);
$("p").text("You Lost!");
$("td").removeClass("marked");
$("td").text("");
$("#demo1").append('<img src="https://media.tenor.com/images/08902a85a6107684f8614846f4a54218/tenor.gif">');
}
if(result=="0") {
$("td").text("");
$("p").text("You Won!");
$("#demo1").append('<img src="https://i.gifer.com/4OuC.gif">');
$("td").removeClass("marked");
clearTimeout(timer);
}
}
});
You are calling showResult immeadiately when the user clicked, so it cant't recognize the X put into the table one second later.
Just do:
$("td").click(function() {
[...]
}).click(function() {
if (x == 1) {
timer = setTimeout(function() {
var choose = $("td").not(".marked");
var random = choose[Math.floor(Math.random() * choose.length)];
$(random).text("X").addClass("marked");
/******** ADD ANOTHER CHECK HERE ********/
showResult();
}, 1000);
x = 0;
showResult();
}
});
It might also be a good idea to add a return to showResult that returns false when a result was achieved. This way you could do something like
x = 0;
if (showResult()) {
timer = setTimeout(function() {
[...]
}
}
And the user can't get a loose message right after a win message.
Also: Why do you need the 2 click listeners? You can just use the if statement in the top one and then you don't need the (x == 1)

When passing an argument with AddEventListener() can't get requestAnimationFrame to work properly

Im trying to get an animation on mouseenter and stop animation on mouseleave, but I'm onlny getting one cycle instead of a full cycle on mouseenter. Must be doing something wrong.
https://jsfiddle.net/b6kezaku/7/ here is a fragment.
var arrowUpFirst = document.getElementsByClassName('turn_up_svg')[0]
var arrowUpTransform = window.getComputedStyle(arrowUpFirst, null).getPropertyValue('transform')
var arrowUpTransformScale = arrowUpTransform.split(',')
var arrowUpValue = typeof arrowUpTransformScale[2] === 'string'
console.log(arrowUpValue)
var arrowNumberUpValue = Number(arrowUpValue) * 100
console.log(typeof arrowNumberUpValue === 'number')
var a = 'start'
var c = 'stop'
var fullCycle = 100
function up_svg(b) {
if (a == b) {
requestAnimationFrame(up_svg)
}
if (c == b) {
cancelAnimationFrame(up_svg)
}
if (arrowNumberUpValue <= 100 && arrowNumberUpValue >= 50) {
fullCycle--
fullCycle <= 75 ? arrowNumberUpValue++ : arrowNumberUpValue--
//document.querySelectorAll('p')[1].textContent = arrowNumberUpValue
var trans = "scale(" + (arrowNumberUpValue / 100).toPrecision(2) + ") rotate(-90deg)"
//document.querySelectorAll('p')[3].textContent = (arrowNumberUpValue/100).toPrecision(2)
arrowUpFirst.style.transform = trans
if (fullCycle < 52) {
fullCycle = 100
arrowNumberUpValue = 100
//document.querySelectorAll('p')[2].textContent = arrowNumberUpValue
}
}
}
//FirstFace.onmouseenter = up_svg
FirstFace.addEventListener('mouseenter', function() {
up_svg('start')
}, false)
//FirstFace.addEventListener('mouseenter', up_svg,false)
//FirstFace.addEventListener('mouseleave', up_svg.bind(null,'stop'),false)
FirstFace.addEventListener('mouseleave', function() {
up_svg('stop')
}, false)
The problem I see is that when requestAnimationFrame invokes up_svg, it doesn't pass a value for b, so you don't trigger a second requestAnimationFrame.
Consider doing the following:
function loopAnimation() {
requestAnimationFame(loop)
// run animation
}
function startAnimation() {
// cancel to prevent duplication
cancelAnimationFrame(loopAnimation)
requestAnimationFame(loopAnimation)
}
function stopAnimation() {
cancelAnimationFrame(loopAnimation)
}
FirstFace.addEventListener('mouseenter', startAnimation,false)
FirstFace.addEventListener('mouseexit', stopAnimation,false)
In this case, up_svg gets split into three functions. One is dedicated to carrying out the animation and preserving it, while the other two can start or stop the loop.
It seems that when requestAnimationFrame(up_svg); runs the callback, it is passed a numerical value, so because b is neither 'start' or 'stop', it doesn't refresh again or ask again to requestAnimationFrame(up_svg);. Here is a little fix so that the function launches itself again:
in declarations:
var running = false;
in the function:
if(a == b){
running = true;
cancelAnimationFrame(up_svg); //just a precaution
}
if(c == b){
running = false;
cancelAnimationFrame(up_svg)
}else{
if(running){
requestAnimationFrame(up_svg);
}
}
fiddle: https://jsfiddle.net/b6kezaku/10/

jQuery not responding to timed events

Im having trouble getting my second function to react to the changes the first function brings.
var jumbotron = function(){
var jumbotronCounter = 1
var jumbotronSwitch = function(){
var jumbotronTimer = function(){
jumbotronCounter++
}
jumbotronTimer();
if (jumbotronCounter > 3){
jumbotronCounter = 1
}
console.log(jumbotronCounter);
}
setInterval(jumbotronSwitch,7000);
var jumbotronListener = function(){
if(jumbotronCounter = 1){
console.log('first');
}else if(jumbotronCounter = 2){
console.log('second');
}else if(jumbotronCounter = 3){
console.log('third');
}
};
jumbotronListener();
}
jumbotron();
Id like to use "jumbotronListener" to run some code when "jumbotronCounter" changes
jumbotronListener is indeed only running once. You can, instead, run it every time the interval runs:
var jumbotron = function () {
var jumbotronCounter = 1;
var jumbotronSwitch = function () {
var jumbotronTimer = function () {
jumbotronCounter++;
};
jumbotronTimer();
if (jumbotronCounter > 3) {
jumbotronCounter = 1;
}
// Execute the listener every time the interval runs
jumbotronListener();
console.log(jumbotronCounter);
};
setInterval(jumbotronSwitch, 7000);
// Run for the first time if you wish:
jumbotronListener();
// Set this as function so you can 'use it before declaring it'
function jumbotronListener() {
// You had invalid operators. = assigns and === compares (strictly)
if(jumbotronCounter === 1) {
console.log('first');
} else if(jumbotronCounter === 2) {
console.log('second');
} else if(jumbotronCounter === 3) {
console.log('third');
}
}
};
jumbotron();
You also had some missing semicolons in there, sometimes it's not a problem since JavaScript auto-inserts them, but sometimes it is, so it's a good idea to always make sure to manually insert them where they go.

unbind/turn off a function in jquery

Good day all, I'm trying to make a jquery game where a group of enemy will spawn after a group of enemy gets destroyed. I'm calling alien_cruiser() function & unbinding minion_roulette() function after minion_roulette_counter gets 0. But every time I run, function does not get unbind & after counter gets 0 both type of enemies show. I want to run them one by one. Here are the codes:
var sound = new Audio("sounds//dishoom.ogg");
var score = 0;
var minion_roulette_life = 10;
var cruiser_life = 20;
var minion_roulette_counter = 3;
var cruiser_counter = 3;
function processBullet() {
$(".projectile").each(function() {
var maxTop = $(this).offset().top;
var breakable1 = $(this).collision("#minion-roulette");
var breakable2 = $(this).collision("#cruiser");
$(this).css("top", maxTop - 25);
if (breakable1.length != 0 || breakable2.length != 0) {
$(this).remove();
}
if (maxTop <= 35) {
$(this).remove();
}
if (breakable1.length != 0) {
--minion_roulette_life;
if (minion_roulette_life == 0) {
sound.play();
breakable1.remove();
minion_roulette(true);
minion_roulette_counter--;
$("#score").html(++score);
minion_roulette_life = 10;
}
}
//This is the place where it checks if counter is 0 or not
if (minion_roulette_counter == 0) {
$('#content').unbind(function() {
minion_roulette(false)
});
alien_cruiser(false);
minion_roulette_counter = -1;
}
if (breakable2.length != 0) {
--cruiser_life;
if (cruiser_life == 0) {
sound.play();
breakable2.remove();
alien_cruiser(true);
$("#score").html(++score);
cruiser_life = 20;
}
}
});
}
Am I doing any wrong here? Please I need a solution badly. Tnx.
In this situation, you could use a conditional statement to determine which function to call.
For example:
if (minion_roulette_counter == 0) {
alien_cruiser();
}
else {
minion_roulette();
}
Binding and unbinding doesn't 'turn off' a function, unfortunately. To quote MDN:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
– MDN: 'Bind'

Categories

Resources