JavaScript: 2D Array Minesweeper обращается к соседям + = 1 им - PullRequest
1 голос
/ 17 июня 2020

Итак, у меня есть входной 2D-массив с уже размещенными в нем минами:

const input = [
  [0, 0, '*'],
  ['*', 0, 0],
  [0, '*', 0]
];

Что мне нужно сделать, чтобы вывести измененный 2D-массив с добавленным номером для соседей, но я не знаю, как могу ли я элегантно получить к ним доступ.

const mineSweeper = (input) => {
  for (let row = 0; row < input.length; row++) {
    for (let col = 0; col < input[row].length; col++) {
      if (input[row][col] === '*') {
        // How can I access neighbors from here elegantly?
      }
    }
  }
}

Результат должен выглядеть так:

const output = [
  [1, 2, '*'],
  ['*', 3, 2],
  [2, '*', 1]
];

Есть подсказка? Спасибо.

Ответы [ 4 ]

2 голосов
/ 17 июня 2020

Вы можете получить массив смещений для получения правильных индексов и проверить, является ли значение звездочкой.

const
    getCount = (array, x, y) => offsets
        .reduce((c, [i, j]) => c + (array[x + i]?.[y + j] === '*'), 0),
    offsets = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]],
    input = [[0, 0, '*'], ['*', 0, 0], [0, '*', 0]],
    result = input.map((row, i, a) => row.map((v, j) => v || getCount(a, i, j)));

result.forEach(a => console.log(a.join(' ')));
1 голос
/ 17 июня 2020

Вы можете использовать двойное вложенное map для получения каждого элемента, а затем вы можете создать другую функцию, которая будет принимать текущий индекс строки и столбца и проверять закрытие * каждого элемента.

const input = [
  [0, 0, '*'],
  ['*', 0, 0],
  [0, '*', 0]
]

function count(data, i, j) {
  let c = 0;

  const prevRow = data[i - 1];
  const currentRow = data[i]
  const nextRow = data[i + 1];

  [prevRow, currentRow, nextRow].forEach(row => {
    if (row) {
      if (row[j - 1] == '*') c++;
      if (row[j] == '*') c++;
      if (row[j + 1] == '*') c++;
    }
  })

  return c;
}

function update(data) {
  return data.map((a, i) => {
    return a.map((b, j) => {
      return b == '*' ? b : count(data, i, j)
    })
  })
}

const result = update(input)
console.log(result)
1 голос
/ 17 июня 2020
const dx = [1, 1, 1, 0, 0, -1, -1, -1];
const dy = [1, 0, -1, 1, -1, 1, 0, -1];
const mineSweeper = (input) => {
  for (let row = 0; row < input.length; row++) {
    for (let col = 0; col < input[row].length; col++) {
      if (input[row][col] === '*') {
        for (let i = 0 ; i < 8 ; i++) {
           let nr = row + dy[i], nc = col + dx[i];
           //check that is within the limits
           if (nr >= 0 && nr < input.length && nc >= 0 && nc < input[row].length) {
             input[nr][nc]++; //Do what you need with this neighbor
           }
        }
      }
    }
  }
}

Я вкратце объясню логику c:

В массивах dx и dy вы сохраняете расстояние в строках и столбцах, которое вам нужно переместить из данной ячейки, чтобы достичь всех 8 соседей.

Например, возьмите dx[2] = 1 и dy[2] = -1, это означает, что для достижения этого соседа 2 вам нужно переместить 1 столбец вправо +1 и одну строку ниже -1.

Здесь нужно проверить, существует ли данный сосед в пределах массива.

0 голосов
/ 17 июня 2020

Не самое элегантное решение

const input = [
    [0, 0, '*'],
    ['*', 0, 0],
    [0, '*', 0],
];

const mineSweeper = input => {
    for (let row = 0; row < input.length; row++) {
        for (let col = 0; col < input[row].length; col++) {
            if (input[row][col] === '*') {
                Number.isInteger(input[row - 1] && input[row - 1][col]) && input[row - 1][col]++;
                Number.isInteger(input[row] && input[row][col - 1]) && input[row][col - 1]++;
                Number.isInteger(input[row + 1] && input[row + 1][col]) && input[row + 1][col]++;
                Number.isInteger(input[row] && input[row][col + 1]) && input[row][col + 1]++;
                Number.isInteger(input[row - 1] && input[row - 1][col - 1]) && input[row - 1][col - 1]++;
                Number.isInteger(input[row + 1] && input[row + 1][col + 1]) && input[row + 1][col + 1]++;
                Number.isInteger(input[row - 1] && input[row - 1][col + 1]) && input[row - 1][col + 1]++;
                Number.isInteger(input[row + 1] && input[row + 1][col - 1]) && input[row + 1][col - 1]++;
            }
        }
    }
};

mineSweeper(input);

console.log(input);
...