- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我正在开发这个蛇游戏,我基本上是在试图防止食物在蛇尾部上生成。我的设置变量:
let headX = 10; //snake starting position
let headY = 10;
let appleX = 5; //food starting position
let appleY = 5;
这是检查头部/食物碰撞的函数
function checkAppleCollision() {
if (appleX === headX && appleY === headY) {
generateApplePosition();
tailLength++;
score++;
}
}
这是在碰撞后随机化苹果位置的函数,并且在几次碰撞后还返回“太多递归”错误:
function generateApplePosition() {
let collisionDetect = false;
let newAppleX = Math.floor(Math.random() * tileCount);
let newAppleY = Math.floor(Math.random() * tileCount);
for (let i = 0; i < snakeTail.length; i++) {
let segment = snakeTail[i];
if (newAppleX === segment.x && newAppleY === segment.y) {
collisionDetect = true;
}
}
while (collisionDetect === true) {
generateApplePosition();
}
appleX = newAppleX;
appleY = newAppleY;
}
请帮忙,我不知道该怎么办。其他一切都按预期进行。
最佳答案
使用递归或do while
是一个坏主意(我稍后会解释)
同时,您可以通过创建来简化逻辑:
samePos()
和collides()
函数createApple()
函数,如果随机生成的 x,y 位置被蛇体占据,该函数将返回自身const world = {w:6, h:1}; // height set to 1 for this demo only
const snake = [{x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}];
const apple = {pos: {x:0, y:0}};
// Check if two object's x,y match
const samePos = (a, b) => a.x === b.x && a.y === b.y;
// Check if object x,y is inside an array of objects
const collides = (ob, arr) => arr.some(o => samePos(ob, o));
const createApple = () => {
const randPos = {
x: ~~(Math.random() * world.w),
y: ~~(Math.random() * world.h),
};
if (collides(randPos, snake)) {
console.log(`position ${randPos.x} ${randPos.y} is occupied by snake`);
return createApple(); // Try another position.
}
// Finally a free spot!
apple.pos = randPos;
console.log(`Apple to free position: ${apple.pos.x} ${apple.pos.y}`);
}
createApple();
Run this demo multiple times
无用的随机猜测!
从上面的示例中可以看出,如果多次运行,随机生成的数字通常与之前生成的数字相同:
...
position 2 0 is occupied by snake <<<
position 1 0 is occupied by snake
position 2 0 is occupied by snake <<<
position 2 0 is occupied by snake <<<
position 1 0 is occupied by snake
position 2 0 is occupied by snake <<<
...
因此,当你的蛇变大时,递归可能会变得疯狂——荒谬,迭代太多次,在相同的 xy 位置上重复和失败,直到最后到达一个罕见的空闲点......
这是一个非常糟糕的设计。
一种解决方案是跟踪数组内已使用的随机位置 - 但这意味着不必要地遍历这样的数组。
最佳解决方案实际上不是将游戏视为2D 游戏,而是视为1D 游戏:
将这张尺寸为 4x3 的 2D map 视为索引:
0 1 2 3
4 5 6 7
8 9 10 11
现在,让我们在这张 map 中放置一条蛇:
0 ⬛ 2 3
4 ⬛ ⬛ 7
8 9 ⬛ 11
这是以蛇作为一维列表的线性映射:
[ 0 ⬛ 2 3 4 ⬛ ⬛ 7 8 9 ⬛ 11 ]
因此,您不需要使用对象数组 {x:n, y:n}
来表示蛇的 body 位置,您所需要的只是:
[1, 5, 6, 10] // Snake body as indexes
既然你知道了所有不允许放置苹果的索引,那么在创建新苹果时你需要做的就是:
删除
这些索引以获得空闲点索引数组const indexToXY = (index, width) => ({ x: index%width, y: Math.trunc(index/width) });
const world = {w:4, h:3};
const snakeBody = [1, 5, 6, 10];
const createApple = () => {
const arr = [...Array(world.w * world.h).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
snakeBody.forEach(i => delete arr[i]);
const freeIndexes = arr.filter(k => k !== undefined); // [0, 2, 3, 4, 7, 8, 9, 11]
const appleIndex = freeIndexes[~~(Math.random() * freeIndexes.length)];
const applePos = indexToXY(appleIndex, world.w);
console.log("New apple position: %o", applePos);
};
createApple();
Run this demo multiple times
有了免费的点索引,只需使用这个简单的公式在 XY 坐标处绘制您的苹果
X = 索引% mapWidth
Y = 地板(索引/ map 宽度)
关于Javascript 贪吃蛇游戏 - 递归错误太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71570107/
我不知道如何将尾部链接到头部以初始化列表。我了解如何链接新节点以及链接后的所有内容,但我不知道如何正确初始化蛇。它是用 C 语言编写的。 typedef struct node { int x
我想“更深入”地了解 C,所以我决定编写一个游戏 - 供 2 名玩家使用的贪吃蛇。 创建一个“ map ”,Snake结构,将其放入“ map ”(使用COORD)不是问题,但我知道,我会卡在某个地方
我是一名优秀的程序员,十分优秀!