Projekt Palec Boży
Inżynieria Biomedyczna
Sztuczna Inteligencja
Piotr Gacek
Maciej Niewiński
"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:
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);
// 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++) {
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];
}
}
}
}
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
}
}
}
}
}
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
}
}
}
}
Krok 1. Nie zapełniona komórkami przestrzeń.
Krok 2. Przestrzeń zapełniona komórkami przez użytkownika. Jest to pierwsze
pokolenie.
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ą.
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,
, 2012