Skip to content

Лабораториска вежба 2

Tomche Delev edited this page Feb 28, 2014 · 12 revisions

Класи и наследување (имплементација на Game of Life)

За играта Game of Life

Game of Life

Game of Life, или уште позната како Life, е автомат на клетки пронајден од Британскиот математичар John Horton Conway во 1970.

За играње на играта не се потребни играчи, односно еволуцијата во следната состојба на играта се одредува од нејзината почетна состоба, без притоа да е потребно било каква интеракција од играчот. Единствена интеракција во играта е да се создаде почетна конфигурација и да се гледа како истата еволуира.

WAT

Светот на Game of Life е бесконечен дво-димензионален ортогонален грид од клекти во квадратна форма, при што секоја клетка може да биде во две можни состојби, жива или мртва. Секоја клетка е во интеракција со нејзините осум соседи, кои се распоредени хоризонтално, вертикално или дијагонално соседно. Во секој момент во времето, односно при секоја еволуција на светот се случуваат следните транзиции:

  1. Секоја жива клетка со помалку од два живи соседи умира од ненаселеност.
  2. Секоја жива клетка со два или три живи соседи преживеува до следната генерација.
  3. Секоја жива клетка со повеќе од три живи соседи умира од пренаселеност.
  4. Секоја мртва клетка со точно три живи соседи оживува преку репродукција.

Иницијалната состојба на светот ја претставува почетната еволуција. Секоја наредна генерација се добива со еволуција на претходната и притоа раѓањето и умирањето на клетките се одвива во ист момент. Правилата на играта се применуваат за постојано еволуриање во нова генерација.

Програмирање

Trust me, I'm a programmer

Играта ќе ја имплементираме на целосно објектно-ориентиран начин. За таа цел на почеток ќе ги идентификуваме класите кои треба да ги имплементираме. Вообичаено класите ја претставуваат статичката структура (податоците) во една објектно-ориентирана програма.

  1. Креирајте нова конзолна апликација Lab2GameOfLife.
  2. Од погоре во текстот може да се заклучи дека основна податочна единка во нашата апликација е клетката. Во вашиот проект додајте нова класа и именувајте ја Cell.
  3. Секоја клетка може да биде во две состојби (мртва или жива). Додајте својство кое ќе ја репрезентира состојбата на клетката.
public bool IsAlive { get; set; } 
  1. Исто така додадете го следното својство кое ќе означува дали треба да оживее клетката во следната еволуција.
public bool ShouldLive { get; set; }
  1. Имплементирајте default конструктор кој ќе ги инцијализира двете својства на false.
  2. Препокриете (override) го методот ToString() така што ако клетката е жива да враќа " X ", а ако не " _ ".
  3. Следната класа која треба да се имплментира е класата која ќе ја претставува дво-димензионалната матрица (грид) со клетки. Додајте нова класа и именувајте ја Grid.
  4. Во класта додадете својства за бројот на редови и колони за матрицата на гридот.
public int Rows { get; set; }
public int Columns { get; set; }
  1. Додајте својство дво-димензионално поле (матрица) во која ќе се чуваат клетките.
public Cell[][] Cells { get; set; }
  1. Имплементирајте конструктор кој ќе прима два аргументи (бројот на редови и бројот на колони) и ќе ја иницијализира матрицата со објекти од класата Cell.
public Grid(int rows, int columns)
{
  // kod za postavuvanje na svojstvata Rows i Columns
  // ... ovde vasiot kod ...
  // kod za inicijalizacija na matricata
  Cells = new Cell[rows][];
  for (int i = 0; i < Rows; i++)
  {
      Cells[i] = new Cell[Columns];
      for (int j = 0; j < Columns; j++)
      {
          // ovde kod za instanciranje na objekt od klasata Cell
          // i postavuvanje na toj objekt na soodvetniot element vo matricata
          // ... vasiot kod ovde...   
      }
  }
}
  1. Имплементирајте го методот ToggleCell за оживување/убивање на клетка на позиција x, y
public void ToggleCell(int x, int y, bool isAlive)
{
  // vasiot kod ovde
}
  1. Во следниот метод Evolve ќе ги имплементираме правилата на еволуција во играта.
public void Evolve()
{
  /*
  Algoritam za implementiranje na pravilata na igrata
  1. Za sekoja kletka vo matricata so kletki treba da se izbrojat brojot na
  zhivi sosedi vo 8-te nasoki (gore levo, gore sredina, gore desno, levo,
  desno, dolu levo, dolu sredina i dolu desno). 
  2. Spored slednite pravila na igrata za evolucija treba da se implementiraat
  slednite uslovi (postavuvanje na svojstvoto ShouldLive):
  - sekoja zhiva kletka so pomalku od dva zhivi sosedi umira od osamenost
  
  - sekoja zhiva kletka so dva ili tri zhivi sosedi prezhivuva do slednata
  generacija
  
  - sekoja zhiva kletka so povekje od tri sosedi umira od prenaselenost
  
  - sekoja mrtva kletka so tochno tri sosedi ozivuva preku reprodukcija
  
  3. Otkako kje gi evoluirame site kletki, treba da ja promenime nivnata
  sostojba (svojstvoto IsAlive) vo zavisnost od toa dali treba da zhivee
  (svojstvoto ShouldLive). Treba da se izminat povtorno site kletki i
  svojstvoto IsAlive da dobie vrednost na svojstvoto ShouldLive.
  */
}
  1. Следна класа која треба да се имплементира е класата која ќе ја претставува самата игра. Додајте нова класа и именувајте ја Game. Направете ја оваа класа апстрактна.
