Increment not working in matching game - javascript

I am trying to call the same function with incremented numberOfFaces, but it loading with previous value of 5 only. What am I doing wrong? All I am trying to do is repeat the function after I click on the last child of the leftside.
var numberOfFaces = 5;
function generateFaces() {
var theRightSide = document.getElementById("rightSide");
var theLeftSide = document.getElementById("leftSide");
var theBody = document.getElementsByTagName("body")[0];
while(numberOfFaces > 0) {
// CREATING IMG ELEMENTS AND APPENDING THEM TO THE LEFTSIDE DIV
var img = document.createElement("img");
img.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png" ;
img.style.top = Math.floor(Math.random() * 400) +"px";
img.style.left = Math.floor(Math.random() * 400) +"px";
theLeftSide.appendChild(img);
// CLONING THE LEFT SIDE DIV ELEMENTS, REMOVING THE LAST CHILD AND APPENDING THEM TO THE RIGHT CHILD
var leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
numberOfFaces--;
}
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
while (theLeftSide.firstChild) {
theLeftSide.removeChild(theLeftSide.firstChild);
}
while (theRightSide.firstChild) {
theRightSide.removeChild(theRightSide.firstChild);
}
numberOfFaces += 5;
generateFaces();
};
theBody.onclick = function gameOver(event) {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
}
}

Here:
numberOfFaces += 5;
generateFaces();
Your numberOfFaces value is 5 and you add 5 to it, so the result is 10. After that you call generateFaces, which will decrement numberOfFaces until it reaches 0, generating 10 faces and at next call will generate 5 faces according to the expectation. This happens inside theLeftSide.lastChild.onclick, so you expect your code to generate the faces and have numberOfFaces as 0 at the end when you click on that element. However, this click handler is defined inside generateFaces, which is never called, hence numberOfFaces is never changed. You need to refactor your code. Define your event handlers outside generateFaces and you should be ok after that.

Related

I have some JavaScript function that keeps repeating itself, I can't find why

This is code that generates a selected image when a function is run, but the image keeps changing, I want this code to let me have one image and keep it that way instead of it changing randomly every 0.5 - 3 seconds, and I don't know why!
const imageSelector = document.querySelector("#changeHeron")
function spinMachine() {
document.getElementById('spinner').disabled = 'disabled';
spinner.style.transform = "rotate(90deg)";
setInterval(enterBall, 1000)
var protmt = prompt("What's your name?")
alert("Hey there " + protmt + ", " + "its great to see you here")
}
function enterBall() {
var ball = document.getElementById("changeHeron");
ball.style.opacity = "100%";
ball.style.transform = "ScaleX(50%) ScaleY(50%)";
setInterval(liftBall, 1000);
}
function liftBall() {
var ball = document.getElementById("changeHeron");
ball.style.transform = "translateY(-250%)";
ball.style.transform = "ScaleX(200%) ScaleY(200%)";
ball.style.top = "40%";
setInterval(changeImage, 1500);
}
function changeImage() {
var images = ["./Images/Football.png", "./Images/Mousetache.png", "./Images/OG.svg"];
var randomNum = Math.floor(Math.random() * images.length);
var ball = document.getElementById("changeHeron");
ball.src = images[randomNum];
ball.style.borderRadius = "5%";
ball.style.backgroundColor = "white";
}
I found that you can place the images varible outside and change it inside when the code has ran so that the rest can just work outside of this problem

Javascript Closure functions

