Liczenie potrójnych elementów w rzędach i wierszach tablicy

0

Cześć

Mam dwuwymiarową tablicę taką jak tu (tylko większą):

const gameArr = [
[{},{}],
[{},{}]
]

Każdy obiekt w tablicy ma parametr name który jest stringiem.

Potrzebuję napisać funkcje, która, jeśli w rzędzie lub kolumnie wystąpi obok siebie trzy lub więcej obiektów z takim samym parametrem name -
zwróci tablicę zawierającą położenia tych obiektówów np:

[[2,0], [3,0],[4,0],[1,1],[1,2],[1,3],[1,4]]

Stworzyłem funkcje która ma za zadanie to robić
ale jest mało czytelna i nie działa :-) :

function findMachingElements() {
  let counter = 0;
  let currentType = "";
  let machingElements = [];
  let currentElements = [];

  function checkElement(x, y) {
    const element = gameArr[x][y];
    const name = element["name"];
    if (currentType === name) {
      counter = counter++;
      currentElements.push([x, y]);
    } else {
      checkIfTriple();
      counter = 1;
      currentType = name;
    }
  }
  function checkIfTriple() {
    if (counter >= 3) {
      machingElements.concat(currentElements);
      currentElements = [];
    }
  }

  // columns
  gameArr.forEach((row, x) => {
    row.forEach((element, y) => {
      checkElement(x, y);
    });
  });
  checkIfTriple();
  // rows
  for (let y = 0; y < gameArr.length; y++) {
    for (let x = 0; x < gameArr.length; x++) {
      checkElement(x, y);
    }
  }
  checkIfTriple();
  return machingElements;
}

Bardzo proszę o pomoc !

0

Dla uściślenia, czy coś takiego to też się liczy jako trafienie (a):

a a b
a c d
e f g

?

Edit:
Przydałby sie też kontekst, do czego to ma służyć? Od tego może zależeć rozwiązanie (np czy cała tablica musi byc przeliczana czy tylko obszar, w który użytkwonik kliknął).

0

Nie. To się nie liczy. Wiersze osobno, kolumny osobno.
Co do kontekstu: Chcę zrobić własną interpretacje tej gry: https://candycrushsoda.co/ :D
Edit:
A taki w takim przypadku funkcja powinna zwrócić tylko trzy punkty:

a b a
b b b
a a b

Edit2:
Przy pierwszym uruchomieniu cała plansza powinna zostać przeliczona.

Później konieczne jest przeliczenie tylko tych trzech pasów które uległy zmianie przy interakcji użytkownika.
Ale nie wiem jak to zrobić w ramach jedniej funkcji :D
Do przeliczenia jest max 100 obiektów więc kwestia optymalizacji nie jest tu bardzo istotna.

Edit3:
Później konieczne jest przeliczenie tylko tych trzech pasów które uległy zmianie przy interakcji użytkownika.
Jeśli użytkownik trafi to po wylosowaniu nowych cukierków będzie znowu koniecznieczne przeliczenie większej ilości kolumn i wierszy
(niekoniecznie wszystich)
Zagraj sobie to zobaczysz o co mi chodzi. :D

1

Tu masz prosty sposób - przejście po wierszach i kolumnach osobno - mało optymalne ale proste:

const board = [
  [{ name: "a" }, { name: "a" }, { name: "a" }, { name: "b" }],
  [{ name: "a" }, { name: "b" }, { name: "a" }, { name: "b" }],
  [{ name: "b" }, { name: "b" }, { name: "b" }, { name: "b" }],
  [{ name: "a" }, { name: "a" }, { name: "b" }, { name: "b" }],
]

const findMatchingElements = (board) => {
  const height = board.length
  const width = board[0].length
  const matches = []
  let prev = null

  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const item = board[y][x]

      if (item.name === prev) {
        matches[matches.length - 1].push([x, y])
      } else {
        matches.push([[x, y]])
        prev = item.name
      }
    }

    prev = null
  }

  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      const item = board[y][x]

      if (item.name === prev) {
        matches[matches.length - 1].push([x, y])
      } else {
        matches.push([[x, y]])
        prev = item.name
      }
    }

    prev = null
  }

  return matches.filter((match) => match.length >= 3)
}

console.log(findMatchingElements(board))

/* Result:
[
  [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ],
  [ [ 0, 2 ], [ 1, 2 ], [ 2, 2 ], [ 3, 2 ] ],
  [ [ 3, 0 ], [ 3, 1 ], [ 3, 2 ], [ 3, 3 ] ]
]
*/

CodePen: https://codepen.io/caderek/pen/qBOrwgY?editors=0012

Możez sobie to zrefaktorować żeby było bardziej DRY, ale wydajnościowo powinno wystarczyć (dla losowej planszy 10x10 na moim średniej klasy laptopie zajmuje to ok 1ms -> https://codepen.io/caderek/pen/qBOreVV?editors=0010).

0

Wspaniale działa!
Wielkie dzięki.

Przy okazji chciałbym się jeszcze o coś dopytać:

gdy w webpacku użyję zapisu:

export const findMatchingElements = (board) => {}

to wyskakuje błąd: Object(...) is not a function. Gdy zadeklaruje to za pomocą function działa dobrze.
Czy wiesz czemu tak się dzieje?

1 użytkowników online, w tym zalogowanych: 0, gości: 1