I have this function that causes the other functions to be skipped
I was just wondering what's wrong?
function sToLeftDiagonal(){
alert("sToLeftDiagonal");
var x, y;
var dCtr = 0;
var hLoop = varInit.maxRow;
for(var fifteen = 0; fifteen <= 3; fifteen++){
x = 0;
y = 5 - fifteen;
for(var xy = 0; xy <= hLoop ; xy++){
if (board[y][x] == player){
alert("plus");
dCtr++;
}else{
alert("negative");
dCtr = 0;
}
if (dCtr == varInit.cWins) {
dWinner(player);
}
x++;
y--;
}
hLoop--;
}
alert("end diagonal");
}
I've placed a lot of 'alert' to check whether they are executed or not, apparently
alert("end diagonal");
is not executed thus skips the next function in the main program
i know this is simple, i think i'm just overlooking some things..
thanks
i figured out what was causing the function to stop unexpectedly and not reach the last alert. it's because the values of [y] and [x] are wrong as i tried alerting every array index that the function goes through and variable y had an index of [-2] which wasn't suppose to be there.
Related
I’m trying to use an increment loop but I want it to increment at the end of the loop. Sadly, whenever I simply put the i++ at the end of the loop it doesn’t behave like I’d expect or want it to. Anyone mind showing me the proper way of doing it?
The referred increment loop:
for (i = 1; i < 15; i++) {
// do somthing here
}
Here is the loop I’m working with:
for (i = 1; i < 15; i++) {
for (x = 1; x < 15; x++) {
var take = document.getElementById("row" + i + "sm" + x);
Tesseract.recognize(take)
.then(function(result) {
console.log(result.text);
// rows[i][x] = result.text;
})
}
}
What I’d like it to do:
for (i = 1; i < 15) {
for (x = 1; x < 15) {
var take = document.getElementById("row" + i + "sm" + x);
Tesseract.recognize(take)
.then(function(result) {
console.log(result.text);
//rows[i][x] = result.text;
x += 1;
})
i += 1;
}
}
I am using the for loop because I need to iterate over something one by one. How do I properly increment i at the end of the loop?
Here is a video explaining my problem with context and explanation why it is not an ASYNC problem. Sorry if it is hard to follow, ill update it with audio soon so I can explain it propperly.
https://drive.google.com/file/d/1n1ZwNJif5Lb5zfLb2GPpBemObwpOqNf7/view
The problem is that the second one doesnt wait until first one is complete.
You can try with recursion inside then. There maybe some mistake with i,x but you get the point.
You execute first with i=1 and x=1, after the operation is done (then) you call the next until all elements are executed.
function execItem(i, x) {
var take = document.getElementById("row" + i + "sm" + x);
Tesseract.recognize(take)
.then(function(result){
rows[i][x] = result.text;
if (i < 15 && x < 15) {
if (i > 15) {
x += 1
i = 1
} else {
i += 1
}
execItem(i, x)
}
})
}
execItem(1, 1)
As a comment suggests this actually seems likely to be a problem with an asynchronous call (Tesseract...then) inside a loop. By the time the function inside then is called, your values of x and i have already moved on, so you don't get the result you expect.
One way around this would be to use a 'closure' - making a function that creates another function based on the value of i and x.
function getDisplayFunc(row, col) {
function displayRecognisedText(result) {
console.log(row, col, result.text);
//rows[row][col] = result.text;
}
return displayRecognisedText;
}
for (i = 1; i < 15; i++) {
for (x = 1; x < 15; x++) {
var take = document.getElementById("row" + i + "sm" + x);
Tesseract.recognize(take).then(getDisplayFunc(i, x));
}
}
I guess #Mike spot the error on: your code is asynchronous. What does it mean?
So, let's suppose you have this loop:
for (i = 0; i < 10; i++) {
console.log(i);
}
It will print this, right?
0
1
2
3
4
5
6
7
8
9
However, you do not print your value inside the loop directly, but as a follow-up operation to a promise. This makes this code asynchronous. It means that it does not have to execute at the exact moment you call it. I do not have Tesseract here so I will make my loop asynchronous using another very old trick, setTimeout():
for (i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
If I run it, I get this:
10
10
10
10
10
10
10
10
10
10
What happens is, when I pass the operation we want to do (in this case, printing the i value) to an asynchronous function (recognize().then() in your case, setTimeout() in my case) through a callback (function() {console.log(i);} in my example) the asynchronous function "schedules" the operation to execute as soon as possible, but this "soon" is not faster than the loop. So, the loop finishes executing but our callback is not called, not even once! Since you are not declaring i with let, it is a global variable, so there exists only one i. And since the loop finished, the value of the i variable is 10 already.
It used to be a hard thing to solve, but with ES6 it is quite straightforward: declare i with let!
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
The let-ed variable has a new binding at each iteration of the loop, so in practice you have 10 variables called i. The closure of your function will have access only to the one with the right value!
Maybe you should try to use while loop.
Like this:
while i < 15:
//do something
i += 1
For two variables: x, i with embeding:
while x < 15:
//do something
while i < 15:
//do something2
i += 1
x += 1
Hope I understand the problem correctly.
I'm trying to make a faux loading screen, and I need delays between loading messages of about 20-50ms or so so that people can actually see what's going on before it cuts to the initialized screen. The button that activates this goes to the following function:
function gameinit() {
for (k = 0; k <=1; k += 0.125) {
setTimeout(function () {
var nexttxt = "Loading... " + toString(100 * k) + "%"
}, 20);
displayupdate(nexttxt);
}
}
However this comes up as an incorrect syntax (on JSfiddle - https://jsfiddle.net/YoshiBoy13/xLn7wbg6/2/) when I use JShint - specifically lines four and five. I've looked at the guides for this and everything seems to be in order. What am I doing wrong?
(Note: displayupdate(nexttxt) updates the <p> tags with the next line of text)
When executing the script, nothing happens - the sixteen lines of text on the HTML move up as normal, the top eight being replaced with the eight generated by the gameinit() function, but the gameinit() only generates blank. If the script is executed again, it just outputs eight lines of 112.5% (as if it was the 9th iteration of the for loop).
I'm almost certain it's something elementary that I've missed, could someone please tell me what I've done wrong?
Use setInterval() instead, you can clear interval using clearInterval()
function gameinit() {
displayupdate("Loading... 0%");
var k = 0;
var inter = setInterval(function() {
if (k < 1) {
k += .25;
displayupdate("Loading... " + 100 * k + "%")
} else {
clearInterval(inter);
}
}, 2000);
}
function displayupdate(d) {
console.log(d);
}
gameinit();
here is another function can do this better ---- setInterval
var txt = '';
var time = 0;
var id = setInterval(function(){
console.log("loading..."+time/8*100+"%");
if(time++>7)
clearInterval(id);
},1000);
setTimeout doesn't work as you would expect it to work inside loops. You have to create a closure for each loop variable passed on to setTimeout, or create a new function to execute the setTimeout operation.
function gameinit() {
for (var k = 0; k <= 1; k += 0.125) {
doSetTimeOut(k);
}
}
function doSetTimeOut(k) {
setTimeout(function() {
var nexttxt = "Loading... " + toString(100 * k) + "%"
}, 20);
displayupdate(nexttxt);
}
My Javascript timer is for people with a rubiks cube with generates a scramble (nevermind all this, but just to tell you I'm generating after each solve a new scramble will be generated) and my scrambles do actually have a while (true) statement. So that does crash my script, but it 95/100 times stops just before the script crashes but I don't wanna have any times.
Let me explain a bit more detailed about the problem.
Problem: javascript crashes because my script takes too long to generate a scramble.
Below you have 3 functions I use.
This function generates a scramble with the Fisher-Yates shuffle.
Timer.prototype.generateScramble = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
This function validates the input e.g. I receive an array as the following:
Here I only have to check the first character. That's why I use the seconds [ ] notation. I don't want people get an F with an F2 e.g.
var scr = ["F","R","U","B","L","D","F2","R2","U2","B2","L2","D2","F'","R'","U'","B'","L'","D'"]
Timer.prototype.validateScramble2 = function(array) {
var last = array.length-1;
for (var i = 0; i < array.length-1; i++) {
if (array[i][0] == array[i+1][0]) {
return false;
}
}
for (var i = 0; i < array.length-2; i++) {
if (array[i][0] == array[i+2][0]) {
return false;
}
}
if (array[0][0] == [last][0]) {
return false;
}
return true;
};
The above functions are just waiting to be called. Well in the function below I use them.
Timer.prototype.updateScramble2 = function(scrambleArr, len, type) {
var self = this;
var scramble = '', j, updatedArr = [];
while (updatedArr.length < len) {
j = (Math.floor(Math.random() * scrambleArr.length));
updatedArr.push(scrambleArr[j]);
}
while (!self.validateScramble2(updatedArr)) {
updatedArr = self.generateScramble(updatedArr);
}
for (var i = 0; i < updatedArr.length; i++) {
scramble += updatedArr[i] + ' ';
}
scrambleDiv.innerHTML = scramble;
};
I assume you guys understand it but let me explain it briefly.
The first while-loop adds a random value from the given array(scrambleArr) into a new array called updatedArr.
The next while-loop calls the validateScramble2() function if there isn't in an array F next to an F2.
The for-loop adds them into a new variable added with a whitespace and then later we show the scramble in the div: scrambleDiv.innerHTML = scramble;
What do I need know after all this information?
Well I wanna know why my updateScramble2() functions lets my browser crash every time and what I do wrong and how I should do it.
I'm not entirely sure I understand the question, but from the way your code looks, I think you have an infinite loop going on. It appears as if validateScramble2 always returns false which causes your second loop in updateScramble2 to perpetually run.
I suggest you insert a breakpoint in your code and inspect the values. You could also insert debugger; statements in your code, works the same way. Open dev tools prior to doing these.
A suggestion is instead of using loops, use a timer. This breaks up your loop into asynchronous iterations rather than synchronous. This allows the browser breathing space for other operations. Here's an example of a forEachAsync:
function forEachAsync(array, callback){
var i = 0;
var timer = setInterval(function(){
callback.call(null, array[i]);
if(++i >= array.length) clearInterval(timer);
}, 0);
}
forEachAsync([1,2,4], function(item){
console.log(item);
});
You can take this further and use Promises instead of callbacks.
i have a problem accessing an array within an object method.
While the log returns the value perfectly, the following line returns an error that allRect[n] is undefined.
I suppose it has something to do with variable accessibility, but the fact that it can be logged in one line and refuses it's existence in the next one leaves me a bit out of ideas.
Thanks all.
this.s = Snap('#'+id);
var allRects = [];
this.xPos = 0;
var scale = vizWidth/locationSum(data);
...
//methods
this.updateViz = function() {
apiRequest('datasets', 164, 'json').done(
function(data){
var n = 0;
data = locationDataIntoArray(data);
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
}
)
};
In this code:
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
you're incrementing n twice on each iteration. Halfway through the for loop, n will be beyond the end of the array.
The first time through the loop, when i and n are both zero, you'll animate allRects[0]. Then you increment n and animate allRects[1], and then increment n again. Thus, on the second time through the loop, you'll be animating allRects[2] and allRects[3], and so on.
I am using this code to weather some circles are overlapping:
iCantThinkOfAGoodLabelName:
x = genX(radius);
y = genY(radius);
for(i in circles) {
var thisCircle = circles[i];
if(Math.abs(x-thisCircle["x"])+Math.abs(y-thisCircle["y"])>radius*2) { //No overlap
continue;
} else { //Overlap
continue iCantThinkOfAGoodLabelName; //<- Line 256
}
thisCircle = [];
}
But when the continue statement is reached, chrome's developer console gives me this: client.html:256 Uncaught SyntaxError: Undefined label 'iCantThinkOfAGoodLabelName'
The label should come immediately before the loop
x = genX(radius);
y = genY(radius);
iCantThinkOfAGoodLabelName:
for(i in circles) {
Because iCantThinkOfAGoodLabelName: needs to be right before the loop.
iCantThinkOfAGoodLabelName:
for (blah; blah; blah)
..
I think what you want is a function..
function iCantThinkOfAGoodFunctionName() {
var x = genX(radius),
y = genY(radius);
for (i in circles) {
var thisCircle = circles[i];
if(Math.abs(x-thisCircle["x"])+Math.abs(y-thisCircle["y"])>radius*2) { //No overlap
continue;
} else { //Overlap
iCantThinkOfAGoodFunctionName();
}
thisCircle = [];
}
}
There should not be any statement between a label name and associated loop.
x = genX(radius);
y = genY(radius);
iCantThinkOfAGoodLabelName:
for(i in circles) {
fixes it.
I recently had this issue and I resolved it by using all lowercase in the loop's label in version v0.8.x of Node.js.
Using labelname: vs. iCantThinkOfAGoodLabelName: might help you.
Others have correctly corrected you on the location of the label. It should be immediately before the for loop.
The Mozilla Developer Network on labels advises to avoid using labels, and instead prefer calling functions or throwing an error. You might rethink your strategy on using them, if possible.
Example of calling a function depending on result:
var i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
// we want to ignore and continue
} else {
// do work with these variables from inside the doWork function
// (scoped to whatever scope `this` for loop is in)
doWork.call(this, i, j);
}
}
}