I have this variable (levelFormula) that contains a formula and then is updated via the output of another variable
var points = 100,
levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
In other words, if points gets updated then so does levelFormula. The question is, how do I detect when the value of levelFormula gets changed?
As mentioned in the comments,
var previousLevelFormula; // should be separated with below scope
...
var points = 100; // I guess it's from function parameter, because it will be changed so you need detection changes of levelFormula
var levelFormula = (Math.sqrt(2 * points + 255) - 5) / 10;
if (previousLevelFormula && previousLevelFormula != levelFormula) {
// it's changed
}
previousLevelFormula = levelFormula; // update previous value
Related
I am trying to write a simple program to find the greatest prime factor of an integer in JavaScript. The code I have written to do this follows:
let ans;
function factor(target, half) {
for (let i = 2; i < half; i++) {
if (target % i == 0) {
ans = target / i;
factor(ans, ans / 2);
}
}
}
factor(30, 15);
console.log(ans);
Now whether or not this code is an efficient solution to the problem or if it even works at all is beyond my issue with it: When I follow breakpoints set at each line of the factor function, I see that right after i = 2, target = 5, half = 2.5, and ans = 5, the value of target and half jump back up to 15 and 7.5 respectively. However, I do not see where in my code the values are told to change.
You're calling the function recursively, and each call to the function gets its own target, half, and i variables. In the first call to factor, target is 30 and half is 15. Then you call it again with the arguments 15 and 7.5; that inner call to factor gets its own target (15) and half (7.5), but the outer call still has its copies (30) and (15). This continues when you call factor again recursively, creating a third set, etc. When you step out of the innermost call, its variables disappear and you see the ones that are for the call that called it.
It may be clearer with a simpler example:
function countdown(value, indent) {
var twice = value * 2;
console.log(indent + "[before] value = " + value + ", twice = " + twice);
if (value > 0) {
countdown(value - 1, indent + " ");
}
console.log(indent + "[after] value = " + value + ", twice = " + twice);
}
countdown(3, "");
.as-console-wrapper {
max-height: 100% !important;
}
The output of that is:
[before] value = 3, twice = 6
[before] value = 2, twice = 4
[before] value = 1, twice = 2
[before] value = 0, twice = 0
[after] value = 0, twice = 0
[after] value = 1, twice = 2
[after] value = 2, twice = 4
[after] value = 3, twice = 6
As you can see, the values for value and twice in the outer call aren't changed by making the inner call. Each call gets its own set of variables.
var currDice, totDice, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
totDice = totDice+complete,
complete = dice * currDice
return totDice;
};
The function moveIt returns NaN.
It should return multiple of 40 till six randomly and keep the previous value.
If I remove it returns Undefined.
I know it is a scope problem. Please help.
You are using complete before initialising it! you habe to swap your lines of code:
function moveIt(beforeTotal) {
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = (beforeTotal || 0)+complete;
return totDice;
};
var total = moveIt();
console.log(total);
total = moveIt(total);
console.log(total);
I try to point out how this method work.
You can call this function without an inital value. Then (beforeTotal || 0) is (undefined || 0) and will evaluate to 0, that's JS logic, and you get the result for one dice.
If you pass a value to this function it will be used to add complete to it. By passing 1000 and complete gets 120, you get 1120 out of it.
All other variables are only available in this function.
Initialy totDIce is undefined and when you add undefined to something, you get the value casted to NaN
function moveIt(){
//memoizing the mutable value as key of the function itself
moveIt.totDice = moveIt.totDice || 0;
// you might wanna wrap it with parseInt()/Math.floor()/Math.ceil()
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = totDice+complete;
return moveIt.totDice ;
};
var totDice; will have undefined and that's why you get NaN
Assign totDice = 0 on the first line...
Also move complete = dice * currDice line above because complete has no value yet
var currDice, totDice = 0, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
complete = dice * currDice,
totDice = totDice+complete
return totDice;
};
you can use the browser's integrated console.
In Chrome: Tools > Javascript Console. Or CTRL + SHIFT + J. There you can console.log from your code and watch it there, or you can use the Sources tab (at the top of the panel). Navigate to the file, click on it and you can put a breakpoint in the line you want by ckicking the line number.
In Firefox: Tools > development > Web console. Or CTRL + SHIFT + K. Yu can debug in a similar fashion like the aforementioned.
You can also use tools like Firebug. See https://getfirebug.com/wiki/index.php/Script_Debugging
I created a table using an 8x8 matrix for a game and i also put into the table prizes, and etc in random places but I am having an issue creating also random start position for the user that doesn't conflict with the objects that are already in the table.
For now I have:
function startPos(matrix) {
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
while (matrix[y][x] != undefined) {
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
return matrix[y][x];
};
return matrix[y][x];
};
but I get nothing. Sorry if the question seems trivial I am just starting Javascript and have looked everywhere for a relevant answer with no avail.
A few mistakes:
you must not return from within the loop, but have to check the condition to leave it
you need to use Math.floor instead of Math.round
you need to return the position, not the value of the field (which you just asserted to be undefined)
function startPos(matrix) {
var l = matrix.length; // assumes square matrix
do { // assumes at least one empty field
var x = Math.floor(Math.random() * l);
var y = Math.floor(Math.random() * l);
} while (matrix[y][x] != undefined);
return [y, x];
}
It looks like what you want to do is select a random position in the matrix, if it is undefined then return it, otherwise select a new random position and try again. You need to make a few changes for this.
First - the return statement in your loop is unnecessary and is causing your function to be returned on the first run of the loop, stopping it from doing its job.
Second - In most cases, you should use === and !== instead of == and !=. You can find a detailed explanation here - Which equals operator (== vs ===) should be used in JavaScript comparisons?
Third - When you want to check if a variable is undefined, while myVar === undefined should work most of the time, there a situations where it could fail. best practice is to use typeof myVar === 'undefined'. More info here - https://stackoverflow.com/a/15093969/7739148
try this:
function startPos(matrix){
// first select a random position
var x = Math.round(Math.random() * matrix.length);
var y = Math.round(Math.random() * matrix.length);
// if the position is not empty, select a new one.
// continue like this until an empty spot is found.
while(typeof matrix[y][x] !== 'undefined'){
x = Math.round(Math.random() * matrix.length);
y = Math.round(Math.random() * matrix.length);
};
// once we have an empty position, return it
return matrix[y][x];
};
Caution - if there are no positions that are undefined the loop will never end, so you should either make sure your matrix will have at least one empty spot, or perform a check at the start of your function.
I found the following script to do a blur image processing to an image since javascript. I replicated the sample but I didn't understand how a little part of this script could work fine, I will show the script:
var gaussianBlur = function() {
var data = ctx.getImageData(0,0,canvas.width,canvas.height);
var px = data.data;
var tmpPx = new Uint8ClampedArray(px.length);
tmpPx.set(px);
for (var i = 0, len= px.length; i < len; i++) {
if (i % 4 === 3) {continue;}
px[i] = ( tmpPx[i]
+ (tmpPx[i - 4] || tmpPx[i])
+ (tmpPx[i + 4] || tmpPx[i])
+ (tmpPx[i - 4 * data.width] || tmpPx[i])
+ (tmpPx[i + 4 * data.width] || tmpPx[i])
+ (tmpPx[i - 4 * data.width - 4] || tmpPx[i])
+ (tmpPx[i + 4 * data.width + 4] || tmpPx[i])
+ (tmpPx[i + 4 * data.width - 4] || tmpPx[i])
+ (tmpPx[i - 4 * data.width + 4] || tmpPx[i])
)/9;
};
// data.data = px;
ctx.putImageData(data,0,0);
delete tmpPx;
btnBlur.removeAttribute('disabled');
btnBlur.textContent = 'Blur'; }
This function (gaussianBlur()) is triggered to a html button, so when it's clicked, it will process the image to get it blurred and this process will be repeated according to the number of clicks on the button. The part of the code I don't understand is when it finishes the for loop, all the math operations were saved on the px variable but in the next line code ctx.putImageData(data,0,0);, this data variable doesn't take the new changed variable px. So I wonder, how is it possible that the canvas could render with the image blurred if data variable wasn't changed its data component (because data.data = px as shown in the first lines of gaussianBlur function).
In my opinion, to understand this code, I would put a data.data = px; after the for loop, with this line code I am saying that the new px will be set on data.data variable. And with ot without this line code the algorithm works. So I am confused why it works despite data.data is not set by the new px value. Please help me to understand it.
Thanks in advance
What is happening, is that px is in reality the same object as data.data, meaning that every changes in px take effect in the object you would think is just a copy.
Look at this simple example:
// We create an object 'x' with an array of data
var x = {
data :[ 0, 1]
};
// Assign x.data value to 'p'
var p = x.data;
console.log(p); // [0, 1]
// Then we change one of the array's values to 'Xpto'
p[1] = "Xpto";
// Now look what happened to x.data
console.log(x.data); // [0, "Xpto"]
This is why your code isn't working. px is not a copy, it is a reference.
If I have an array of buttons, how can I tell which button was clicked?
example below
var i=0
CreateButton = new function () {
savebutton[i]=NewButton()
i++
}
every time a user runs the function a new button is generated.
the first button is savebutton[0] the second is savebutton[1] and so on potentially infinity times.
when later the user presses the button I want the screen to alert it's index number (or 'i').
is there any way to make this work in arrays?
this : savebutton[i].click(alert(this))
and this: savebutton[i].onClick(alert(this))
do not work
the code is entirely written in RephaelJs and contains absolutely no DOM elements.
I use RaphaelJS and my HTML document contains no DOM elements. everything is scripted.
the entire function that generates the buttons:
var insertframe = function () {
ww = WindowWidth
mw = mywindoww
zx = zone.getBBox().x
zy = zone.getBBox().y
zw = zone.getBBox().width
zh = zone.getBBox().height
sh = screen.getBBox().height
sw = screen.getBBox().width
py = picy
px = picx
srw = screenratiow
srh = screenratioh
savebutton[i] = paper.image(imageurl)
savebutton[i].attr(
{
'width': px * (framewidth * miniframesize) / zw,
'height': py * (frameheight * miniframesize) / zh,
'x': ((srw*520) + (i * 120) * srw) - zx * (frameheight * miniframesize) / zh,
'y': srh*600 - zy * (framewidth * miniframesize) / zw,
'clip-rect': (srw*520) + (i * 120) * srw + "," + srh * 600 + "," + framewidth * miniframesize + ',' + frameheight * miniframesize
})
savebutton[i].click(alert(this))
i++
}
When you create the button, you can assign its index from the array as an attribute of the button and then when it's clicked on, you can examine that attribute of the clicked on button to see where it is positioned in the array.
If you don't want to do that, you can also search the array and find where the current button is in the array.
You can use a 2d array with each element having an ID and an identifier. Can't say too much more without seeing your code.
I think JQuery might help you achieve that way easier. Check out this:
http://api.jquery.com/index/
Hope this helps!