为什么它立即让玩家输了

Why does it instantly have the player lose

var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;

function setup() {
  smooth();
  frameRate(999)
  createCanvas(600, 450);
  playerX = 500;
  playerY = 100;

}

function draw() {
  var TotalBlue = 0;
  var TotalRed = 0;
  var Total = 0;
  var cellDist = [];
  if (lost) {
    noLoop()
    fill(255)
    textSize(40)
    background(0)
    text("You lost", width / 2.5, height / 2)
    textSize(20)
    text("Final Board: ", 350, 60)
  } else {
    background(220);
    push();

    var Newzoom = 10 / playerSize
    let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
    Newzoom = lerp(zoom, Newzoom, 0.3)
    translate(Xgrid / 2, Ygrid / 2 - 50);
    scale(newnewZoom)
    translate(-playerX, -playerY);


    playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
    Newcelltimer++;

    if (Newcelltimer % 40 == 0) {
      cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
        ceil(random(0 - Ygrid, 2 * Ygrid)))
    }

    if (Newcelltimer % 200 == 0) {
      cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
      OffSetX.push(ceil(random(0, 1000000)))
      OffSetY.push(ceil(random(1000000, 2000000)))
      CPUteam++;
    }
    if (Newcelltimer == 1 || Newcelltimer == 2) {
      cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
      OffSetX.push(ceil(random(0, 1000000)))
      OffSetY.push(ceil(random(1000000, 2000000)))
      CPUteam++;
    }
    //Checks if player Ate cell
    for (var i = 0; i < cell.length / 2; i++) {
      let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
      if (d <= playerSize / 2) {
        playerSize += 5;
        cell.splice(i * 2, 2)
        celliseaten = true;
      }
    }
    if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
      playerY -= playerSpeed;
    }
    if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
      playerX += playerSpeed;
    }
    if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
      playerY += playerSpeed;
    }
    if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
      playerX -= playerSpeed;
    }

    if (Newcelltimer % 200 == 0) {
      cell.splice(0, 2)
    }
    for (var j = 0; j < (cpu.length / 4); j++) {
      var cpuDist = [];
      //Checks if AI ate cell
      for (var n = 0; n < cell.length / 2; n++) {

        let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
        if (dis <= cpu[j * 4 + 2] / 2) {
          cpu[j * 4 + 2] += 5;
          cell.splice(n * 2, 2)
        } else {
          cellDist.push(dis)
        }
      }
      var ClosestCell = min(cellDist);
      var ClosestCellpos;
      for (var r = 0; r < cell.length / 2; r++) {
        if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
          ClosestCellpos = r;
          break;
        }
      }

      let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
      if (r < 100 && dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 || cpu[j * 4 + 2] > playerSize) {
        var disXpos = cell[r * 2] - cpu[j * 4];
        var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];

        disXpos = map(disXpos, -100, 100, -1, 1);
        disYpos = map(disYpos, -100, 100, -1, 1);
        cpu[j * 4] += disXpos * amp;
        cpu[j * 4 + 1] += disYpos * amp;
      } else {
        x += 0.003;
        y += 0.003;
        let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
        let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
        cpu[j * 4] += offsetX;
        cpu[j * 4 + 1] += offsetY;
      }
      //Draws the AI's
      if (cpu[j * 4 + 3] % 2 == 0) {
        fill(0, 0, 255)
        circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
      } else {
        fill(255, 0, 0)
        circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
      }
      //Checks if player ate AI or vice versa
      let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
      if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
        playerSize += floor(cpu[j * 4 + 2]);
        cpu.splice(j * 4, 4)
      }
      if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
        lost = true;
      }

      //Checks if one AI eats another
      for (var m = 0; m < cpu.length / 4; m++) {
        if (m != j) {
          if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
            distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
            let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]

            if (higher > distant) {
              if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
                cpu[m * 4 + 2] += cpu[j * 4 + 2]
                cpu.splice(j * 4, 4)
              } else {
                cpu[j * 4 + 2] += cpu[m * 4 + 2]
                cpu.splice(m * 4, 4)
              } //Else
            } // If
          } //If
        } //If
      } //If
    } //Nested For
  } // For
  //Draws all the "cells"
  for (var k = 0; k < cell.length / 2; k++) {

    fill(0, 255, 255, 100)
    circle(cell[k * 2], cell[k * 2 + 1], 7)
  }
  //Nothing important, drawing the smiley face character
  fill(255, 255, 0)
  circle(playerX, playerY, playerSize)
  fill(0)
  ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
  ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
  arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
  fill(255, 255, 0)
  noStroke()
  arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
  stroke(0)
  //Limits the max player size
  if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
    if (Xgrid > Ygrid) {
      playerSize = 3 * Ygrid;
    } else {
      playerSize = 3 * Xgrid;
    }
  }
}

