gpt4 book ai didi

Javascript 贪吃蛇游戏 - 递归错误太多

转载 作者:行者123 更新时间:2023-12-02 01:41:13 25 4
gpt4 key购买 nike

所以我正在开发这个蛇游戏,我基本上是在试图防止食物在蛇尾部上生成。我的设置变量:

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

既然你知道了所有不允许放置苹果的索引,那么在创建新苹果时你需要做的就是:

  • 创建一个由 0-N 个索引组成的数组,长度为:world.w * world.h
  • 循环蛇体索引并从索引数组中删除这些索引以获得空闲点索引数组
  • 只需从该数组的空闲点中仅获取一次随 secret 钥即可!

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com