So I'm new to javascript and I am looking for a way to count how many times a function is executed. The code randomly generates a square or circle and displays from the shape is shown to when you click it (reactionTime). That works fine and dandy.
But I'm looking for a way to keep track of the number of times a shape is clicked and then eventually the cumulative time to calculate average time per click. If it helps, I come from a pretty good C++ background.
To count number of clicks, I was thinking of adding a closure function.
From here: How do I find out how many times a function is called with javascript/jquery?
myFunction = (function(){
var count = 0;
return function(){
count++
alert( "I have been called " + count + " times");
}
})();
And from here: Function count calls
var increment = function() {
var i = 0;
return function() { return i += 1; };
};
var ob = increment();
But I tried a global variable and several variations of closure functions to no avail (look for the comments). I tried putting the closure function in other functions. And I also tried something like:
var increment = makeBox();
I'm wondering if anyone can guide me in the right direction. It would be much appreciated!
var clickedTime; var createdTime; var reactionTime;
var clicked; var avg = 0;
avg = (avg + reactionTime) / clicked;
document.getElementById("clicked").innerHTML = clicked;
document.getElementById("avg").innerHTML = avg;
function getRandomColor() {
....
}
function makeBox() { // This is the long function that makes box
createdTime = Date.now();
var time = Math.random();
time = time * 3000;
///////// var increment = function () {
var i = 0;
//return function() { return i += 1; };
i++;
return i;
///////// };
// clicked++; /////////// global variable returns NaN
// console.log(clicked);
// alert("Clicked: "+clicked);
setTimeout(function() {
if (Math.random() > 0.5) {
document.getElementById("box").style.borderRadius="75px"; }
else {
document.getElementById("box").style.borderRadius="0px"; }
var top = Math.random(); top = top * 300;
var left = Math.random(); left = left * 500;
document.getElementById("box").style.top = top+"px";
document.getElementById("box").style.left = left+"px";
document.getElementById("box").style.backgroundColor = getRandomColor();
document.getElementById("box").style.display = "block";
createdTime = Date.now();
}, time);
}
ob = increment(); //////////////////////// I think this gives me 1 every time
alert("Increment: "+ob); //////////////////
document.getElementById("box").onclick = function() {
clickedTime = Date.now();
reactionTime= (clickedTime - createdTime)/1000;
document.getElementById("time").innerHTML = reactionTime;
this.style.display = "none";
makeBox();
}
makeBox();
You have a few problems but to answer your question:
You're not defining clicked as a number (or any other type) so trying to perform an operation on undefined returns NaN...because well, it's not a number.
Your second attempt var i = 0; won't work because i is re-defined on each function call.
You should be able to use your gobal variable clicked as long as you set it to zero.
Here is an example that shows how a closure can count calls to a function:
function add5(y) {
//A totally normal function
return y + 5;
}
var counter = 0, /*a counter scoped outside of the function counter function*/
trackedAdd5 = (function (func) {
/*This anonymous function is incrementing a counter and then calling the function it is passed*/
return function () {
counter++;
/*The trick is this function returns the output of calling the passed in function (not that it is applying it by passing in the arguments)*/
return func.apply(this, arguments);
}
})(add5); /*calling this tracking function by passing the function to track*/
document.getElementById('run').addEventListener('click', function () {
/*Here we are treating this new trackedAdd5 as a normal function*/
var y = document.getElementById('y');
y.value = trackedAdd5(parseInt(y.value, 10));
/*Except the outer counter variable now represents the number of times this function has been called*/
document.getElementById('counter').value = counter;
});
<label> <code>y = </code>
<input id='y' value='0' />
<button id='run'>add5</button>
</label>
<br/>
<label><code>add5()</code> was called
<input readonly id='counter' value='0' />times</label>
makeBox.click = 0; // define the function's counter outside the function
makeBox.click++; // replace the `i` usage with this inside the function
About ob = increment();: it is used erroneously (redefines ob many times);
var ob = increment(); // define it once
ob(); // increments the counter
// another way to define `increment`:
var increment = (function () {
var i = 0;
return function () {
return i += 1;
};
})();
ob = increment(); // ob becomes 1 initially
ob = increment(); // ob becomes 2, etc.

Modifying a simple jquery game

