Pomoce:

Biblioteka procedur obsługi konsoli znakowej - newconio


Gra LIFE

Gra w Życie (ang. Game of Life) została wynaleziona około roku 1970 przez Johna Conwaya i opisana w czasopiśmie "American Scientific". Gra pozwala symulować życie, rozwój oraz śmierć żywych organizmów i rozgrywana jest na nieskończonym polu komórek. Każda komórka posiada dokładnie 8 przyległych do niej sąsiadów. W komórce może żyć organizm lub nie. Nowe pokolenie organizmów powstaje wg następujących reguł:
 

obrazek

Śmierć

Organizm umiera z samotności, jeśli w przyległych do niego komórkach jest mniej niż dwóch żywych sąsiadów. Organizm umiera z przeludnienia, jeśli w przyległych do niego komórkach jest więcej niż 3 żywych sąsiadów. Zatem śmierć następuje w przypadku, gdy otaczające organizm komórki zawierają 0,1,4,5,6,7 lub 8 organizmów.

Przeżycie

Jeśli w otaczających organizm komórkach jest dwóch lub trzech żywych sąsiadów, organizm przeżywa do następnego pokolenia.

Narodziny

Jeśli pusta komórka posiada dokładnie trzech żywych sąsiadów, to rodzi się w niej nowy organizm.

 

Implementacja

Komórki zajęte przez organizmy tworzą różne wzory geometryczne zmieniające się w każdym pokoleniu. Niektóre układy organizmów powodują wymarcie kolonii, inne z kolei dają w efekcie cykliczny rozwój żywych komórek. Badanie tych układów może być bardzo ciekawym zajęciem.

W naszej implementacji zrezygnujemy z nieskończonego pola gry, które raczej trudno uzyskać w skończonej pamięci komputera. Plansza będzie złożona z matrycy komórek ułożonych w 49 wierszy po 80 kolumn. Taka matryca zmieści się bez problemów w okienku konsoli znakowej.

Chociaż pole nie będzie nieskończone, to jednak jego krawędź górna zostanie połączona z dolną, a prawa z lewą. Dzięki temu, każda komórka zawsze będzie posiadała 8 sąsiadów.

W pamięci plansza gry zostanie zrealizowana w formie tablicy łańcuchów znakowych. Ponieważ nowe pokolenie powstaje na podstawie sytuacji istniejącej w pokoleniu poprzednim, zatem musimy posiadać dwie takie tablice - z pokoleniem aktualnym oraz drugą, w której utworzymy następną generację żywych organizmów. Po tej operacji dane z drugiej tablicy przenosimy do pierwszej i wyświetlamy w okienku konsoli.

Program będzie interaktywny. W trakcie gry użytkownik może tworzyć w wybranych komórkach nowe organizmy lub usuwać je z komórek. Przyjmiemy następujący schemat klawiszy sterowania grą:

 

klawisz funkcja
strzałki przemieszczanie aktywnej komórki po planszy gry
ESC zakończenie rozgrywki
spacja jeśli aktywna komórka jest pusta, to wprowadzamy tam nowy organizm. Jeśli natomiast w aktywnej komórce już jest organizm, to usuwamy go.
Enter przejście do następnego pokolenia
A powoduje automatyczną generację nowych pokoleń organizmów aż do momentu powtórnego naciśnięcia klawisza innego klawisza.
B powoduje wygenerowanie 100 nowych komórek w przypadkowych miejscach na planszy
C usunięcie wszystkich organizmów z planszy gry.

 

// Automaty komórkowe - Gra Life
// (C)2010 ILO w Tarnowie
// KOŁO INFORMATYCZNE
//-----------------------

#include <iostream>
#include <string>
#include "newconio.h"
#include <cstdlib>
#include <time.h>

using namespace std;

// zmienne globalne

string pole1[49],pole2[49]; // przestrzenie życiowe organizmów
int cx,cy;                  // pozycja kursora 
int np;                     // numer pokolenia

