JS写的贪吃蛇游戏未定义

Undefined in Snake Game written in JS

我正在制作自己的贪吃蛇游戏来掌握我的 JS,但我遇到了以下问题:

我制作了跟踪蛇头位置的移动日志。由于日志历史记录,每个下一个 snake 段都应该就位。每个移动序列函数都会将位置坐标添加到日志中。问题是一些添加到日志数组的对象是未定义的。谁能告诉我为什么??

//ELEMENTS
const segments = document.querySelectorAll(".segment");
const snake = document.getElementById("snake");
snake.style.position = "absolute";
let moveLog = []; //LOG REMEMBERING MOVEMENTS

//CONFIG

//start position
let position = {
  t: 300,
  l: 300,
  dir: "top",
};
let wonszSize = 30; //SNAKE SIZE
let movementSpeed = 1 * wonszSize;

//EVENTS LISTENERS

document.addEventListener("keydown", Turn);
document.addEventListener("click", () => {
  console.log(moveLog);
}); //I USE IT TO LOOK INTO LOG AND DEBUG

//FUNCTIONS

//REFRESHES POSITION
function setPosition(t, l) {
  snake.style.top = `${t}px`;
  snake.style.left = `${l}px`;
}

//ASIGNMENT OF ID FOR EACH SEGMENT
function SegmentsID() {
  let i = 0;
  segments.forEach((segment) => {
    segment.id = i;
    ++i;
  });
}

//SETTING POSITION OF SEGMENTS (STARTING)
function setSegments(t, l) {
  segments.forEach((segment) => {
    segment.style.top = `${t + segment.id * 30}px`;
    segment.style.left = `${l}px`;
  });
}

//MAKING TURNS
function Turn(e) {
  if (position.dir == "top") {
    switch (e.code) {
      case "KeyA":
        position.dir = "left";
        break;
      case "KeyD":
        position.dir = "right";
        break;
    }
  } else if (position.dir == "left") {
    switch (e.code) {
      case "KeyW":
        position.dir = "top";
        break;
      case "KeyS":
        position.dir = "bot";
        break;
    }
  } else if (position.dir == "bot") {
    switch (e.code) {
      case "KeyA":
        position.dir = "left";
        break;
      case "KeyD":
        position.dir = "right";
        break;
    }
  } else {
    switch (e.code) {
      case "KeyW":
        position.dir = "top";
        break;
      case "KeyS":
        position.dir = "bot";
        break;
    }
  }
}

// CONSTANT MOVEMENT - MARKS COORDINATES IN THE LOG HISTORY /IT'S HISTORY OF HEAD MOVEMENTS
function movement() {
  let logObject = {
    t: position.t,
    l: position.l,
  }; //HERE COMES THE PROBLEM SINCE SOME LOGS ARE NOT ADD AS OBJECTS BUT AS UNDEFINED <---------
  moveLog.push(logObject);
  if (position.dir == "bot") {
    position.t += movementSpeed;
  } else if (position.dir == "top") {
    position.t -= movementSpeed;
  } else if (position.dir == "left") {
    position.l -= movementSpeed;
  } else {
    position.l += movementSpeed;
  }

  setPosition(position.t, position.l); // REFRESH FOR NOW WORKS FOR HEAD ONLY
}

//MOVE ALL THE BODY <- THIS MEANT TO MOVE ALL THE SEGMENTS TO DESTINATIONS IN MOVMENTLOG HISTORY
function bodyMovin() {
  segments.forEach((segment) => {
    let destination = moveLog[moveLog.length - segment.id];
    console.log(destination); // <----SOME ARE UNDEFINED DON'T KNOW WHY
    /* 
    THIS WILL BE HERE IF CODE WORKS.

     RefreshPostion(destination.t, destination.l)
    
    */
  });
}

//TIME
let MoveTimeHead = setInterval(movement, 300);
let MoveTimeBody = setInterval(bodyMovin, 300);

// MAIN
function main() {
  SegmentsID();
  setSegments(position.t, position.l);
  MoveTimeHead;
  MoveTimeBody;
}
main();

HTML:

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="plansza">
      <div class="snake">
        <div class="snake-head segment" id="snake"></div>
        <div class="segment"></div>
        <div class="segment"></div>
        <div class="segment"></div>
      </div>
    </div>
    <script src="app3.js"></script>
  </body>
</html>

如果 array.length 是数组中的项数,则 array[array.length - 1] 是数组中的最后一项。如果您访问 array[array.length],您将获得 undefined

问题出在函数 bodyMovin 的下面一行...

let destination = moveLog[moveLog.length - segment.id];

segment.id 从 0 开始向上计数。因此,您用来访问数组的第一个索引是 moveLog.length - segment.idmoveLog.length - 0,这是数组中最后一项之后的索引,因此 undefined

如果你使用

let destination = moveLog[moveLog.length - 1 - segment.id];

并且只要没有 segments.id 大于 moveLog.length - 1,您就不会再得到 undefined,因为数组 moveLog 中没有未定义的项。

然而,一个数组的索引依赖于另一个数组中的项目数,这只会再次打扰您。