Javascript蛇游戏(食物产卵地点)

时间:2017-11-03 20:13:44

标签: javascript html5 canvas

假设我有一个20格的20格“格子”。我随机产生食物的方式是使用以下公式:

Math.floor(Math.random() * ((max - min) / 20) + 1) + 20 * min;

这基本上可以确保食物在一个网格单元内整齐地生成。

我想避免在蛇身上产生食物。我没有找到最好的方法来保持分布式随机性。

不太有用的解决方案:

我见过有些人这样做,但它不起作用,因为它不能保证食物永远不会在蛇身上产生,它只会降低它的可能性。 getRandomPoint()可能仍然让我在蛇上随机点。

for (let i = 0; i < snake.length; i++) {
    if (foodPosition.x === snake[i].x && foodPosition.y === snake[i].y) {
        foodPosition.x = getRandomPoint();
        foodPosition.y = getRandomPoint();
    }
}

下一个也不起作用,因为食物仍然可以在尚未检查的蛇的任何细胞上产卵。例如,当i = 0时,它只检查foodPosition.x和foodPosition.y是否等于snake [0] .x和snake [0] .y。在i = 0的循环迭代中,食物仍会在蛇[2] .x,蛇[2] .y所占据的细胞上产生(例如,我认为?)。

for (let i = 0; i < snake.length; i++) {
    while (foodPosition.x === snake[i].x && foodPosition.y === snake[i].y) {
        foodPosition.x = getRandomPoint();
        foodPosition.y = getRandomPoint();
    }
}

还有其他一些我尝试过的东西,但我会留下它。做我想做的事情的好方法是什么?

3 个答案:

答案 0 :(得分:2)

我会生成一个允许食物产卵的可能位置列表。类似于所有位置的集合减去蛇体位置的​​集合。

我在JavaScript和p5.js中做过与Minesweeper类似的事情。两个地雷不能占用同一个小区。当我生成地雷时,我从可能的位置列表中删除了它们的位置。

let numRows = 20;
let numColumns = 20;

let possibleFoodLocations = [];

for (let row = 0; row < numRows; row++) {
    for (let column = 0; column < numColumns; column++) {
        let isLocationValid = snake.every(bodyPart => {
            return row !== bodyPart.y || column !== bodyPart.x;
        });

        if (isLocationValid) {
            possibleFoodLocations.push({ x: column, y: row });
        }
    }
}

请注意,这将执行numRows * numColumns * snake.length * 2操作,因此当这些值中的任何一个很大时重复执行将变得效率低下。我认为,最好的方法是当这些值很大时将它们组合在一起,并在这些值很小时选择一个随机点。

答案 1 :(得分:1)

您是否可以获得随机点,然后检查以确保它与蛇的任何一点不匹配?如果是这样,你可以得到另一个随机点。

答案 2 :(得分:1)

我在您的解决方案中添加了一个标志,然后它就能正常工作

let colliding = true;

let new_x, new_y; 

while(colliding) {
    colliding = false;
    new_y = getRandomPoint();
    new_x = getRandomPoint();

    for (let box of snake) {
        if (new_x == box.x && new_y == box.y) {
            colliding = true;
            break;
        }
    }
}

foodPosition.x = new_x;
foodPosition.y = new_y;