VS


var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;

function setup() {
  smooth();
  frameRate(999)
  createCanvas(600, 450);
  playerX = 500;
  playerY = 100;

}

function draw() {
  var TotalBlue = 0;
  var TotalRed = 0;
  var Total = 0;
  var cellDist = [];
  if (lost) {
    noLoop()
    fill(255)
    textSize(40)
    background(0)
    text("You lost", width / 2.5, height / 2)
    textSize(20)
    text("Final Board: ", 350, 60)
  } else {
    background(220);
    push();

    var Newzoom = 10 / playerSize
    let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
    Newzoom = lerp(zoom, Newzoom, 0.3)
    translate(Xgrid / 2, Ygrid / 2 - 50);
    scale(newnewZoom)
    translate(-playerX, -playerY);


    playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
    Newcelltimer++;

    if (Newcelltimer % 40 == 0) {
      cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
        ceil(random(0 - Ygrid, 2 * Ygrid)))
    }

    if (Newcelltimer % 200 == 0) {
      cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
      OffSetX.push(ceil(random(0, 1000000)))
      OffSetY.push(ceil(random(1000000, 2000000)))
      CPUteam++;
    }
    if (Newcelltimer == 1 || Newcelltimer == 2) {
      cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
      OffSetX.push(ceil(random(0, 1000000)))
      OffSetY.push(ceil(random(1000000, 2000000)))
      CPUteam++;
    }
    //Checks if player Ate cell
    for (var i = 0; i < cell.length / 2; i++) {
      let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
      if (d <= playerSize / 2) {
        playerSize += 5;
        cell.splice(i * 2, 2)
        celliseaten = true;
      }
    }
    if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
      playerY -= playerSpeed;
    }
    if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
      playerX += playerSpeed;
    }
    if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
      playerY += playerSpeed;
    }
    if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
      playerX -= playerSpeed;
    }

    if (Newcelltimer % 200 == 0) {
      cell.splice(0, 2)
    }
    for (var j = 0; j < (cpu.length / 4); j++) {
      var cpuDist = [];
      //Checks if AI ate cell
      for (var n = 0; n < cell.length / 2; n++) {

        let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
        if (dis <= cpu[j * 4 + 2] / 2) {
          cpu[j * 4 + 2] += 5;
          cell.splice(n * 2, 2)
        }
      }

      let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
      x += 0.003;
      y += 0.003;
      let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
      let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
      cpu[j * 4] += offsetX;
      cpu[j * 4 + 1] += offsetY;
      //Draws the AI's
      if (cpu[j * 4 + 3] % 2 == 0) {
        fill(0, 0, 255)
        circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
      } else {
        fill(255, 0, 0)
        circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
      }
      //Checks if player ate AI or vice versa
      let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
      if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
        playerSize += floor(cpu[j * 4 + 2]);
        cpu.splice(j * 4, 4)
      }
      if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
        lost = true;
      }

      //Checks if one AI eats another
      for (var m = 0; m < cpu.length / 4; m++) {
        if (m != j) {
          if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
            distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
            let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]

            if (higher > distant) {
              if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
                cpu[m * 4 + 2] += cpu[j * 4 + 2]
                cpu.splice(j * 4, 4)
              } else {
                cpu[j * 4 + 2] += cpu[m * 4 + 2]
                cpu.splice(m * 4, 4)
              } //Else
            } // If
          } //If
        } //If
      } //If
    } //Nested For
  } // For
  //Draws all the "cells"
  for (var k = 0; k < cell.length / 2; k++) {

    fill(0, 255, 255, 100)
    circle(cell[k * 2], cell[k * 2 + 1], 7)
  }
  //Nothing important, drawing the smiley face character
  fill(255, 255, 0)
  circle(playerX, playerY, playerSize)
  fill(0)
  ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
  ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
  arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
  fill(255, 255, 0)
  noStroke()
  arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
  stroke(0)
  //Limits the max player size
  if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
    if (Xgrid > Ygrid) {
      playerSize = 3 * Ygrid;
    } else {
      playerSize = 3 * Xgrid;
    }
  }
}

