Javascript array not looping back to beginning - javascript

I'm writing a simple card game, but for some reason this code below behaves very strangely...The turn functions is first called using theTurn(0)
players is an array of objects with player name and hand etc.
function theTurn(playerNumber) {
if(play == 1) {
$('#player').text(players[playerNumber].Name);
$('#submit').click(function() {
nextPlayer(playerNumber);
})
}
}
function nextPlayer(playerNumber) {
if(playerNumber == players.length - 1) {
theTurn(0);
} else {
theTurn(playerNumber + 1);
}
}
For some reason I get player 0 then 1 then 1 again and then 0.
I've left out some of the stuff in theTurn...but this is the gist of it and the problem shows up in this simplified version too.
Any help with my faulty logic would be greatly appreciated.

This actually makes a little more sense... just add the click handler once, then set the player number as a data property so the nextPlayer function knows what it is without an argument.
$('#player').data('activePlayer', 0);
$('#submit').click(function() {
nextPlayer();
});
function theTurn(playerNumber) {
if(play == 1) {
$('#player').text(players[playerNumber].Name);
$('#player').data('activePlayer', playerNumber);
}
}
function nextPlayer() {
var playerNumber = $('#player').data('activePlayer');
if(playerNumber == players.length - 1) {
theTurn(0);
} else {
theTurn(playerNumber + 1);
}
}

Related

How can I set timers in slideshow to show as selected?

I have to create a slideshow, using an array of images and have that set on a timer. There is a drop-down menu with slow, medium, and fast options and the pictures need to transition with accordance to the drop down option selected. Whenever I execute this code in a web browser the code repeats itself, while doubling, as I read the value of i in the console.
I have tried using a while and a do-while loop to have the images on a rotation.
I have also tried putting the if-statements outside and below/above the function.
<script>
var i = 0;
function changeImg(){
if (x == 'slow'){
setInterval("changeImg()", 5000);
} else if (x == 'medium'){
setInterval("changeImg()", 3000);
} else if (x == 'fast') {
setInterval("changeImg()", 1000);
} else {}
while (i < 3){
console.log(i);
document.slide.src = sportsArray[i];
i++;
}
console.log(i);
console.log(sportsArray);
}
</sctipt>
First, I would read up on MDN's docs on setInterval() and clearInterval to fill in the knowledge gaps that lead you to approach the problem this way.
You are recursively calling changeImg() in your code which I believe is causing the issue you describe as:
the code repeats itself, while doubling, as I read the value of i in the console
Also, your while loop will run immediately when calling changeImg() which also does not appear to be desired in this situation.
setInterval() mimics a while loop by nature. There is no need for a while loop in this code. Below is a solution that I hope you can use as a reference. I separated the code to determine the interval into a function the getIntervalSpeed.
function changeImg(x) {
var getIntervalSpeed = function(x) {
if (x === 'slow') {
return 5000;
} else if (x === 'medium') {
return 3000;
} else if (x === 'fast') {
return 1000;
} else {
return 3000;
// return a default interval if x is not defined
}
};
var i = 0;
var slideShow = setInterval(function() {
if (i >= sportsArray.length) {
i = 0; // reset index
}
document.slide.src = sportsArray[i]; // set the slide.src to the current index
i++; // increment index
}, getIntervalSpeed(x));
// on click of ANY button on the page, stop the slideshow
document.querySelector('button').addEventListener('click', function() {
clearInterval(slideShow);
});
}

Javascript Click Event Pushing Multiple Duplicates to Array

In recreating the Simon game, I am trying to push a click event to an array and then immediately test that Array in a nested function. On the first pass it seems to work.
However, on the third run the array does not seem to clear.
The screen shot below also shows that each input is printed multiple times to the console.
Full code pen here - https://codepen.io/jhc1982/pen/NwQZRw?editors=1010
Quick example:
function userMoves() {
var userInput = [];
document.getElementById("red").addEventListener("click", function(){
userInput.push("red");
testington();
});
$(".red").mousedown(function(event){
redAudio.play();
$(".red").css("background-color", "red");
});
$(".red").mouseup(function(){
$(".red").css("background-color", "#990000");
});
function testington(){
if (userInput.length == pattern.length) {
for (var i = 0; i < userInput.length; i++) {
if (userInput[i] !== pattern[i]) {
alert("Game Over");
} else if (i === userInput.length -1 && userInput[i] === pattern[i]) {
userInput = emptyArr;
simonMoves();
console.log("user input is ",userInput);
} else {
continue;
}
}
}
}
}
I am sure it is something really obvious but have been stuck for hours.
I think the problem may be that you are assigning the click events every time the userMoves execute. That means every time the function is called the event is added to the elements, so after two calls to userMoves() when you click on red the event is executed twice, after three calls it is executed three times, etc.
The code that adds the event listener should be out of the userMoves function. The testington function should also be out of userMoves, which would get much simpler:
function userMoves() {
$("#score-text").text(level);
userInput = [];
}
Here's a Pen with working code: https://codepen.io/anon/pen/ppzqyY
You need to add the break; keyword to after alert("Game over");
function testington(){
if (userInput.length == pattern.length) {
for (var i = 0; i < userInput.length; i++) {
if (userInput[i] !== pattern[i]) {
alert("Game Over");
break; // Break the loop
} else if (i === userInput.length -1 && userInput[i] === pattern[i]) {
userInput = emptyArr;
simonMoves();
console.log("user input is ",userInput);
} else {
continue;
}
}
}
}

