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….
Advertisement
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!"); }