Gra w życie

Gra w życie to przykład automatu komórkowego wymyślonego przez matematyka Johna Conwaya. Gra jest prowadzona w macierzy elementów, komórek. Każda z komórek może być żywa lub martwa. O stanie komórki w kolejnym etapie gry decyduje kilka zasad.

  • jeśli komórka jest martwa i ma dokładnie trzech sąsiadów żywych, staje się żywą
  • jeśli komórka jest żywa i ma dwóch lub trzech sąsiadów żywych, żyje dalej
  • jeśli komórka jest żywa i ma jednego lub mniej sąsiadów lub więcej niż trzech sąsiadów żywych, umiera (odpowiednio z samotności i przeludnienia).
Poniżej prosta implementacja Gry w życie. Podstawowym założeniem jest wykorzystanie macierzy przechowującej typ logiczny. Komórki żywe to elementy z wartościami true, a martwe z wartościami false. Po każdym etapie rozwoju wyświetlana jest plansza z aktualnym stanem naszej populacji komórek. Przejście do następnego etapu to naciśnięcie klawisza Enter, dowolny znak - koniec gry.
001.import java.util.Scanner;
002. 
003./**
004. * Prosta implementacja Gry w życie
005. * @author kodatnik.blogspot.com
006. */
007.public class GraWZycie {
008. 
009. // stałe symbolizujące żywą i martwą komórkę
010. private final char ZYWA = '#';
011. private final char MARTWA = '.';
012. // pola przechowujące rozmiar naszej planszy
013. private int wiersze;
014. private int kolumny;
015. // deklaracja macierzy z planszą gry
016. private boolean[][] plansza;
017. 
018. // konstruktor, podajemy liczbę wierszy i kolumn planszy
019. public GraWZycie(int wiersze, int kolumny) {
020.  // inicjalizujemy pola naszej klasy
021.  this.wiersze = wiersze;
022.  this.kolumny = kolumny;
023.  // tworzymy odpowiednią macierz, domyślnie wypełniona jest ona wartościami false
024.  plansza = new boolean[wiersze][kolumny];
025. }
026. 
027. // metoda pokazująca planszę na ekranie
028. public void pokazPlansze(){
029.  // wyświetlamy każdy element planszy, w zależności od zawartości na ekranie pojawi się odpowiedni znak
030.  for(boolean wiersz[] : plansza){
031.   for(boolean element : wiersz)
032.    System.out.print((element) ? ZYWA : MARTWA);
033.   System.out.println();
034.  }
035. }
036. 
037. // przykładowa metoda uzupełniająca planszę populacją początkową
038. public void utworzDaneTestowe() {
039.  // tworzymy populację początkową (standardowy Exploder)
040.  plansza[5][5] = true; plansza[5][7] = true; plansza[5][9] = true;
041.  plansza[6][5] = true; plansza[6][9] = true;
042.  plansza[7][5] = true; plansza[7][9] = true;
043.  plansza[8][5] = true; plansza[8][9] = true;
044.  plansza[9][5] = true; plansza[9][7] = true; plansza[9][9] = true;
045. }
046. 
047. // metoda zwraca liczbę żywych sąsiadów konkretnej komórki
048. // w wywołaniu podajemy współrzędne komórki
049. private int liczbaSasiadow(int x, int y) {
050. 
051.  // zmienna przechowująca liczbę sąsiadów
052.  int sasiedzi = 0;
053. 
054.  // sprawdzamy komórki na około naszej
055.  for(int i = x-1; i <= x+1; i++) {
056.   // jeżeli przekraczamy zakres planszy (wiersz) idziemy dalej
057.   if(i < 0 || i > wiersze-1) continue;
058.   for(int j = y-1; j <= y+1; j++) {
059.    // jeżeli przekraczamy zakres planszy (kolumna), lub jesteśmy w komórce(x,y) idziemy dalej
060.    if(j < 0 || j > kolumny-1 || (i == x && j == y)) continue;
061.    // jeśli sąsiad jest żywy to zwiększamy naszą zmienną
062.    if(plansza[i][j]) sasiedzi++;
063.   }
064.  }
065.  // zwracamy zmienną
066.  return sasiedzi;
067. }
068. 
069. // metoda sprawdza czy dana komórka będzie żywa czy też martwa w następnym etapie
070. // w wywołaniu podajemy współrzędne komórki
071. private boolean ewolucja(int x, int y) {
072. 
073.  // sprawdzamy liczbę żywych sąsiadów
074.  int sasiedzi = liczbaSasiadow(x, y);
075. 
076.  // jeżeli nasza komórka jest żywa
077.  if(plansza[x][y]) {
078.   // jeśli liczba sąsiadów jest mniejsza lub równa jeden lub większa od trzech to nasza komórka będzie martwa
079.   if(sasiedzi <= 1 || sasiedzi > 3) return false;
080.   // jeśli liczba sąsiadów jest równa trzy lub dwa to nasza komórka będzie żywa
081.   if(sasiedzi == 3 || sasiedzi == 2) return true;
082.  } else {
083.   // jeśli nasza komórka jest martwa i ma dokładnie trzech żywych sąsiadów to będzie żyła
084.   if(sasiedzi == 3) return true;
085.  }
086.  // w każdym innym przypadku zwracamy fałsz (komórka jest martwa)
087.  return false;
088. }
089. 
090. // metoda tworzy następną populację/pokolenie komórek
091. public void nastepnePokolenie() {
092.  // tworzymy planszę tymczasową o takim samy rozmiarze jak nasza
093.  boolean[][] planszaTymczasowa = new boolean[wiersze][kolumny];
094. 
095.  // uzupełniamy nową planszę wartościami na podstawie ogólnych zasad
096.  for(int i = 0; i < wiersze; i++)
097.   for(int j = 0; j < kolumny; j++)
098.    planszaTymczasowa[i][j] = ewolucja(i, j);
099. 
100.  // nasza główna plansza staje się planszą tymczasową
101.  plansza = planszaTymczasowa;
102. }
103. 
104. public static void main(String[] args) {
105. 
106.  // wyświetlamy napisy informacyjne
107.  System.out.println("Gra w życie - [Enter] generuje następne pokolenie, dowolny znak i [Enter] kończy grę.");
108. 
109.  // obsługujemy wejście
110.  Scanner sc = new Scanner(System.in);
111. 
112.  // tworzymy nowy obiekt przekazując do konstruktora rozmiar planszy
113.  GraWZycie gra = new GraWZycie(15, 15);
114.  // wypełniamy naszą planszę wartościami testowymi
115.  gra.utworzDaneTestowe();
116.  // wyświetlamy planszę na ekranie
117.  gra.pokazPlansze();
118. 
119.  // dopóki użytkownik będzie naciskał klawisz Enter
120.  while(sc.nextLine().equals("")) {
121.   // generujemy następne pokolenie
122.   gra.nastepnePokolenie();
123.   // wyświetlamy go na ekranie
124.   gra.pokazPlansze();
125.  }
126. }
127.}
Pojawianie się następnych etapów naszej populacji może odbywać się automatycznie (bez konieczności naciskania klawisza Enter). Poniżej zmodyfikowana wersja pętli while z metody main. Mankamentem tego rozwiązania jest to, iż zakończenie programu odbywa się jedynie poprzez jego przerwanie np. za pomocą kombinacji Ctrl+C.
1.while(true) {
2. gra.nastepnePokolenie();
3. gra.pokazPlansze();
4. try {
5.  Thread.sleep(300); // długość pauzy w milisekundach
6. } catch (Exception e) {}
7.}
Uruchomiona aplikacja, początkowa populacja:
Gra w życie - [Enter] generuje następne pokolenie, dowolny znak i [Enter] kończy grę.
...............
...............
...............
...............
...............
.....#.#.#.....
.....#...#.....
.....#...#.....
.....#...#.....
.....#.#.#.....
...............
...............
...............
...............
...............
Populacja w następnych etapach:
...............
...............
...............
...............
...............
......#.#......
....##...##....
....###.###....
....##...##....
......#.#......
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
.....#...#.....
....#.....#....
...#..#.#..#...
....#.....#....
.....#...#.....
...............
...............
...............
...............
...............
Gra wygląda znacznie lepiej w środowisku graficznym ;)


4 Komentarze - Gra w życie

programowanie java, c++, pascal pisze...

Pierwszy raz widze gre w zycie w konsoli ;) ale dobra robota

Najlepszekasyno pisze...

To jest interesująco zobaczyć grę od strony programowania.

Tomek pisze...

Najwięcej frajdy i zabawy daje granie na konsoli. Takie jest moje zdanie, jeśli chodzi o gry. Tutaj gry mają zdecydowanie lepszą grafikę i dają sporo możliwości graczom. Konsola jest w stanie zapewnić długi godziny fajnej rozrywki. Sprawdzi się na samotne wieczory, ale też i przy okazji na jakieś fajne zabawy i spotkania z przyjaciółki. Możecie sprawdzić sobie różne oferty na stronie https://4console.pl/ , więc zdecydowanie szukajcie i sprawdzajcie, jeśli tylko macie możliwość. Na pewno znajdziecie coś fajnego dla siebie.

obiady domowe z dostawą Międzyrzecz pisze...

zycie to nie gra

Prześlij komentarz

Możesz użyć niektórych tagów HTML, takich jak <b>, <i>, <u>, <a> Nie spamuj :)

Popularne posty