Like

Jeśli ktoś bawił się komputerem w latach 80. czy 90. to może tą grę pamiętać. Albo jeśli ktoś w tych latach spod stołu oglądał co tam klika tata na ZX Spectrum czy Atari. To jest gra na zero graczy stworzona w 1970 roku.

Szeroki opis (który mnie wciągnął bez pamięci) znajdziecie w wikipedii.

Zero graczy oznacza, że wpisujemy tylko parametry, a gra się toczy sama. Grafika jest skrajnie prosta i zasady też.

Reguły gry według Conwaya

Tworzymy sieć kwadratów – komórek. Komórki mogą być żywe lub martwe.

  • Martwa komórka, która ma dokładnie 3 żywych sąsiadów, staje się żywa w następnej jednostce czasu (rodzi się).
  • Żywa komórka z 2 albo 3 żywymi sąsiadami pozostaje nadal żywa; przy innej liczbie sąsiadów umiera (z „samotności” albo „zatłoczenia”).

Okazuje się, że struktura którą otrzymujemy wcale nie jest trwała, a zmienia się dynamicznie, ewoluuje. Czasem wszystkie komórki “zdychają” bardzo szybko, a czasem wędrują, oscylują. Ćwiczenie, które zrobimy w środowisku arkuszy będzie bardzo proste. Ale jeśli Wam się spodoba – możecie śmiało eksperymentować dalej.

Przykład zaawansowanej struktury zwanej Breederem (autor: Protious , pobrane z wikipedii)

Gra w Życie w Arkuszu Google

Zaczynamy od stworzenia planszy na której umieścimy ręcznie komórki żywe i martwe. To będzie pierwsza klatka naszego filmu. Plik roboczy został udostępniony tutaj. Możecie się nim bawić jeśli zrobicie sobie własną kopię (Menu Plik –> Utwórz kopię)

Podstawowa plansza wykonana ręcznie

Czarne prostokąty znalazłem w tablicy znaków. Skopiowałem i wkleiłem. Ale możecie w tym miejscu użyć jakiegoś innego znaku.

Następnym krokiem jest zrobienie drugiej tablicy, która będzie kolejną klatką “filmu”. Czyli będzie zawierała tablicę przetworzoną według zasad gry (odpowiednie komórki obumrą, inne się rozmnożą, etc.).

Po lewej źródłowa tabela, a po prawej tabela która będzie “reagować”. Zgrupowałem kolumny X do AU (Menu Dane –>Grupuj), żeby mi było później łatwo schować tą tabelę. Docelowo będzie niewidoczna.

Opisanie zasad przy pomocy formuł

Przypominam zasady i opisuję je za pomocą funkcji SWITCH:

  • Martwa komórka, która ma dokładnie 3 żywych sąsiadów, staje się żywa w następnej jednostce czasu (rodzi się).
  • Żywa komórka z 2 albo 3 żywymi sąsiadami pozostaje nadal żywa; przy innej liczbie sąsiadów umiera (z „samotności” albo „zatłoczenia”).

SWITCH to funkcja nieco podobna do klasycznego IF (JEŻELI), ale mogąca rozpatrywać wiele przypadków.

Składnia:

SWITCH ( Wyrażenie ; przypadek 1; wartość 1; przypadek 2; wartość 2; przypadek 3.... ; wartość 3...; wartość domyślna)

  • Wyrażenie: tutaj musimy wybrać wszystkie komórki otaczające komórkę “badaną” i policzyć ile z nich jest żywych. Zatem “wyrażenie” to będzie podliczenie 8 komórek wokół badanej.
  • przypadek 1; wartość 1; – Tutaj ustalamy jakie wartości mają być w komórce w zależności od tego jaki wynik dało zliczanie sąsiadów. wartość będzie zatem oznaczać obecność komórki (czarny prostokąt) lub jej brak (pusta komórka).
  • wartość domyślna – to wartość, którą przybierze komórka jeśli żaden z wcześniejszych warunków nie zostanie spełniony.

Zacznijmy więc od naszego wyrażenia zliczającego ile pól dookoła zawiera żywą komórkę (czarny prostokąt).

Formułę wpisujemy w nowej tabeli. Zatem, żeby określić jaki będzie stan komórki w następnym pokoleniu (czyli w tej nowej tabeli), musimy sprawdzić ilu miała sąsiadów. Do tego używamy funkcji COUNTIF (LICZ.JEŻELI):

countif({B3;B4;B5;C3;C5;D3;D4;D5};"█")

Robimy tu w zapisie klamrowym listę wszystkich komórek dookoła C4. Funkcja COUNTIF podaje liczbę komórek zawierających █.

Zatem cała nasza funkcja będzie wyglądać tak:

=SWITCH(countif({B3;B4;B5;C3;C5;D3;D4;D5};"█");
3;"█"

;2; if(C4="█";"█";"")
;"")

Już tłumaczę o co chodzi:

