1
votes

JavaScript: Démineur à matrice 2D accédant aux voisins à + = 1 eux

J'ai donc un tableau 2D d'entrée avec des mines déjà placées dedans:

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

Ce que je dois faire c'est de sortir un tableau 2D modifié avec un nombre ajouté aux voisins, mais je ne savoir comment puis-je y accéder avec élégance.

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?
      }
    }
  }
}

Le résultat devrait ressembler à ceci:

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

Un conseil? Merci.


0 commentaires

4 Réponses :


1
votes
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
           }
        }
      }
    }
  }
}
I will explain briefly the logic:On arrays dx and dy, you store the distance in rows and columns you need to move from a given cell to reach all 8 neighbors.For example, take the dx[2] = 1 and dy[2] = -1 this means to reach this neighbor 2 you need to move 1 column to the right +1 and one row below -1.The if is to check wether the given neighbor exists within the limits of the array.

0 commentaires

0
votes

Pas la solution la plus élégante

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);


0 commentaires

1
votes

Vous pouvez utiliser une carte imbriquée double pour obtenir chaque élément, puis vous pouvez créer une autre fonction qui prendra l'index actuel de la ligne et de la colonne et vérifier la fermeture * de chaque élément.

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)


0 commentaires

2
votes

Vous pouvez obtenir un tableau de décalages pour obtenir les bons indices et vérifier si la valeur est une étoile.

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(' ')));


0 commentaires