JS максимальный стек вызовов превышен P5 - PullRequest
3 голосов
/ 19 января 2020

Я пытаюсь создать программу для подсчета самых больших цветных связанных блоков в p5. js. Проблема заключается в том, что когда я рекурсивно вызываю соседние блоки, он выдает: «Превышен максимальный стек вызовов», и я знаю, что означает ошибку, но я не знаю, почему это происходит. Вот мой код:

class Box {
  constructor(id, x, y, w, h, col, colId) {
    this.id = id;
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.col = col;
    this.colId = colId;
  }

  render() {
    fill(this.col);
    stroke(1);
    rect(this.x * this.w, this.y * this.w, this.w, this.h);
  }

  getNeighbour(visited, x, y) {
    if(x - 1 < 0 || x + 1 >= rows || y - 1 < 0 || y + 1 >= cols) {
      return -1; 
    }
    else {
      this.col = color(10,10,10);
      arr[x-1][y].getNeighbour(visited,x-1,y);
      arr[x+1][y].getNeighbour(visited,x+1,y);
      arr[x][y-1].getNeighbour(visited,x,y-1);
      arr[x][y+1].getNeighbour(visited,x,y+1);
    }
    if(!this.contains(this.id)) {
      visited.push(this.id); 
    }
    
    
    
  }
  
  contains() {
    for(let i = 0; i < visited.length; i++) {
      if(this.id == visited[i]) return true; 
    }
    return false;
  }
}

Скажите, пожалуйста, где проблема. Я также попытался сделать проверку по одному. Сначала для левого соседа, и это работает как шарм. Но когда я добавляю правильный, эта ошибка появляется. Я думаю, что у меня есть подходящие случаи по умолчанию, которые встречаются, но реальность может отличаться.

Ответы [ 3 ]

2 голосов
/ 19 января 2020

Вместо:

else {
  this.col = color(10,10,10);
  arr[x-1][y].getNeighbour(visited,x-1,y);
  arr[x+1][y].getNeighbour(visited,x+1,y);
  arr[x][y-1].getNeighbour(visited,x,y-1);
  arr[x][y+1].getNeighbour(visited,x,y+1);
}
if(!this.contains(this.id)) {
  visited.push(this.id); 
}

try:

else if(!this.contains(this.id)) {
  visited.push(this.id);
  this.col = color(10,10,10);
  arr[x-1][y].getNeighbour(visited,x-1,y);
  arr[x+1][y].getNeighbour(visited,x+1,y);
  arr[x][y-1].getNeighbour(visited,x,y-1);
  arr[x][y+1].getNeighbour(visited,x,y+1);
}

Далее: я не уверен, что this.contains - это то, что нужно сделать, возможно, попробуйте: visited.contains...

2 голосов
/ 19 января 2020

Когда вы начинаете с коробки, она возвращается к коробке слева, справа, сверху и снизу. То же самое происходит с этими четырьмя коробками. Но если вы находитесь в поле выше и оно вызывает поле ниже, вы вернулись к тому, с чего начали. Это будет продолжаться до тех пор, пока ваш стек не закончится.

В зависимости от того, что вы пытаетесь сделать, простое решение состоит в том, чтобы выполнить проверку «содержит» и прервать, если ящик был посещен ранее:

getNeighbour(visited, x, y) {
    if( isOutsideBounds(x,y) || visited.indexOf(this.id) > -1) {
      return -1; 
    }
    this.col = color(10,10,10);
    visited.push(this.id)
    arr[x-1][y].getNeighbour(visited,x-1,y);
    arr[x+1][y].getNeighbour(visited,x+1,y);
    arr[x][y-1].getNeighbour(visited,x,y-1);
    arr[x][y+1].getNeighbour(visited,x,y+1); 
}  

Кроме того, похоже, что ваша функция contains() обращается к массиву visited, который находится вне области действия функции.

1 голос
/ 19 января 2020

Это абстрактный подход. Вы можете взять счетчик островов и посчитать предметы каждого острова.

function check(array) {

    function test(array, i, j, value) {
        if (array[i] && array[i][j] === -1) {
            count[value] = (count[value] || 0) + 1;
            array[i][j] = value;
            test(array, i - 1, j, value);
            test(array, i + 1, j, value);
            test(array, i, j - 1, value);
            test(array, i, j + 1, value);
            return true;
        }
    }
    
    var value = 1,
        count = {};

    array.forEach(a=> a.forEach((b, i, bb) => bb[i] = -b));
    array.forEach((a, i, aa) => a.forEach((b, j) => test(aa, i, j, value) && value++));
    array.map(a => console.log(...a));
    return count;
}

console.log(check([[1, 0, 1], [1, 0, 0], [1, 1, 1]]));
console.log(check([[1, 0, 1], [0, 1, 0], [1, 0, 1]]));
console.log(check([[1, 0, 0, 1, 1], [1, 1, 1, 0, 0], [0, 0, 1, 0, 1], [0, 0, 1, 0, 1], [1, 1, 1, 0, 1]]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
...