此代码在 grid<=11 时运行,但在 grid>=12 时永远卡住。谁能解释为什么会这样? (使用 JavaScript 的 p5.js 库)

This code runs for grid<=11 but gets stuck forever for grid>=12. Can anyone explain why this happens? (Using p5.js library of JavaScript)

基本上是标题。每一行我都读了很多遍,仍然找不到我的错误。 我只是想通过调用创建 object 然后再次调用自身的递归函数来将正方形放在网格上。我已经检查过递归不是无限的,并且有一个简单的退出条件。请帮忙。

let grid = 11;
let sqr = [];
function setup() {
  createCanvas(grid * grid, grid * grid);
  noFill();
  colorMode(HSB);
  noLoop();
  let maxs = floor(grid / 3);
  let ratio = 2 * maxs * maxs;
  makegrid(maxs, ratio);
}
function draw() {
  background(0);
  for (let sq of sqr) sq.show();
}
function makegrid(m, r) {
  if (!m) return;
  if (m == floor(grid / 3)) {
    for (let i = 0; i < 2; i++) sqr.push(new sqrs(m, r));
    m--;
    makegrid(m, r);
  } else {
    let j = r / (m * m);
    for (let k = 0; k < j; k++) sqr.push(new sqrs(m, r));
    m--;
    makegrid(m, r);
  }
}

class sqrs {
  constructor(m, r) {
    let flag = true;
    this.s = (m * width) / grid;
    while (flag) {
      flag = false;
      this.x = (width / grid) * floor((grid + 1 - m) * random());
      this.y = (height / grid) * floor((grid + 1 - m) * random());
      if (!sqr.length) flag = false;
      else {
        for (let sq of sqr) {
          let d = (this.x - sq.x) ** 2 + (this.y - sq.y) ** 2;
          if (d < this.s ** 2 || d < sq.s ** 2) {
            flag = true;
            break;
          }
        }
      }
    }
  }

  show() {
    stroke(random(340), 80, 80);
    square(this.x, this.y, this.s);
  }
}

正如 Jay 在评论中指出的那样,问题不在于递归,而在于 sqrs 构造函数中的 while (flag) 循环:

let grid = 12;
let sqr = [];

function setup() {
  createCanvas(grid * grid, grid * grid);
  noFill();
  colorMode(HSB);
  noLoop();
  // maxs will be 4 if grid is 12
  let maxs = floor(grid / 3);
  // ratio will be 32
  let ratio = 2 * maxs * maxs;
  makegrid(maxs, ratio);
}

function draw() {
  background(0);
  for (let sq of sqr) sq.show();
}

function makegrid(m, r) {
  if (m <= 0) return;
  if (m == floor(grid / 3)) {
    // Call 0: m == floor(grid / 3) == 4
    for (let i = 0; i < 2; i++) sqr.push(new sqrs(m, r));
    m--;
    // Call 0: makegrid(3, 32);
    makegrid(m, r);
  } else {
    // Call 1: j = 32 / (3 * 3) = 3.55555
    // Call 2: j = 32 / (2 * 2) = 8
    // Call 3: j = 32 / (1 * 1) = 32
    let j = r / (m * m);
    for (let k = 0; k < j; k++) sqr.push(new sqrs(m, r));
    m--;
    // Call 1: makegrid(2, 32)
    // Call 2: makegrid(1, 32)
    // Call 3: makegrid(0, 32)
    makegrid(m, r);
  }
}

class sqrs {
  constructor(m, r) {
    let flag = true;
    this.s = (m * width) / grid;
    // This code might end up repeating forever because every randomly generated
    // position is too close to some existing square
    let count = 0;
    while (flag && ++count < 1000) {
      flag = false;
      this.x = (width / grid) * floor((grid + 1 - m) * random());
      this.y = (height / grid) * floor((grid + 1 - m) * random());
      if (sqr.length) {
        // Check if the new square is too close to any existing squares
        for (let sq of sqr) {
          let d = (this.x - sq.x) ** 2 + (this.y - sq.y) ** 2;
          if (d < this.s ** 2 || d < sq.s ** 2) {
            flag = true;
            break;
          }
        }
      }
    }

    if (flag) {
      this.s = 0;
      print(`gave up after ${count} attempts to find a position for this square.`);
    }
  }

  show() {
    stroke(random(340), 80, 80);
    square(this.x, this.y, this.s);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

while 循环中的逻辑对我来说没有多大意义,所以如果您需要更多建议,您将不得不描述您实际尝试做的事情。