首先我知道这甚至不接近最小可重现代码,但我试图用一些注释来清理它。我不确定要删除什么,所以我 100% 对对此 post 所做的任何编辑持开放态度。话虽如此,我的问题是为什么最重要的一个不起作用。我应该弄清楚我要做什么,在伪代码中看起来像这样:

  1. Return 包含单元格和 AI 之间所有距离的数组
  2. 找到该数组中的最小值
  3. 找出单元格的X和Y位置
  4. 检查该数组中的最小值是否小于任意 100,AND EITHER AI 的大小大于玩家的,OR 玩家和AI之间的距离小于另一个任意100
    1. 如果为假,继续使用 Perlin 噪声计算 AI 的下一步行动
    2. 如果为真,计算AI离cell的X距离和Y距离
      • 使用这些距离,将其映射到 -1 和 1,然后将其乘以振幅,然后只需将 AI 移动您获得的值即可。

我要问的是,为什么这不是首先起作用的,以及如何使其起作用。 我怀疑AI在整个地图上都失去了控制,并且由于AI的初始大小比玩家大,所以玩家输了。

很可能我的程序不会加载到代码段工具中,所以这里是 Web 编辑器上程序的链接

第一个(不工作)- https://editor.p5js.org/Meowmeow/sketches/5725Ik6AF

第二个(工作)- https://editor.p5js.org/Meowmeow/sketches/XTH-hArn6

如果问题不清楚,请写下您不明白的地方,因为我不确定没有任何背景信息的其他人是否很难理解发生了什么。

编辑)刚刚意识到该列表不适用于伪代码,我现在没有时间修复它。 (固定)

-编辑) 只是为了清除它,我希望 CPUs 有一个更具战略性、随机性更少的路径,为此我首先执行上面所述的以下操作(让 CPU 吃掉一个单元格如果附近有的话)

玩家立即失败的原因是检查 AI“cpu”与玩家距离的代码无法正常工作。

      var cpuDist = [];
      //Checks if AI ate cell
      for (var n = 0; n < cell.length / 2; n++) {
        let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
        if (dis <= cpu[j * 4 + 2] / 2) {
          cpu[j * 4 + 2] += 5;
          cell.splice(n * 2, 2)
        } else {
          cellDist.push(dis)
        }
      }
      // NOTE: if there are no entries in cpu for which the condition in the above if block was false, then cellDist will be empty
      var ClosestCell = min(cellDist);
      // NOTE: if cellDist is empty, then ClosestCell will be Infinity
      var ClosestCellpos;
      for (var r = 0; r < cell.length / 2; r++) {
        // NOTE: If ClosestCell is Infinity than this will never be true, and ClosestCellpos will be undefined
        if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
          ClosestCellpos = r;
          break;
        }
      }

      let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
      // NOTE: This is bad form: using r from the above for loop. If you are going to use a variable that is initialized/incremented by a for loop you should declare it separately outside of the for loop. Perhaps you should be using ClosestCellpos instead of r?
      // NOTE: r < 100 is strange. what does that mean/matter? is cell.length / 2 guaranteed to be >= 100?
      if (r < 100 &&
          dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 ||
          // NOTE: because this is after a logical OR this can succeed even if the value of r is >= cell.length / 2
          cpu[j * 4 + 2] > playerSize) {

        // NOTE: when r is >= cell.length / 2 + 1 one or both of these become NaN
        var disXpos = cell[r * 2] - cpu[j * 4];
        var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];

        // When disXpos or disYpos are NaN we start putting NaN values into the cpu array
        disXpos = map(disXpos, -100, 100, -1, 1);
        disYpos = map(disYpos, -100, 100, -1, 1);
        cpu[j * 4] += disXpos * amp;
        cpu[j * 4 + 1] += disYpos * amp;
      }

      // .........

      // NOTE: the int() function converts NaN into 0, which is unfortunate. You should use floor() instead of int()
      let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
      if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
        playerSize += floor(cpu[j * 4 + 2]);
        cpu.splice(j * 4, 4)
      }
      // NOTE: Once distance is zero because if the above series of notes, this becomes true, which happens immediately
      if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
        lost = true;
      }

这是一个 working version。我搬到 OpenProcessing.org 是因为 p5js.org 编辑器不能很好地调试。我能够通过简单地在 list = true; 之前抛出一个 debugger; 语句然后向后工作来找到这个问题。您需要打开浏览器的开发人员工具面板才能使 debugger; 语句生效。

注意:这个草图有很多代码味道问题,很难调试。

  1. 永远不要使用 var。始终使用 let
  2. 单元格和 cpu 数据结构令人困惑且难以理解。与其像这样将 x 和 y 值打包到数组中,不如将这些数据结构表示为对象数组要好得多。我仍然不理解这些数组中的所有 n * 2j * 4 索引。必须有更好的方法来模拟您的状态。

但是您很好地为可运行的示例提供了 link,否则将无法确定您的问题。