Życie - programy


W tym rozdziale: Podrozdziały:

 

Prezentowane poniżej programy utworzono w następujących środowiskach programowania:

Jeśli stosujesz inne środowiska, to prawdopodobnie będziesz musiał przetworzyć odpowiednio kod programów.

 

Programy

Na podstawie opisanego algorytmu tworzymy program w języku Pascal. Poniżej przedstawiamy przykładowe zrzuty zawartości okienka konsoli oraz kod źródłowy programu.

 


Strona tytułowa gry

Przykładowa rozgrywka

 

Program w języku Pascal

//           G R A  W  Ż Y C I E
//            WERSJA  FUNKCYJNA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program Life;

uses Crt, Windows;

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
function PL(s : string) : string;
var
  i : integer;
  c : char;
begin
  for i := 1 to length(s) do
  begin
   case s[i] of
      'ą' : c := #165;
      'ć' : c := #134;
      'ę' : c := #169;
      'ł' : c := #136;
      'ń' : c := #228;
      'ó' : c := #162;
      'ś' : c := #152;
      'ż' : c := #190;
      'ź' : c := #171;
      'Ą' : c := #164;
      'Ć' : c := #143;
      'Ę' : c := #168;
      'Ł' : c := #157;
      'Ń' : c := #227;
      'Ó' : c := #224;
      'Ś' : c := #151;
      'Ż' : c := #189;
      'Ź' : c := #141;
      else
        c := s[i]; 
    end;
    s[i] := c;
  end;
  Result := s;
end;

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
procedure Centruj(t : string);
begin
  GotoXY(1 + (80-length(t)) div 2, WhereY);
  writeln(t);
end;

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
procedure Ramka(xp,yp,xk,yk : integer);
var
  i : integer;
