Sprawdzanie wygranej w grze kółko i krzyżyk w JavaScript

Teraz nadszedł czas, aby napisać kod, który będzie określał zwycięstwo i wyświetlał imię zwycięzcy.

Po przemyśleniu zadania, można dojść do wniosku, że sprawdzenie na obecność wygranej należy wykonywać w każdym ruchu:

javascriptfunction init(selector) {
  let cells = document.querySelectorAll('#field td');
  let i = 0;
  
  for (let cell of cells) {
    cell.addEventListener('click', function step() {
      this.textContent = ['X', 'O'][i % 2];
      this.removeEventListener('click', step);
      
      // tutaj powinniśmy sprawdzać wygraną lub remis
      
      i++;
    });
  }
}

Stwórzmy funkcję isVictory, która parametrem będzie przyjmować tablicę komórek i zwracać true, jeśli na planszy jest wygrana, i false, jeśli nie. Będziemy używać tej funkcji w następujący sposób:

javascriptfunction start(cells) {
  let i = 0;
  
  for (let cell of cells) {
    cell.addEventListener('click', function step() {
      this.textContent = ['X', 'O'][i % 2];
      this.removeEventListener('click', step);
      
      if (isVictory(cells)) {
        alert('imię zwycięzcy');
      }
      
      i++;
    });
  }
}

Jak mamy poznać imię zwycięzcy? Oczywiście, jego imię jest przechowywane w każdej ze zwycięskich komórek. Wyjaśniam: jeśli mamy wygraną, to oznacza to, że niektóre 3 komórki w poziomie, pionie lub po przekątnej zawierają identyczną wartość: albo krzyżyk, albo kółko.

Oczywiście, wartość dowolnej z tych komórek to imię zwycięzcy. Ale można pójść inną, mniej oczywistą drogą: ponieważ określamy obecność wygranej w każdym ruchu, to logiczne jest, że zwycięzcą będzie gracz, który wykonał ostatni ruch. Imię tego gracza jest zawarte w tekście klikniętej komórki:

javascriptfunction start(cells) {
  let i = 0;
  
  for (let cell of cells) {
    cell.addEventListener('click', function step() {
      this.textContent = ['X', 'O'][i % 2];
      this.removeEventListener('click', step);
      
      if (isVictory(cells)) {
        alert(this.textContent); // wyświetlamy imię zwycięzcy
      }
      
      i++;
    });
  }
}

Implementacja isVictory

Jak mamy technicznie określić obecność wygranej na planszy? Jeśli dobrze wszystko przemyśleć, można dojść do wniosku, że na planszy jest ograniczona liczba trójek komórek.

Oznacza to, że dla sprawdzenia wygranej można po prostu sprawdzić wszystkie te trójki. Należy sprawdzać, czy trójki mają identyczne niepuste wartości (czyli jest tam albo krzyżyk, albo kółko).

Stwórzmy dwuwymiarową tablicę, w każdej podtablicy której będą numery komórek jednej z trójek:

javascriptlet combs = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6],
];

Napiszmy za pomocą tej tablicy określenie wygranej:

javascriptfunction isVictory(cells) {
  let combs = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  for (let comb of combs) {
    if (
      cells[comb[0]].textContent == cells[comb[1]].textContent &&
      cells[comb[1]].textContent == cells[comb[2]].textContent &&
      cells[comb[0]].textContent != ''
    ) {
      return true;
    }
  }
  
  return false;
}
Задание 1

Samodzielnie, nie podglądając w mój kod, zaimplementuj opisane. Sprawdź, jak funkcjonuje proces gry.

Задание 2

Spróbuj zaimplementować sprawdzanie remisu. W następnej lekcji będzie omówienie tego miejsca.