Skip to content

browser freezing when in while loop (snake game)

I’m making the popular snake game for js homework. I have a function which is meant to ensure that after an apple is eaten it moves to a different location on the canvas while not being on any part of the snake, the function without the loop works fine (though apples are placed on the snake too):

 move() {
            let onSnake = true;
            let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
            let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
          
            this.x = x;
            this.y = y;

            this.draw();
        }

the function though with the loop ends up freezing after a few apples are eaten (right before hitting an apple):

 move() {
            let onSnake = true;
            let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
            let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
            while (onSnake) {
                onSnake = false;
                x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
                y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
                for (let index = 0; index < snake.parts.length; index++) {
                    if (x === snake.parts[index].x || y === snake.parts[index].y) {
                        onSnake = true;
                        break;
                    }
                }
            }
            this.x = x;
            this.y = y;

            this.draw();
        }

with getRandomNumber being:

getRandomNumber(min, max) {
            let r = Math.floor(Math.random() * (max - min + 1)) + min;
            r = r - (r % UnitSize);
            return r;
        }

this is my second question on SO, don’t fry me please….

Answer

I didn’t get a moment to test but I suspect it’s as simple as the following evalutation.

if (x === snake.parts[index].x || y === snake.parts[index].y) {
    onSnake = true;
    break;
}

You are accepting either X or Y collision. Meaning the apple cannot share any X or Y coordinates with any of the snake pieces. What you want instead is and I believe. It’s like saying we both live on the same house because we live on the same street. No, we need to also have the same address.

As a safety, you could add a limit to how many iterations of the loop can run in the event their is no more space remaining for an apple.

let counter = 0;
while (onSnake && counter < 5000) {
    onSnake = false;
    x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
    y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
    for (let index = 0; index < snake.parts.length; index++) {
        if (x === snake.parts[index].x && y === snake.parts[index].y) {
            onSnake = true;
            break;
        }
    }
    counter += 1;
}
if (counter == 5000)    {
    alert("Could not find space for any more apples!");
}