Cannot call a nested function

As the question says, I can't call a nested function!
Here's the JavaScript:
var n;
var i = 0;
$("#men").click(function(){
$("#reshead").slideToggle("300");
});
$("#nxt").click(function() {
pic(i+=n);
});
$(window).on("scroll", function() {
if($(window).scrollTop() > 50) {
$("#header").addClass("scroll");
} else {
$("#header").removeClass("scroll");
}
});
function pic(n) {
if(n=1){
dx1();
} else if (n==2) {
dx2();
} else if (n=3){
dx3();
} else{
n=0;
}
}
function dx1() {
document.getElementById("picb").style.backgroundImage='url("src/black-belt.png")';
}
function dx2() {
document.getElementById("picb").style.cssText+='background-image:url(src/kut.png);background-repeat:no-repeat; width:auto;height:auto;';
}
function dx3() {
document.getElementById("picb").style.cssText+='background-image:url(src/slmb.jpg);background-repeat:no-repeat; width:auto;height:auto;';
}
I tried everything possible. Nothing happens. The code is for a slideshow in which the background image alone changes.
I first tried it in jQuery but it didn't happen. So I tried in plain JavaScript and it still doesn't work.
if(n=1)
and
else if(n=3)
are assingments and not comparison operators...
You are assigning a value to n so it's always entering to the first if. Try using == operator:
function pic(n) {
if(n==1){
dx1();
}
else if(n==2){
dx2();
}
else if(n==3){
dx3();
}
else{
n=0;
}
}
Be aware that even with the syntax fixes, you will still run into a problem trying to add undefined to 0.
pic(i+=n);
where the first time it is called i equals 0 and n equals undefined. Afterwards, i will equal NaN and n will equal 0.

Right way to execute all if-bodies on the first method call

I use JavaScript to display a binary clock on a website. When the site is first loaded, the clock needs to be set to the right time and then updated.
What is the right way to get this behaviour? Right now I have a var that is checked on every update and is set to false after the first run.
Would it be better to copy the function, remove the conditions and have it call the other function?
This is the function:
time.firstRun = true;
function updateBinaryClock() {
var now = moment().toObject();
var bin;
if (time.showClockWithSeconds) {
bin = toSixBit(now.seconds.toString(2));
setColor(".binSec", bin);
}
if (now.seconds == 0 || time.firstRun) {
bin = toSixBit(now.minutes.toString(2));
setColor(".binMin", bin);
}
if (now.minutes == 0 || time.firstRun) {
bin = toSixBit(now.hours.toString(2));
setColor(".binHour", bin);
}
if (time.firstRun) {
time.firstRun = false;
}
setTimeout(updateBinaryClock, 0.1 * 1000);
}
Your function will saturate your ram soon, because you forgot to clear timeout on every function execution.
You could use setInterval instead of setTimeout:
function updateBinaryClock() {
aux_updateBinaryClock(true);
setInterval(aux_updateBinaryClock, 100); // 0.1*1000
}
function aux_updateBinaryClock(isFirstRun) {
var now = moment().toObject(),
bin;
if (time.showClockWithSeconds) {
bin = toSixBit(now.seconds.toString(2));
setColor(".binSec", bin);
}
if (now.seconds === 0 || isFirstRun) {
bin = toSixBit(now.minutes.toString(2));
setColor(".binMin", bin);
}
if (now.minutes === 0 || isFirstRun) {
bin = toSixBit(now.hours.toString(2));
setColor(".binHour", bin);
}
}
updateBinaryClock();
Also note that setInterval and setTimeout are inaccurate, there are many more accurate implementations of setInterval and setTimeout (es. this or this)
What I would do is separate it into 2 functions.
function initBinaryClock() {
}
function updateBinaryClock() {
requestAnimationFrame(updateBinaryClock);
}
window.addEventListener("load", function loader(){
window.removeEventListener("load", loader, false);
initBinaryClock();
updateBinaryClock();
}, false);

Have function to show subsets of a string - now trying to adapt code to handle arrays

Some working code is on the bottom. But my poorly adapted code on the top goes into an infinite recursion loop.
What is it I do not know about arrays?
function recSubsets(soFar, rest)
{
if (rest===[]) console.log(soFar);
else
{
recSubsets(soFar.push(rest[0])), rest.slice(1));
recSubsets(soFar, rest.slice(1));
}
}
function listSubsets(s)
{
recSubsets([],s);
}
listSubsets([4,9,3,77])
below is the working version for strings
function recSubsets(soFar, rest)
{
if (rest==="") console.log(soFar);
else
{
recSubsets(soFar+rest[0], rest.substring(1));
recSubsets(soFar, rest.substring(1));
}
}
function listSubsets(s)
{
recSubsets("",s);
}
listSubsets("cat")
gives me:
cat
ca
ct
c
at
a
t
I found two problems -
push does not return an array(returns the new length of the array)
your stopping condition did not work. checking length === 0 instead works.
function recSubsets(soFar, rest)
{
if (rest.length===0) console.log(soFar);
else
{
var newSoFar = soFar.slice();
newSoFar.push(rest[0]);
recSubsets(newSoFar, rest.slice(1));
recSubsets(soFar, rest.slice(1));
}
}
function listSubsets(s)
{
recSubsets([],s);
}
listSubsets([4,9,3,77])

Categories

Resources