abstract class Game
{

}
  1. Во класта додадете својства за гридот на клетките во играта, моменталната генерација и максималниот број на генерации што може да еволуираат клетките.
  protected Grid grid;

  public int CurrentGeneration { get; set; }
  
  public int MaxGenerations { get; set; }
  1. Имплементирајте конструктор кој ќе прима аргумент максимален број на генерации и ќе го поставува ова својство, а својството моментна генерација ќе го поставува на 0.
public Game(int maxGenerations)
{
  // vasiot kod ovde
}
  1. Имплементирајте метод Evolve кој не прима аргументи и само го повикува соодветниот метод од класата Grid и ја зголемува тековната генерација за 1.
public void Evolve()
{
  // vasiot kod ovde
}
  1. Имплементирајте виртуелен метод virtual кој ќе ја печати состојбата на играта на конзола.
virtual public void Show()
{
  Console.Clear();
  // vasiot kod ovde
  // prikazot od pechatenjeto treba da e sleden:
  // 'Current generation: <CurrentGeneration>'
  // ' _ _ _ X _ _ _
  
  // ' _ _ _ X _ _ _
  
  // itn
}
  1. Додајте две класи StillLifeGame и OscilatorGame кои наследуваат од класата Game и го содржат следниот код:
/// <summary>
  /// Implementacija na igrata so pochetna sostojba so statichki raspored na zhivi kletki koi ne se menuvaat pri evolucija.
  /// </summary>
  class StillLifeGame : Game
  {
      public enum GameType
      {
          Block,
          Beehive,
          Loaf,
          Boat
      }

      public GameType Type { get; set; }

      public StillLifeGame(GameType gameType, int maxGenerations) : base(maxGenerations)
      {
          Type = gameType;
          if (Type == GameType.Block)
          {
              grid = new Grid(4, 4);
              grid.ToggleCell(1, 1, true);
              grid.ToggleCell(1, 2, true);
              grid.ToggleCell(2, 1, true);
              grid.ToggleCell(2, 2, true);
          }

          if (Type == GameType.Beehive)
          {
              grid = new Grid(5, 6);
              grid.ToggleCell(1, 2, true);
              grid.ToggleCell(1, 3, true);
              grid.ToggleCell(2, 1, true);
              grid.ToggleCell(2, 4, true);
              grid.ToggleCell(3, 2, true);
              grid.ToggleCell(3, 3, true);
          }
      }

      override public void Show()
      {
          Console.Title = String.Format("Still Game of Life: {0}", Type);
          base.Show();
      }
  }
/// <summary>
  /// Implementacija na igrata so pochetna sostojba so raspored na zhivi kletki koi osciliraat pri evolucija.
  /// </summary>
  class OscilatorGame : Game
  {
      public enum GameType
      {
          Blinker,
          Toad,
          Beacon,
          Pulsar
      }

      public GameType Type { get; set; }

      public OscilatorGame(GameType gameType, int maxGenerations) : base(maxGenerations)
      {
          Type = gameType;
          if (gameType == GameType.Blinker)
          {
              grid = new Grid(5, 5);
              grid.ToggleCell(2, 1, true);
              grid.ToggleCell(2, 2, true);
              grid.ToggleCell(2, 3, true);
          }

          if (gameType == GameType.Toad)
          {
              grid = new Grid(6, 6);
              grid.ToggleCell(2, 1, true);
              grid.ToggleCell(3, 1, true);
              grid.ToggleCell(4, 2, true);
              grid.ToggleCell(1, 3, true);
              grid.ToggleCell(2, 4, true);
              grid.ToggleCell(3, 4, true);
          }
          if (gameType == GameType.Beacon)
          {
              grid = new Grid(6, 6);
              grid.ToggleCell(1, 1, true);
              grid.ToggleCell(1, 2, true);
              grid.ToggleCell(2, 1, true);
              grid.ToggleCell(2, 2, true);
              grid.ToggleCell(3, 3, true);
              grid.ToggleCell(3, 4, true);
              grid.ToggleCell(4, 3, true);
              grid.ToggleCell(4, 4, true);
          }
          if (gameType == GameType.Pulsar)
          {
              grid = new Grid(17, 17);
              for (int i = 0; i < 17; i++)
              {
                  for (int j = 0; j < 17; j++)
                  {
                      if (i == 2 || i == 7 || i == 9 || i == 14)
                      {
                          if (j == 4 || j == 5 || j == 6 || j == 10 || j == 11 || j == 12)
                          {
                              grid.ToggleCell(i, j, true);
                          }                            
                      }
                      if ((i >= 4 && i <= 6) || (i >= 10 && i <= 12))
                      {
                          if (j == 2 || j == 7 || j == 9 || j == 14)
                          {
                              grid.ToggleCell(i, j, true);
                          }
                          
                      }
                  }
              }               
          }
      }

      override public void Show()
      {
          Console.Title = String.Format("Oscilator Game of Life: {0}", Type);
          base.Show();
      }
  }
  1. Додајте го следниот код во класата Program
static readonly int MAX_GENERATIONS = 10;

      static void Main(string[] args)
      {
          // Instanciranje na objekt od igrata
          Game game = new OscilatorGame(OscilatorGame.GameType.Beacon, MAX_GENERATIONS);
          while (game.CurrentGeneration <= game.MaxGenerations)
          {
              game.Show();
              game.Evolve();
              Thread.Sleep(1000);
          }
          Console.WriteLine("Evaluation ended!\nPress any key to exit...");
          Console.ReadKey();
      }
  1. Изврешете ја програмата. Not bad

  2. Додајте ваша имплементација на класа која наследува од Game и имплементирајте некоја почетна генерација и извршете ја програмата со објект од оваа класа.

Се сеќавате што испрограмиравте?

I have no memories