David Nugent David Nugent - 6 months ago 12
jQuery Question

Getting an infinite loop and can't see why - Javascript

I'm writing a simple little Connect 4 game and I'm running into an infinite loop on one of my functions:

var reds = 0;
var greens = 0;

function checkEmpty(div) {
var empty = false;
var clicked = $(div).attr('id');
console.log(clicked);
var idnum = parseInt(clicked.substr(6));
while (idnum < 43) {
idnum = idnum + 7;
}
console.log("idnum=" + idnum);
while (empty == false) {
for (var i = idnum; i > 0; i - 7) {
idnumStr = idnum.toString();
var checking = $('#square' + idnumStr);
var str = checking.attr('class');
empty = str.includes('empty');
console.log(empty);
var divToFill = checking;
}
}

return divToFill;
}

function addDisc(div) {
if (reds > greens) {
$(div).addClass('green');
greens++;
console.log("greens=" + greens);
} else {
$(div).addClass('red');
reds++;
console.log("reds=" + reds);
};
$(div).removeClass('empty');
}

$(function() {
var i = 1;
//add a numbered id to every game square
$('.game-square').each(function() {
$(this).attr('id', 'square' + i);
i++;
//add an on click event handler to every game square

//onclick functions
$(this).on('click', function() {
var divToFill = checkEmpty(this);
addDisc(divToFill);
})
})
})


Here is a link to the codepen http://codepen.io/Gobias___/pen/xOwNOd

If you click on one of the circles and watch the browser's console, you'll see that it returns true over 3000 times. I can't figure out what I've done that makes it do that. I want the code to stop as soon as it returns empty = true. empty starts out false because I only want the code to run on divs that do not already have class .green or .red.

Where am I going wrong here?

Answer

for (var i = idnum; i > 0; i - 7);

You do not change the i.

Do you want to decrement it by 7?

Change your for loop to the one shown below:

for (var i = idnum; i > 0; i -= 7) {
  // ...
}

You also do not use loop variable in the loop body. Instead, you use idnum, I think this can be issue.

while (empty == false) {
    for (var i = idnum; i > 0; i -= 7) {
        idnumStr = i.toString(); // changed to i
        var checking = $('#square' + idnumStr);
        var str = checking.attr('class');
        empty = str.includes('empty');
        console.log(empty);
        var divToFill = checking;
        // and don't forget to stop, when found empty
        if (empty) break;
    }
}

I add break if empty found, because if we go to next iteration we will override empty variable with smallest i related value.

You can also wrap empty assignment with if (!empty) {empty = ...;} to prevent this override, but I assume you can just break, because:

I want the code to stop as soon as it returns empty = true