I am trying to modify this game, right now it shows 9 images at random positions and the user has to click on them and when it reaches 10 clicks the game ends. I want to appear only one image. I will share the original function and the function I have modified it.
Original
function createImages(){
var myarray= ["img/img1.gif","img/img2.gif","img/img3.png",
"img/img4.gif","img/img5.gif","img/img6.gif",
"img/img7.gif","img/img8.png", "img/img9.jpg"];
var count=0;
var div;
for (var i = 0; i < 9; i++) {
var randPos = 0 + Math.floor(Math.random() * 500);
this.img = document.createElement("img");
div = document.createElement("div");
$("div").attr("id","div"+i);
var randNew = 0 + Math.floor(Math.random() * (5));
var rand = 0 + Math.floor(Math.random() * (9-count));
this.img.src = myarray[rand];
$('#div'+i).css("left", randPosition());
$('#div'+i).css("right", randPosition());
$('#div'+i).css("top", randPosition());
$('#div'+i).css("bottom",randPosition());
$('#div'+i).css("position","relative");
$('#div'+i).show();
div.appendChild(this.img);
$("body").prepend(div);
myarray.splice(rand,1);
count++;
}
}
After I modified it
function createImages(){
var count=0;
var div;
for (var i = 0; i < 9; i++) {
var randPos = 0 + Math.floor(Math.random() * 500);
this.img = document.createElement("img");
div = document.createElement("div");
$("div").attr("id","div");
var randNew = 0 + Math.floor(Math.random() * (5));
var rand = 0 + Math.floor(Math.random() * (9-count));
this.img.src = "img/img1.gif";
$('#div').css("left", randPosition());
$('#div').css("right", randPosition());
$('#div').css("top", randPosition());
$('#div').css("bottom",randPosition());
$('#div').css("position","relative");
$('#div').show();
div.appendChild(this.img);
$("body").prepend(div);
count++;
}
}
The problem is that now it appears the same image 10 times, I want it to appear only once and then disappear and appear again. Can anyone help me fix this issue.
If it's not to much to ask I would like to put this image inside a div so it wouldn't appear all over the page.
function randPosition() {
return 0 + Math.floor(Math.random() * 500);
}
In createImages() function you have a loop that adds the image 10 times:
for (var i = 0; i < 9; i++) {
...
}
Remove it, and it'll do it only once. Also you can simplify the code removing some random variables that are not used.
Further, this two sentences aren't correct. The first one creates a div in a variable named also div. The second is selector for all div elements, you are not referencing the new created one as I think you expect.
div = document.createElement("div");
$("div").attr("id","div");
You should create a jQuery object with the new created div to work with it:
var div = document.createElement("div");
$div = $(div); // << Create jQuery object wrapping the new div
$div.css("left", randPosition());
Edited function:
function createImages(){
var div = document.createElement("div");
$div = $(div);
$div.css("left", randPosition());
$div.css("right", randPosition());
$div.css("top", randPosition());
$div.css("bottom",randPosition());
$div.css("position","relative");
$div.show();
var img = document.createElement("img");
img.src = "http://dummyimage.com/25x25/4F4/000.png";
div.appendChild(img);
$("body").prepend(div);
}
EDIT: I've built a JSFiddle for you so you can play with it: http://jsfiddle.net/6aLh9qam/3/

Javascript gradual width increase

I'm trying to gradually increase the elements of 2 id's in javascript using a Timeout. I can get one working but when trying to call another element into the same function it only does one iteration then crashes after the first recursive call.
I'm passing two id's for the elements. and I want the left element to gradually increase while the right element gradually increases in width.
Heres what ive got
function grow(elementL, elementR)
{
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
clearTimeout(loopTimer);
return false;
}
var loopTimer = setTimeout('grow(\''+elementL+','+elementR+'\')',50);
}
You could simplify this (removing the script-generation) by using setInterval -- this repeats the function call until you cancel it.
function grow(elementL, elementR)
{
var loopTimer = setInterval(function() {
if (!growStep(elementL, elementR)) {
clearInterval(loopTimer);
}
}, 50);
}
function growStep(elementL, elementR) {
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
return false;
}
return true;
}
(Fiddle)
Edit
Yeah, I guess the only problem with the OP code is that it passes a string to setTimeout, rather than the function itself:
var loopTimer = setTimeout(function() {
grow(elementL, elementR);
},50);
setTimeout('grow(\''+elementL+','+elementR+'\')',50)
would need to be
setTimeout('grow(\''+elementL+'\',\''+elementR+'\')',50)
// ^^ ^^
to work. But don't do that. Pass a function expression to setTimeout:
setTimeout(function() {
grow(elementL, elementR);
}, 50)