begin
  GotoXY(xp,yp); write(#218);
  GotoXY(xp,yk); write(#192);
  GotoXY(xk,yp); write(#191);
  GotoXY(xk,yk); write(#217);
  for i := xp + 1 to xk - 1 do
  begin
    GotoXY(i,yp); write(#196);
    GotoXY(i,yk); write(#196);
  end;
  for i := yp + 1 to yk - 1 do
  begin
    GotoXY(xp,i); write(#179);
    GotoXY(xk,i); write(#179);
  end;
end;

//------------------------------------------------------
// PROGRAM GRY
//------------------------------------------------------

// ZMIENNE GLOBALNE
//------------------------------------------------------
var
  pobc,pnst : array[2..24,2..79] of boolean;
  pozycja   : COORD;
  pokolenie : integer;
  populacja : integer;

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
procedure StronaTytulowa;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,4);
  TextAttr := $6f;
  Centruj(PL('                                  '));
  Centruj(PL('        G R A  W  Ż Y C I E       '));
  Centruj(PL('                                  '));
  TextAttr := $ce;
  Centruj(PL('                                  '));
  Centruj(PL('    (C)2004 mgr Jerzy Wałaszek    '));
  Centruj(PL('                                  '));
  TextAttr := $e2;
  Centruj(PL('                                  '));
  Centruj(PL('     I Liceum Ogólnokształcące    '));
  Centruj(PL('   im. Kazimierza  Brodzińskiego  '));
  Centruj(PL('             w Tarnowie           '));
  Centruj(PL('                                  '));
  TextAttr := $f1;
  Centruj(PL('                                  '));
  Centruj(PL('    Buduj i badaj różne układy    '));
  Centruj(PL('           żywych kolonii         '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0c; Ramka(23,3,58,22);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr; GotoXY(1,8);
  TextColor(14);
  Centruj(PL('Do sterowania grą używaj następujących klawiszy'));
  writeln;
  TextColor(15);
  Centruj(PL('[strzałki] - zmiana aktywnej komórki           '));
  Centruj(PL('[Enter]    - przejście do następnego pokolenia '));
  Centruj(PL('[spacja]   - wstawianie/usuwanie organizmu     '));
  Centruj(PL('[Delete]   - zerowanie planszy gry             '));
  Centruj(PL('[F1]       - start/stop generacji pokoleń      '));
  Centruj(PL('[Escape]   - zakończenie pracy programu        '));
  writeln;
  TextColor(10);
  Centruj(PL('Gdy będziesz gotowy, naciśnij dowolny klawisz. '));
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Procedura wyświetla obecną planszę gry
//------------------------------------------------------
procedure Plansza;
var
  i,j : integer;
  s   : string;
begin
  populacja := 0;
  TextAttr := $0e;
  GotoXY(32,1); write('Pokolenie nr ',pokolenie,'     ');
  TextAttr := $1f;
  for i := 2 to 24 do
  begin
    GotoXY(2,i); s := '';
    for j := 2 to 79 do
      if pobc[i,j] then
      begin
        s := s + 'O'; inc(populacja);
      end
      else s := s + ' ';
    writeln(s);
  end;
  GotoXY(25,25); TextAttr := $0c;
  write(PL('Liczba organizmów żywych :'),populacja,'     ');
end;

// Procedura zeruje pole gry pobc, umieszcza kursor
// na środku i wyświetla pole w oknie konsoli
//------------------------------------------------------
procedure UsunOrganizmy;
var
  i,j : integer;
begin
  for i := 2 to 24 do
    for j := 2 to 79 do
      pobc[i,j] := false;
  pozycja.X := 40; pozycja.Y := 12; pokolenie := 0;
  Plansza;
end;

// Procedura wyświetla mrugający kursor na bieżącej
// pozycji gracza. Przerwanie następuje po wykryciu
// naciśniętego klawisza.
//------------------------------------------------------
procedure Kursor;
var
  c   : char;
  a,l : integer;
begin
  if pobc[pozycja.Y,pozycja.X] then c := 'O' else c := ' ';
  l := 0; a := $ce;
  while not KeyPressed do
    if l = 0 then
    begin
      l := 15; a := a xor $00ff;
      GotoXY(pozycja.X,pozycja.Y);
      TextAttr := a; write(c);
    end
    else
    begin
      dec(l); Delay(10);
    end;
  GotoXY(pozycja.X,pozycja.Y); TextAttr := $1f; write(c);
end;

// Procedura generuje następne pokolenie organizmów
//------------------------------------------------------
procedure NastepnePokolenie;
var
  i,j,k,w,x,y,ls : integer;
begin
  for i := 2 to 24 do
    for j := 2 to 79 do
    begin
      ls := 0;
      for k := -1 to 1 do
        for w := -1 to 1 do
          if (k <> 0) or (w <> 0) then
          begin
            x := j + k;
            if x = 80 then x := 2 else if x = 1 then x := 79;
            y := i + w;
            if y = 25 then y := 2 else if y = 1 then y := 24;
            if pobc[y,x] then inc(ls);
          end;
      if pobc[i,j] then
        pnst[i,j] := (ls = 2) or (ls = 3)
      else
        pnst[i,j] := (ls = 3);
    end;
  pobc := pnst;
  inc(pokolenie);
  Plansza;
end;

// Funkcja obsługuje poszczególne akcje z klawiatury.
//------------------------------------------------------
function Akcja : boolean;
var
  klawisz : char;
begin
  Result := true;
  Kursor;
  repeat
    klawisz := ReadKey;
  until klawisz <> #0;
  case klawisz of
    #13 : NastepnePokolenie; // klawisz Enter
    #27 : Result := false;   // klawisz Escape
    ' ' : with pozycja do    // klawisz spacji
          begin
            pobc[Y,X] := not pobc[Y,X];
            pokolenie := 0;
            Plansza;
          end;
    #59 : repeat             // klawisz F1
            NastepnePokolenie;
            Delay(300);
            if populacja > 0 then
            begin
              if KeyPressed then
                repeat
                  klawisz := ReadKey;
                until klawisz <> #0
              else klawisz := #0;
            end
            else break;
          until klawisz = #59;
    #72 : with pozycja do   // klawisz strzałka w górę
          begin
            dec(Y); if Y < 2 then Y := 24;
          end;
    #75 : with pozycja do   // klawisz strzałka w lewo
          begin
            dec(X); if X < 2 then X := 79;
          end;
    #77 : with pozycja do   // klawisz strzałka w prawo
          begin
            inc(X); if X > 79 then X := 2;
          end;
    #80 : with pozycja do   // klawisz strzałka w dół
          begin
            inc(Y); if Y > 24 then Y := 2;
          end;
    #83 : UsunOrganizmy;    // klawisz Delate
  end;
end;

// PROGRAM GŁÓWNY
//------------------------------------------------------

var
  a : integer;
begin
  a := TextAttr; ClrScr; CursorOff;
  StronaTytulowa;
  UsunOrganizmy;
  while Akcja do ;
  TextAttr := a; CursorOn; ClrScr;
end.

 

Program obiektowy w języku Pascal

//           G R A  W  Ż Y C I E
//            WERSJA  OBIEKTOWA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program Life;

uses Crt, Windows;

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
function PL(s : string) : string;
var
  i : integer;
  c : char;
begin
  for i := 1 to length(s) do
  begin
   case s[i] of
      'ą' : c := #165;
      'ć' : c := #134;
      'ę' : c := #169;
      'ł' : c := #136;
      'ń' : c := #228;
      'ó' : c := #162;
      'ś' : c := #152;
      'ż' : c := #190;
      'ź' : c := #171;
      'Ą' : c := #164;
      'Ć' : c := #143;
      'Ę' : c := #168;
      'Ł' : c := #157;
      'Ń' : c := #227;
      'Ó' : c := #224;
      'Ś' : c := #151;
      'Ż' : c := #189;
      'Ź' : c := #141;
      else
        c := s[i]; 
    end;
    s[i] := c;
  end;
  Result := s;
end;

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
procedure Centruj(t : string);
begin
  GotoXY(1 + (80-length(t)) div 2, WhereY);
  writeln(t);
end;

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
procedure Ramka(xp,yp,xk,yk : integer);
var
  i : integer;
begin
  GotoXY(xp,yp); write(#218);
  GotoXY(xp,yk); write(#192);
  GotoXY(xk,yp); write(#191);
  GotoXY(xk,yk); write(#217);
  for i := xp + 1 to xk - 1 do
  begin
    GotoXY(i,yp); write(#196);
    GotoXY(i,yk); write(#196);
  end;
  for i := yp + 1 to yk - 1 do
  begin
    GotoXY(xp,i); write(#179);
    GotoXY(xk,i); write(#179);
  end;
end;

//------------------------------------------------------
// PROGRAM GRY
//------------------------------------------------------

// Definicje obiektów
//------------------------------------------------------

type
  TZycie = class
    private
      pobc,pnst : array[2..24,2..79] of boolean;
      pozycja   : COORD;
      pokolenie : integer;
      populacja : integer;
      a         : integer;
      function  Akcja : boolean;
      procedure NastepnePokolenie;
      procedure Plansza;
      procedure StronaTytulowa;
      procedure UsunOrganizmy;
    public
      constructor Tworz;
      destructor  Usun;
      procedure   Graj;
  end;

// Definicje metod
//------------------------------------------------------
constructor TZycie.Tworz;
begin
  a := TextAttr; CursorOff;
end;

destructor TZycie.Usun;
begin
  TextAttr := a; CursorOn; ClrScr;
end;

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
procedure TZycie.StronaTytulowa;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,4);
  TextAttr := $6f;
  Centruj(PL('                                  '));
  Centruj(PL('        G R A  W  Ż Y C I E       '));
  Centruj(PL('                                  '));
  TextAttr := $ce;
  Centruj(PL('                                  '));
  Centruj(PL('    (C)2004 mgr Jerzy Wałaszek    '));
  Centruj(PL('                                  '));
  TextAttr := $e2;
  Centruj(PL('                                  '));
  Centruj(PL('     I Liceum Ogólnokształcące    '));
  Centruj(PL('   im. Kazimierza  Brodzińskiego  '));
  Centruj(PL('             w Tarnowie           '));
  Centruj(PL('                                  '));
  TextAttr := $f1;
  Centruj(PL('                                  '));
  Centruj(PL('    Buduj i badaj różne układy    '));
  Centruj(PL('           żywych kolonii         '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0c; Ramka(23,3,58,22);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr; GotoXY(1,8);
  TextColor(14);
  Centruj(PL('Do sterowania grą używaj następujących klawiszy'));
  writeln;
  TextColor(15);
  Centruj(PL('[strzałki] - zmiana aktywnej komórki           '));
  Centruj(PL('[Enter]    - przejście do następnego pokolenia '));
  Centruj(PL('[spacja]   - wstawianie/usuwanie organizmu     '));
  Centruj(PL('[Delete]   - zerowanie planszy gry             '));
  Centruj(PL('[F1]       - start/stop generacji pokoleń      '));
  Centruj(PL('[Escape]   - zakończenie pracy programu        '));
  writeln;
  TextColor(10);
  Centruj(PL('Gdy będziesz gotowy, naciśnij dowolny klawisz. '));
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Procedura zeruje pole gry pobc, umieszcza kursor
// na środku i wyświetla pole w oknie konsoli
//------------------------------------------------------
procedure TZycie.UsunOrganizmy;
var
  i,j : integer;
begin
  for i := 2 to 24 do
    for j := 2 to 79 do
      pobc[i,j] := false;
  pozycja.X := 40; pozycja.Y := 12; pokolenie := 0;
  Plansza;
end;

// Procedura wyświetla obecną planszę gry
//------------------------------------------------------
procedure TZycie.Plansza;
var
  i,j : integer;
  s   : string;
begin
  populacja := 0;
  TextAttr := $0e;
  GotoXY(32,1); write('Pokolenie nr ',pokolenie,'     ');
  TextAttr := $1f;
  for i := 2 to 24 do
  begin
    GotoXY(2,i); s := '';
    for j := 2 to 79 do
      if pobc[i,j] then
      begin
        s := s + 'O'; inc(populacja);
      end
      else s := s + ' ';
    writeln(s);
  end;
  GotoXY(25,25); TextAttr := $0c;
  write(PL('Liczba organizmów żywych :'),populacja,'     ');
end;

// Procedura generuje następne pokolenie organizmów
//------------------------------------------------------
procedure TZycie.NastepnePokolenie;
var
  i,j,k,w,x,y,ls : integer;
begin
  for i := 2 to 24 do
    for j := 2 to 79 do
    begin
      ls := 0;
      for k := -1 to 1 do
        for w := -1 to 1 do
          if (k <> 0) or (w <> 0) then
          begin
            x := j + k;
            if x = 80 then x := 2 else if x = 1 then x := 79;
            y := i + w;
            if y = 25 then y := 2 else if y = 1 then y := 24;
            if pobc[y,x] then inc(ls);
          end;
      if pobc[i,j] then
        pnst[i,j] := (ls = 2) or (ls = 3)
      else
        pnst[i,j] := (ls = 3);
    end;
  pobc := pnst;
  inc(pokolenie);
  Plansza;
end;

// Funkcja obsługuje poszczególne akcje z klawiatury.
//------------------------------------------------------
function TZycie.Akcja : boolean;
var
  klawisz : char;

procedure Kursor;
var
  c   : char;
  a,l : integer;
begin
  if pobc[pozycja.Y,pozycja.X] then c := 'O' else c := ' ';
  l := 0; a := $ce;
  while not KeyPressed do
    if l = 0 then
    begin
      l := 15; a := a xor $00ff;
      GotoXY(pozycja.X,pozycja.Y);
      TextAttr := a; write(c);
    end
    else
    begin
      dec(l); Delay(10);
    end;
  GotoXY(pozycja.X,pozycja.Y); TextAttr := $1f; write(c);
end;

begin
  Result := true;
  Kursor;
  repeat
    klawisz := ReadKey;
  until klawisz <> #0;
  case klawisz of
    #13 : NastepnePokolenie; // klawisz Enter
    #27 : Result := false;   // klawisz Escape
    ' ' : with pozycja do    // klawisz spacji
          begin
            pobc[Y,X] := not pobc[Y,X];
            pokolenie := 0;
            Plansza;
          end;
    #59 : repeat             // klawisz F1
            NastepnePokolenie;
            Delay(300);
            if populacja > 0 then
            begin
              if KeyPressed then
                repeat
                  klawisz := ReadKey;
                until klawisz <> #0
              else klawisz := #0;
            end
            else break;
          until klawisz = #59;
    #72 : with pozycja do   // klawisz strzałka w górę
          begin
            dec(Y); if Y < 2 then Y := 24;
          end;
    #75 : with pozycja do   // klawisz strzałka w lewo
          begin
            dec(X); if X < 2 then X := 79;
          end;
    #77 : with pozycja do   // klawisz strzałka w prawo
          begin
            inc(X); if X > 79 then X := 2;
          end;
    #80 : with pozycja do   // klawisz strzałka w dół
          begin
            inc(Y); if Y > 24 then Y := 2;
          end;
    #83 : UsunOrganizmy;    // klawisz Delate
  end;
end;

// Metoda obsługuje całą rozgrywkę
//------------------------------------------------------
procedure TZycie.Graj;
begin
  StronaTytulowa;
  UsunOrganizmy;
  while Akcja do ;
end;

//------------------------------------------------------
// PROGRAM GŁÓWNY
//------------------------------------------------------

var
  zycie : TZycie;
begin
  zycie := TZycie.Tworz;
  zycie.Graj;
  zycie.Usun;
end.

 

Program w języku C++

Program uruchomiono w środowisku Dev-C++.

//            G R A  W  Ż Y C I E
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

#include <conio.h>
#include <windows.h>
#include <iostream>
#include <iomanip>

using namespace std;

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

const int BLACK        = 0;
const int BLUE         = 1;
const int GREEN        = 2;
const int CYAN         = 3;
const int RED          = 4;
const int MAGENTA      = 5;
const int BROWN        = 6;
const int LIGHTGRAY    = 7;
const int DARKGRAY     = 8;
const int LIGHTBLUE    = 9;
const int LIGHTGREEN   = 10;
const int LIGHTCYAN    = 11;
const int LIGHTRED     = 12;
const int LIGHTMAGENTA = 13;
const int YELLOW       = 14;
const int WHITE        = 15;

static int __BACKGROUND = BLACK;
static int __FOREGROUND = LIGHTGRAY;

// Procedura ustawia pozycję wydruku w oknie konsoli
//----------------------------------------------------
void gotoxy(int x, int y)
{
  COORD c;

  c.X = x - 1;
  c.Y = y - 1;
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

// Procedura ustawia kolor tła wydruku
//----------------------------------------------------
void textbackground(int color)
{
  __BACKGROUND = color;
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
    __FOREGROUND + (color << 4));
}

// Procedura ustawia kolor tekstu
//----------------------------------------------------
void textcolor(int color)
{
  __FOREGROUND = color;
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
    color + (__BACKGROUND << 4));
}

// Procedura ustawia atrybuty koloru tekstu i tła
//----------------------------------------------------
void textattr(int _attr)
{
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _attr);
}

// Funkcja zwraca aktualną pozycję x kursora
//----------------------------------------------------
int wherex()
{
  CONSOLE_SCREEN_BUFFER_INFO info;

  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
  return info.dwCursorPosition.X + 1;
}

// Funkcja zwraca aktualną pozycję y kursora
//----------------------------------------------------
int wherey()
{
  CONSOLE_SCREEN_BUFFER_INFO info;

  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
  return info.dwCursorPosition.Y + 1;
}

// Procedura czyści zawartość okna konsoli
//----------------------------------------------------
void clrscr()
{
  DWORD written;

  FillConsoleOutputAttribute(GetStdHandle (STD_OUTPUT_HANDLE),
    __FOREGROUND + (__BACKGROUND << 4), 2000, (COORD){0, 0}, &written);
  FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ',
    2000, (COORD){0, 0}, &written);
  gotoxy(1, 1);
}

// Procedura ukrywa kursor okienka konsoli
//------------------------------------------------------
void CursorOff()
{
  CONSOLE_CURSOR_INFO Info;

  GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
  Info.bVisible = 0;
  SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
};

// Procedura przywraca kursor okienka konsoli
//------------------------------------------------------
void CursorOn()
{
  CONSOLE_CURSOR_INFO Info;

  GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
  Info.bVisible = -1;
  SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
};

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
string PL(string s)
{
  int i;
  char c;

  for(i = 0; i < s.length(); i++)
  {
    switch(s[i])
    {
      case 'ą' : c = char(165); break;
      case 'ć' : c = char(134); break;
      case 'ę' : c = char(169); break;
      case 'ł' : c = char(136); break;
      case 'ń' : c = char(228); break;
      case 'ó' : c = char(162); break;
      case 'ś' : c = char(152); break;
      case 'ż' : c = char(190); break;
      case 'ź' : c = char(171); break;
      case 'Ą' : c = char(164); break;
      case 'Ć' : c = char(143); break;
      case 'Ę' : c = char(168); break;
      case 'Ł' : c = char(157); break;
      case 'Ń' : c = char(227); break;
      case 'Ó' : c = char(224); break;
      case 'Ś' : c = char(151); break;
      case 'Ż' : c = char(189); break;
      case 'Ź' : c = char(141); break;
      default:   c = s[i]; 
    };
    s[i] = c;
  };
  return(s);
}

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
void Centruj(string t)
{
  gotoxy(1 + (80 - t.length()) / 2, wherey());
  cout << t << endl;
}

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
void Ramka(int xp,int yp,int xk,int yk)
{
  int i;

  gotoxy(xp,yp); putch(char(218));
  gotoxy(xp,yk); putch(char(192));
  gotoxy(xk,yp); putch(char(191));
  gotoxy(xk,yk); putch(char(217));
  for(i = xp + 1; i <= xk - 1; i++)
  {
    gotoxy(i,yp); putch(char(196));
    gotoxy(i,yk); putch(char(196));
  };
  for(i = yp + 1; i <= yk - 1; i++)
  {
    gotoxy(xp,i); putch(char(179));
    gotoxy(xk,i); putch(char(179));
  };
}

// Procedura wprowadza opóźnienie
// o zadaną ilość milisekund
//----------------------------------------------------
void Delay(int d)
{
  long start;

  start = GetTickCount();
  while((GetTickCount() - start) < d);
}

//------------------------------------------------------
// PROGRAM GRY
//------------------------------------------------------

// Definicje obiektów
//------------------------------------------------------

class TZycie
{
  private:
    int pobc[25][80],pnst[25][80],px,py,pokolenie,populacja;
    int Akcja();
    void NastepnePokolenie();
    void Plansza();
    void StronaTytulowa();
    void UsunOrganizmy();
  public:
    TZycie();
    ~TZycie();
    void Graj();
};

// Definicje metod
//------------------------------------------------------
TZycie::TZycie()
{
  CursorOff();
}

TZycie::~TZycie()
{
  textcolor(7); textbackground(0); CursorOn(); clrscr();
}

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
void TZycie::StronaTytulowa()
{
  textcolor(7); textbackground(0); clrscr();
  gotoxy(1,4); textattr(0x6f);
  Centruj(PL("                                  "));
  Centruj(PL("        G R A  W  Ż Y C I E       "));
  Centruj(PL("                                  "));
  textattr(0xce);
  Centruj(PL("                                  "));
  Centruj(PL("    (C)2004 mgr Jerzy Wałaszek    "));
  Centruj(PL("                                  "));
  textattr(0xe2);
  Centruj(PL("                                  "));
  Centruj(PL("     I Liceum Ogólnokształcące    "));
  Centruj(PL("   im. Kazimierza  Brodzińskiego  "));
  Centruj(PL("             w Tarnowie           "));
  Centruj(PL("                                  "));
  textattr(0xf1);
  Centruj(PL("                                  "));
  Centruj(PL("    Buduj i badaj różne układy    "));
  Centruj(PL("           żywych kolonii         "));
  Centruj(PL("                                  "));
  textattr(0xf4);
  Centruj(PL("        Gdy będziesz gotowy,      "));
  Centruj(PL("     naciśnij dowolny klawisz     "));
  Centruj(PL("                                  "));
  textattr(0x0c); Ramka(23,3,58,22);
  while(getch() == '\0') ; // Oczekiwanie na dowolny klawisz
  clrscr(); gotoxy(1,8); textcolor(14);
  Centruj(PL("Do sterowania grą używaj następujących klawiszy"));
  cout << endl; textcolor(15);
  Centruj(PL("[strzałki] - zmiana aktywnej komórki           "));
  Centruj(PL("[Enter]    - przejście do następnego pokolenia "));
  Centruj(PL("[spacja]   - wstawianie/usuwanie organizmu     "));
  Centruj(PL("[Delete]   - zerowanie planszy gry             "));
  Centruj(PL("[F1]       - start/stop generacji pokoleń      "));
  Centruj(PL("[Escape]   - zakończenie pracy programu        "));
  cout << endl; textcolor(10);
  Centruj(PL("Gdy będziesz gotowy, naciśnij dowolny klawisz. "));
  while(getch() == '\0') ; // Oczekiwanie na dowolny klawisz
  clrscr();
}

// Procedura zeruje pole gry pobc, umieszcza kursor
// na środku i wyświetla pole w oknie konsoli
//------------------------------------------------------
void TZycie::UsunOrganizmy()
{
  int i,j;

  for(i = 2; i <= 24; i++)
    for(j = 2; j <= 79; j++) pobc[i][j] = false;
  px = 40; py = 12; pokolenie = 0;
  Plansza();
}

// Procedura wyświetla obecną planszę gry
//------------------------------------------------------
void TZycie::Plansza()
{
  int i,j;
  string s;

  populacja = 0; textattr(0x0e); gotoxy(32,1);
  cout << "Pokolenie nr " << pokolenie << "     ";
  textattr(0x1f);
  for(i = 2; i <= 24; i++)
  {
    gotoxy(2,i); s = "";
    for(j = 2; j <= 79; j++)
      if(pobc[i][j])
      {
        s += "O"; populacja++;
      }
      else s += " ";
    cout << s;
  };
  gotoxy(25,25); textattr(0x0c);
  cout << PL("Liczba organizmów żywych : ") << populacja << "     ";
}

// Procedura generuje następne pokolenie organizmów
//------------------------------------------------------
void TZycie::NastepnePokolenie()
{
  int i,j,k,w,x,y,ls;

  for(i = 2; i <= 24; i++)
    for(j = 2; j <= 79; j++)
    {
      ls = 0;
      for(k = -1; k <= 1; k++)
        for(w = -1; w <= 1; w++)
          if((k != 0) || (w != 0))
          {
            x = j + k;
            if(x == 80) x = 2; else if(x == 1) x = 79;
            y = i + w;
            if(y == 25) y = 2; else if(y == 1) y = 24;
            if(pobc[y][x]) ls++;
          };
      if(pobc[i][j])
        pnst[i][j] = (ls == 2) || (ls == 3);
      else
        pnst[i][j] = (ls == 3);
    };
  for(i = 2; i <= 24; i++)
    for(j = 2; j <= 79; j++) pobc[i][j] = pnst[i][j];
  pokolenie++;
  Plansza();
}

// Funkcja obsługuje poszczególne akcje z klawiatury.
//------------------------------------------------------
int TZycie::Akcja()
{
  char klawisz,c;
  int a,l;

  if(pobc[py][px]) c = 'O'; else c = ' ';
  l = 0; a = 0xce;
  while(!kbhit())
    if(!l)
    {
      l = 15; a = (~a) & 0xff;; gotoxy(px,py);
      textattr(a); cout << c;
    }
    else
    {
      l--; Delay(10);
    };
  gotoxy(px,py); textattr(0x1f); cout << c;
  while((klawisz = getch()) == '\0');
  switch(klawisz)
  {
    case char(13) : NastepnePokolenie(); break; // klawisz Enter
    case char(27) : return(false);              // klawisz Escape
    case ' '      : pobc[py][px] = !pobc[py][px]; // klawisz spacji
                    pokolenie = 0; Plansza(); break;
    case char(59) : do             // klawisz F1
                    {
                      NastepnePokolenie(); Delay(300);
                      if(populacja)
                      {
                        if(kbhit())
                          while((klawisz = getch())=='\0');
                        else klawisz = '\0';
                      }    
                      else break;
                    } while(klawisz != char(59));
                    break;
    case char(72) : py--;   // klawisz strzałka w górę
                    if(py < 2) py = 24;
                    break;
    case char(75) : px--;   // klawisz strzałka w lewo
                    if(px < 2) px = 79;
                    break;
    case char(77) : px++;   // klawisz strzałka w prawo
                    if(px > 79) px = 2;
                    break;
    case char(80) : py++;   // klawisz strzałka w dół
                    if(py > 24) py = 2;
                    break;
    case char(83) : UsunOrganizmy(); break; // klawisz Delate
  };
  return(true);
}

// Metoda obsługuje całą rozgrywkę
//------------------------------------------------------
void TZycie::Graj()
{
  StronaTytulowa();
  UsunOrganizmy();
  while(Akcja());
}

//------------------------------------------------------
// PROGRAM GŁÓWNY
//------------------------------------------------------

int main()
{
  TZycie zycie;

  zycie.Graj();
}

 

Dla ambitnych

  1. Dodaj do programu edytor reguł śmierci, przeżycia oraz narodzin nowego organizmu.
  2. Znajdź układy stabilne, czyli nie zmieniające się w kolejnych pokoleniach.
  3. Znajdź układy cykliczne o długości cyklu 2, czyli w drugim pokoleniu następuje powrót do stanu wyjściowego.

 

 


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

©2018 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