Funkcja Switch i Countif – klucz do naszego zadania.

Następnie kopiujemy formułę do wszystkich komórek nowej tabeli. Od tego momentu, cokolwiek zmienimy w “Tabeli aktualnej”, “Tabela nowa” pokaże nam nowe pokolenie. Najlepiej kopiować i wklejać te prostokąty by zobaczyć co się dzieje.

Niestety w ten sposób uzyskujemy tylko dwa pokolenia i potrzebujemy aż dwóch tabel. Więc trzeba jeszcze trochę namieszać, żeby przenieść zawartość nowego pokolenia “Tabela nowa” i zacząć kolejną przemianę pokoleń.

Wprowadzenie do skryptów

Możemy to zrobić “z palca”, używając poleceń Kopiuj / Wklej wartości. W ten sposób teoretycznie możemy ręcznie przeprowadzić ewolucję naszego stadka komórek, ale będzie to bardzo pracochłonne. Potrzebujemy więc zbudować automat, który będzie nam kopiował zawartość “Tabeli nowej” do “Tabeli aktualnej” tyle razy ile chcemy.

Google Sheets zawiera edytor skryptów

Ten blog nie ma na celu zapoznawania ze skryptami, ale problem “Gry w Życie” wydał się na tyle ciekawy, że zrobię wyjątek. Edytor znajduje się w menu Narzędzia. Skrypty piszemy w języku Google Apps Script, który jest odmianą Javascriptu z dodanymi elementami charakterystycznymi pakietu Google. To potężne narzędzie pozwalające łączyć arkusze z Kalendarzem, z Dokumentami, z Gmailem i wieloma innymi elementami ekosystemu.

Każdy nowy skrypt przed pierwszym uruchomieniem wymaga potwierdzenia, że się zgadzamy na jego odpalenie (potencjalnie mogą zawierać szkodliwy kod, który np. wyłudzi dane, którymi wolelibyśmy się nie dzielić). Zatem warto dwa razy się zastanowić zanim odpali się skrypt z nieznanego źródła.

Użycie skrytptu do stworzenia rund i animacji

Poniższy skrypt to zaledwie kilka linijek. Możesz go uruchomić w swojej kopii pliku. Możesz go też modyfikować. Postarałem się jak najdokładniej opisać poszczególne komendy, natomiast nie jest moim celem opisywanie całej składni Javascriptu i Google Apps Scriptu.

Żeby móc sterować symulacją, wprowadzam ograniczenie ilości “pokoleń” oraz wskaźnik, który będzie nas informował, które “pokolenie” jest aktualnie wyświetlanie.

Komórki C29 i H29 podają informacje ile pokoleń ma trwać symulacja i które pokolenie jest wyświetlane teraz. Te dane pobierze sobie skrypt.
function kopiujtabele() {  // tu definiuję nazwę funkcji i otwieram klamrę funkcji.
  var arkusz = SpreadsheetApp.getActive(); // Definiuję zmienną arkusz, 
                                           // która jest aktywnym arkuszem w aplikacji Arkusze Google
  var liczbacykli = arkusz.getRange('C29').getValue(); // Z komórki C29 pobieram liczbę cykli (pokoleń), 
                                                       //które mają być wykonane
  
  for (i=0 ; i<liczbacykli ; i++){    // Zaczynam pętlę, która dla zmiennej i od 0 do 
                                      // liczby cykli wykona operacje z następnych 3 linii kodu.
 
    var tabela = arkusz.getRange('AA3:AU23').getValues();  //Pobieram wartości 
                                                           //komórek AA3:AU23 (czyli cała Nowa tabela)
                                                           //opisuję je jako zmienna 'tabela'.

    arkusz.getRange('B3:V23').setValues(tabela); // wWpisuję pobrane wartości do komórek B3:V23 
                                                 // (czyli do tabeli aktualnej)
 
    arkusz.getRange('h29').setValue(i);          // W komórce h29 podaję który cykl jest wykonywany.
    };   // Zamykam klamrę pętli.

} // Zamykam klamrę funkcji.


Na koniec chowam Tabelę nową (zamykam utworzoną wcześniej grupę) i dorabiam przycisk który będzie uruchamiał symulację.

Wybieram z menu Wstaw —> Rysunek
Gryzmolę jakiś przycisk, który będzie odpalał symulację…
Klikam prawym klawiszem w rysunek i wybieram opcję przypisywania skryptu. Nazwa mojego skryptu to: kopiujtabele.
Naciskam lewym klawiszem na przycisk i patrzę jak symulacja się rozwija.
Tutaj mamy gotową przykładową animację.

Przykład szaleństwa w Grze w Życie (video)

Jeśli powyższe ćwiczenie wydało się Wam mało spektakularne, to spójrzcie jak wyglądają owoce rozważań Conwaya po 50 latach ewolucji i kombinacji ludzi z całego świata.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.