Why is it looping through the 'else' in my if/else statement?

If you enable the alert(rand) at the bottom of my if/else statement, you will notice that when ran, it will constantly loop over the else section of my if/else statement. It's probably a simple fix, but I can't seem to figure it out. I had it working in the earlier stages of development but can't seem to figure it out now.
I'll post the code below, but it's probably easier to look at my jsfiddle, here: http://jsfiddle.net/zAPsY/7/ Thanks.
$(document).ready(function(){
//You can edit the following file paths to change images in selection
var img1 = '<img src="images/luke.jpg">';
var img2 = '<img src="images/luke.jpg">';
var img3 = '<img src="images/luke.jpg">';
var img4 = '<img src="images/luke.jpg">';
var img5 = '<img src="images/luke.jpg">';
var img6 = '<img src="images/luke.jpg">';
var all = img1 + img2 + img3 + img4 + img5 + img6;
//Rotation
var speed = 0.00;
var radius = 80;
var count = 0;
$("#run").bind("click",runButtonClick);
function rotate()
{
var centerx = $(document).width()/2;
var centery = $(document).height()/2;
var num_items = $("#container > img").length;
$("#container > img").each(function(){
var angle = count * (Math.PI/180);
var newx = centerx + Math.cos(angle)*radius - $(this).width()/2;
var newy = centery + Math.sin(angle)*radius - $(this).height()/2;
$(this).css("left",newx+"px").css("top",newy+"px");
count += 360/num_items + speed;
});
}
setInterval(rotate,100/1000);
//Append elements to container
$("#appendall").click(function(){$('#container').append(all);});
$('#append').children().eq(2).click(function(){$('#container').append(img1);});
$('#append').children().eq(3).click(function(){$('#container').append(img2);});
$('#append').children().eq(4).click(function(){$('#container').append(img3);});
$('#append').children().eq(5).click(function(){$('#container').append(img4);});
$('#append').children().eq(6).click(function(){$('#container').append(img5);});
$('#append').children().eq(7).click(function(){$('#container').append(img6);});
//Refresh page
$("#reset").click(function(){location.reload();});
//IF speed is greater than 0 - ELSE add animation to div element
function runButtonClick() {
var maxcount = 0.40;
var incdec = 0.01;
setInterval(function(){counter();}, 100);
counter()
speed;
function counter()
{
if (maxcount >= 0.00)
{
maxcount = maxcount - incdec;
speed = speed + incdec;
//alert(speed)
//alert(maxcount)
}
else if (maxcount <= 0.00)
{
speed = 0.00;
//Find amount of div elements and add 1
var brewees = $('#container').children().length +=1;
//get a random number
var rand = (Math.floor(Math.random()*brewees));
var ap = '20px';
var ab = '#ddd';
var ad = 1000;
//match random number corrosponding child in div
$('#container').children().eq(parseFloat(rand))
.animate({padding: ap, background : ab}, {duration:ad});
alert(rand);
}
}
}
});
You let your maxcount drop below zero but still your function is being called every 100ms (due to your setInterval).
So you should clear that interval eventually by doing:
/* first */
var intervalID = setInterval(function(){counter();}, 100);
/* later */
clearInterval(intervalID);
You're calling the function at a rate of 10 times per second (setInterval). Eventually, the maxcount variable will drop below 0, causing the else condition to execute.
You should store the interval call in a variable, and use clearInterval at else, so that the function runs only once after else:
//Store a reference to the interval
var interval = setInterval(function(){counter();}, 100);
...
function counter(){
...
else if(..){
...
clearInterval(interval); //Clear the previously defined interval
}
...
Another note: In the code, speed; has no use. Either prefix it by var (var speed;), or remove it.

Categories

Resources