// zeruje przestrzeń życiową pole1
// ustawia kursor na środku pola gry
// zeruje numer pokolenia
 
void zeruj()
{
    string s;
    int i;

    s = "";
    for(i = 0; i < 80; i++) s += " ";

    for(i = 0; i < 49; i++) pole1[i] = pole2[i] = s;

    cx = 39;
    cy = 24;
    np =  0;
}

// wyświetla zawartość pole1
//--------------------------

void wyswietlaj()
{
    int i;

    gotoxy(0,0);
    textattr(0x1f);

    for(i = 0; i < 49; i++)
    {
        cout << pole1[i];
        if(i == cy) putattrxy(0x4e,cx,cy);
    }

    gotoxy(31,49); textattr(YELLOW); cout << "Pokolenie: " << np << "     ";
}

// wylicza współrzędną x w obrębie pola gry
//-----------------------------------------

int wx(int x)
{
    if(x > 79) x =  0;
    if(x <  0) x = 79;
    return x;
}

// wylicza współrzędną y w obrębie pola gry
//-----------------------------------------

int wy(int y)
{
    if(y > 48) y =  0;
    if(y <  0) y = 48;
    return y;
}

// wylicza nowe pokolenie organizmów w pole2
// przenosi pole2 do pole1
//------------------------------------------

void pokolenie()
{
    int i,j,k,l,ls;

    for(i = 0; i < 49; i++)
      for(j = 0; j < 80; j++)
      {
          ls = 0;

          // obliczamy w ls liczbę sąsiadów komórki [i,j]

          for(k = -1; k < 2; k++)
            for(l = -1; l < 2; l++)
              if(((k != 0) || (l != 0)) && (pole1[wy(i + k)][wx(j + l)] == 'O')) ls++;

          // sprawdzamy reguły przeżycia komórki lub narodzin nowej

          if(pole1[i][j] == 'O')
          {
              if((ls == 2) || (ls == 3)) pole2[i][j] = 'O';
              else                       pole2[i][j] = ' ';
          }
          else
          {
              if(ls == 3) pole2[i][j] = 'O';
              else        pole2[i][j] = ' ';
          }
      }

      // przenosimy pole2 do pole1

      for(i = 0; i < 49; i++) pole1[i] = pole2[i];
      np++;
}

// wypełnia w pole1 100 komórek organizmami
//-----------------------------------------

void wypelnij()
{
    int x,y,i;

    for(i = 0; i < 100; i++)
    {
        x = rand() % 80;
        y = rand() % 48;
        pole1[y][x] = 'O';
    }
}

// generuje kolejne pokolenia organizmów aż do
// naciśnięcia klawisza A
//--------------------------------------------

void generuj()
{
    do
    {
        wyswietlaj();
        pokolenie();
        delay(100);
    } while(!kbhit());
}

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

int main()
{
    int kl;
    bool gra_w_toku = true;

    srand(time(NULL));

    _cinit();

    fullscreen(true); cursoroff();

    zeruj();

    while(gra_w_toku)
    {
        wyswietlaj();
        if(kbhit())
        {
            while(!(kl = getch()));

            switch(kl)
            {
                case 13:  pokolenie();
                          break;

                case 27:  gra_w_toku = false;
                          break;

                case 32:  if(pole1[cy][cx] == ' ') pole1[cy][cx] = 'O';
                          else                     pole1[cy][cx] = ' ';
                          break;

                case 72:  cy = wy(cy - 1);
                          break;

                case 77:  cx = wx(cx + 1);
                          break;

                case 80:  cy = wy(cy + 1);
                          break;

                case 75:  cx = wx(cx - 1);
                          break;

                case 'a': generuj();
                          break;

                case 'b': wypelnij();
                          break;

                case 'c': zeruj();
                          break;  
            }
        }
    }

    fullscreen(false); cursoron(); textattr(7); clrscr();

    return 0;
}

 


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe