background image

 

Projekt Palec Boży 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Inżynieria Biomedyczna 
Sztuczna Inteligencja 
Piotr Gacek 
Maciej Niewiński 

 
 
 
 
 
 
 
 
 

background image

"Gra w życie " to gra zero-gracz , co oznacza, że jego ewolucja zależy od stanu 
początkowego, nie wymaga dalszego wkładu.Komunikacja z Game of Life, tworząc 
konfigurację początkową i obserwowanie jej rozwoju lub dla zaawansowanych 
graczy, tworząc wzory o szczególnych właściwościach. 
Życie została wymyślona przez matematyka Johna Conwaya w 1970 roku wybrać 
zasady ostrożnie po wypróbowaniu wielu innych możliwości, z których niektóre 
spowodowane komórki umrzeć zbyt szybko i innych, które spowodowane zbyt 
wiele komórek urodzić. Życie równoważy te tendencje, co trudno powiedzieć, czy 
wzór wymrze całkowicie, tworząc stabilną populację, lub rosną wiecznie. 
Niektóre z najbardziej popularnych obiektów w życiu pozostają takie same z etapu 
na etap. Brak żywe komórki umierają i rodzą się żadne nowe komórki. Conway, 
który lubi co kalambury, nazywa ten rodzaj obiektu a "martwej natury". Można 
zaobserwować kilka z tych przedmiotów, uruchamiając R-Pentomino w aplecie. Do 
obiektu jest martwa natura, każda komórka na żywo większość ma 2 lub ​

3 żywo 

sąsiadów, a co martwe komórki może mieć dowolną liczbę sąsiadów z wyjątkiem 
3.Zasady te mogą ulec zmianie w każdym momencie programowania poprzez 
zmianę zakresu sąsiadów. 
Najczęstszym życie wciąż jest nazywany bloku. To jest po prostu kwadrat 2x2 
żywych komórek: 

 

Przekonasz się, że pojawia się wiele razy, jak uruchomić R-Pentomino.Każda 
komórka na żywo ma dokładnie trzy sąsiadów, ale nie martwa komórka ma więcej 
niż dwóch sąsiadów. 
Niektóre inne martwe natury można zobaczyć są: 

 

 

ul 

 

 

łódź 

  statek 

  bochenek 

stnieją pewne wczesne odkrycia, które nie pojawiają się w R-Pentomino, ale które 
czasami pojawiają się od przypadkowych stanów wyjściowych. 
Prostopadłych statki kosmiczne w lewo, w prawo, w górę lub w dół, a nie na 
przekątnych jak szybowce. Są to znacznie mniej powszechne niż szybowców, ale 
bardzo ważne w niektórych rodzajów wzorów. Są one dostępne w trzech 
rozmiarach: 

background image

waga 

waga 
średnia 

waga 
ciężka 

Wreszcie, oto kilka prostych wzorów, które rozwijają się w wyjściowych 
oscylatorów. Wiersz 10 żywych komórek staje się oscylator okres-15 o nazwie 
pentadecathlon: 

 

Poniższy wzór staje się bardzo ładna okres-3 oscylatora nazywa pulsar: 

 

 
 

Kod 

 
// SPACJA AKTYWUJE MOŻLIWOŚC WPROWADZANIA ZNAKÓW  
// PONOWNE KLIKNIĘCIE SPACJI ZAŁĄCZENIE PROGRAMU 
// R - RESTART PROGRAMU 
// C - CZYSZCZENIE POWIERZCHNI PRACY  
int cellSize = 5; 
 
 
// zmienne dla zegara 
int interval = 100; 
int lastRecordedTime = 0; 
 
//kolor komórki żywa /martwa 
color alive = color(0, 200, 0); 
color dead = color(0); 

background image

 
 
// macierz komórek 
int[][] cells;  
// Buffor do rejestrowania stanu komórek  i użycia w tego podczas zmiany 
pozostałych w iteracjach   
int[][] cellsBuffer;  
 
//przerwa 
boolean pause = false; 
 
void setup() { 
  size (640, 360); 
 
  
  // Tworzenie instancji macierzy 
  cells = new int[width/cellSize][height/cellSize]; 
  cellsBuffer = new int[width/cellSize][height/cellSize]; 
 
  // Ta kreska będzie rysować kreske tła 
  stroke(48); 
 
  noSmooth(); 
 
   
  // Inicjacja komórek  
  for (int x=0; x<width/cellSize; x++) { 
    for (int y=0; y<height/cellSize; y++) { 
      float state = random (100); 
 

 

      cells[x][y] = int(state);  //Zapisanie stanu każdej komórki  
    } 
  } 
  background(0); //Wypełnienie  czarnym kolorem gdykomórki nie pokryją całego 
tła   

 
 
void draw() { 
 
   
  // Rysowanie siatki 
  for (int x=0; x<width/cellSize; x++) { 

background image

    for (int y=0; y<height/cellSize; y++) { 
      if (cells[x][y]==1) { 
        fill(alive); //Jeśli żyje  
      } 
      else { 
        fill(dead); // Jeśli umrze  
      } 
      rect (x*cellSize, y*cellSize, cellSize, cellSize); 
    } 
  } 
  // Powtórz jeśli zegar tyka 
  if (millis()-lastRecordedTime>interval) { 
    if (!pause) { 
      iteration(); 
      lastRecordedTime = millis(); 
    } 
  } 
 
  // Stwórz ręcznie komórki podczas pauzy  
  if (pause && mousePressed) { 
    //Mapuj i unikaj pozagranicznych błędów  
    int xCellOver = int(map(mouseX, 0, width, 0, width/cellSize)); 
    xCellOver = constrain(xCellOver, 0, width/cellSize-1); 
    int yCellOver = int(map(mouseY, 0, height, 0, height/cellSize)); 
    yCellOver = constrain(yCellOver, 0, height/cellSize-1); 
 
    //Sprawdź czy komórka jest w buforze  
    if (cellsBuffer[xCellOver][yCellOver]==1) { // komórka żywa  
      cells[xCellOver][yCellOver]=0; // Zabij 
      fill(dead); // Wypełnij kolorem oznaczającym śmierć  
    } 
    else { // Komórka martwa 
      cells[xCellOver][yCellOver]=1; // Ożyw 
      fill(alive); // Wypełnij kolorem oznaczającym życie   
    } 
  }  
  else if (pause && !mousePressed) { // Bufforowanie po kliknięciu myszki 
    // Zapisz stan komórek ( możliwośc operacji na 1 macierzy by utrzymać resztę 
w porządku )  
    for (int x=0; x<width/cellSize; x++) { 
      for (int y=0; y<height/cellSize; y++) { 
        cellsBuffer[x][y] = cells[x][y]; 
      } 

background image

    } 
  } 

 
 
 
void iteration() { // Kiedy zegar tyka  
 // Zapisz stan komórek ( możliwośc operacji na 1 macierzy by utrzymać resztę w 
porządku )  
  for (int x=0; x<width/cellSize; x++) { 
    for (int y=0; y<height/cellSize; y++) { 
      cellsBuffer[x][y] = cells[x][y]; 
    } 
  } 
 
  // Odwiedź każdą komórkę  
  for (int x=0; x<width/cellSize; x++) { 
    for (int y=0; y<height/cellSize; y++) { 
      // Odwiedź każdego sąsiada komórki  
      int neighbours = 0; //Policzymy sąsiadów  
      for (int xx=x-1; xx<=x+1;xx++) { 
        for (int yy=y-1; yy<=y+1;yy++) {   
          if (((xx>=0)&&(xx<width/cellSize))&&((yy>=0)&&(yy<height/cellSize))) { 
// Upewnij się że nie jesteś poza graniami  
            if (!((xx==x)&&(yy==y))) { // Upewnij się że to sprawdziłeś  
              if (cellsBuffer[xx][yy]==1){ 
                neighbours ++; // Sprawdź żywych sąsiadów i policz  
              } 
            }  
          }  
        }  
      }  
      //Zasady gry  
 

 

      if (cellsBuffer[x][y]==1) { // Komórka żywa zabij jeśli jest to konieczne  
        if (neighbours < 2 || neighbours > 3) { 
          cells[x][y] = 0; // Umrzyj jeśli nie ma 2 lub 3 sąsiadów  
        } 
      }  
      else { // Komórka martwa jeśli to konieczne   
        if (neighbours == 3 ) { 
          cells[x][y] = 1; // Tylko jeśli ma 3 sąsiadów  
        } 

background image

      }  
    }  
  }  
}  
 
void keyPressed() { 
  if (key=='r' || key == 'R') { 
    // Restart: ponowna inicjalizacja komórek  
    for (int x=0; x<width/cellSize; x++) { 
      for (int y=0; y<height/cellSize; y++) { 
        float state = random (100); 
 

 

        cells[x][y] = int(state); // Zapisz stan każdej  
      } 
    } 
  } 
  if (key==' ') { // Włącz/wyłącz pauze  
    pause = !pause; 
  } 
  if (key=='c' || key == 'C') { // Wyczyść wszystko 
    for (int x=0; x<width/cellSize; x++) { 
      for (int y=0; y<height/cellSize; y++) { 
        cells[x][y] = 0; // Wyzeruj wszystko  
      } 
    } 
  } 

 

background image

Krok 1. Nie zapełniona komórkami przestrzeń. 
 
 
 
 

 

Krok 2. Przestrzeń zapełniona komórkami przez użytkownika. Jest to pierwsze 
pokolenie. 

background image

 

Krok3. Użytkownik włącza algorytm symulujący “naturalne życie” kolejnych 
pokoleń. Komórki łączą się, dają nowe komórki, te które nie spełniają warunków 
przeżycia giną.  
 
 
 
 
 
 

background image

 

Krok 4.Ostatnie pokolenia. Pozostały już tylko żywe grupy które spełniają 
wymagane warunki. Skupiska tych komórek mają kształt Okręgów lub krzyży na 
zdjęciu. Reszta komórek jest martwa.  
 
 
 
 
 
 
 
 
 
Bibliografia 
The Nature of Code, Daniel Shiffman,

Magic Book Project

, 2012 

http://www.math.com/students/wonders/life/life.html

 ( stan na 21.01.2015) 

https://processing.org/

 (stan na 21.01.2015)