GameGrid: Spielprogrammierung mit Java

Entwicklungsprojekt PHBern  
HomeStart Online-EditorDruckenJava-Online

Game Of Life


Eine Population entwickelt sich nach folgenden Regeln:

Jede Zelle hat 8 Nachbarzellen.

  • jede lebende Zelle, die keinen oder nur einen Nachbarn hat, stirbt (einsam)
  • jede lebende Zelle, die 4 oder mehr Nachbarn hat, stirbt (überbevölkert)
  • jede lebende Zelle, die 2 oder 3 Nachbarn hat überlebt
  • eine tote Zelle, die 3 Nachbarn hat, wird lebendig

Implementierung:
Alle Zellen enthalten einen Actor der selben Klasse Creature. Für eine lebende Zelle ist der Actor sichtbar, für eine tote Zelle ist er unsichtbar. In der ersten Variane (GameOfLife.java) werden zu Beginn zufällig 200 lebende Zellen bestimmt. In der weiten Variante (GameOfLife2.java) können die lebenden Zellen zu Beginn des Spieles mit einem Mausklick ausgewählt werden.

Beispiel zeigen

Beispiel im Online-Editor bearbeiten

 

Programmcode:

// GameOfLife.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.util.ArrayList;

public class GameOfLife extends GameGrid
{
  private static final int nb = 20;  // Number of cells in each direction
  private static final int nbCreatures = nb * nb;
  private static final int popSize = 200// Size of population at start
  private boolean[][] pop = new boolean[nb][nb];
  private Creature[] creatures = new Creature[nbCreatures];

  public GameOfLife()
  {
    super(nb, nb, 25Color.red, "sprites/snowwindow.gif");
    setSimulationPeriod(1);
    int k = 0;
    // Create creature in every cell
    for (int x = 0; x < nb; x++)
    {
      for (int y = 0; y < nb; y++)
      {
        creatures[k] = new Creature();
        Location loc = new Location(x, y);
        addActor(creatures[k], loc);
        creatures[k].setVisible(false);
        k++;
      }
    }
    reset();
    show();
  }

  public void reset()
  {
    // All actors are dead
    for (int i = 0; i < nbCreatures; i++)
      creatures[i].isAlive = false;
    // Create the living population randomly
    for (int i = 0; i < popSize; i++)
    {
      Creature creature = (Creature)getOneActorAt(getRandomLocation());
      creature.isAlive = true;
    }
    act();
  }

  public void act()
  {
    // Show the population
    for (int i = 0; i < nbCreatures; i++)
      creatures[i].setVisible(creatures[i].isAlive);
  }

  public static void main(String[] args)
  {
    new GameOfLife();
  }
}

// ------------------class Creature ----------------------------------
class Creature extends Actor
{
  protected boolean isAlive = false;

  public Creature()
  {
    super("sprites/creature.gif");
  }

  // Every actor applies the population rules to himself
  public void act()
  {
    // Get number of (living) neighbours
    ArrayList<Actor> neighbours = getNeighbours(1);
    int nbNeighbours = 0;
    for (Actor neighbour : neighbours)
      if (neighbour.isVisible())
        nbNeighbours++;

    // Generation rule:
    if (isVisible())  // alive
    {
      if (!(nbNeighbours == 2 || nbNeighbours == 3))
        isAlive = false// dying
    }
    else // dead
    {
      if (nbNeighbours == 3)
        isAlive = true;  // become alive
    }
  }
}


Variante 2: Lebende Zellen per Mausklick festlegen


Die Lebenwesen können zu Beginn mit einem Mausklick festgelegt werden. Auf diese Weise können interessante Populationen mit wenigen Lebenwesen untersucht werden.
Im oberen Teil des Bildes rechts sind zum Beispiel einige stabile Populationen dargestellt. Im unteren Teil sind weitere merkwürdige Gebilde, die blinken oder sich fortbewegen.

Beispiel zeigen

Beispiel im Online-Editor bearbeiten

 

Programmcode:

// GameOfLife2.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.util.ArrayList;
import java.awt.*;

public class GameOfLife2 extends GameGrid implements GGMouseListener
{
  private static final int nb = 20;  // Number of cells in each direction
  private static final int nbCreatures = nb * nb;
  private static final int popSize = 200; // Size of population at start
  private boolean[][] pop = new boolean[nb][nb];
  private Creature[] creatures = new Creature[nbCreatures];

  public boolean mouseEvent(GGMouse mouse)
  {
    Location location = toLocationInGrid(mouse.getX(), mouse.getY());
    Creature creature = (Creature)getOneActorAt(location);
    if (mouse.getEvent() == GGMouse.lClick)
    {
      creature.isAlive = !creature.isVisible();
      if (creature.isVisible())
        creature.hide();
      else
        creature.show();
    }
    else  // Drag
    {
      creature.isAlive = true;
      creature.show();
    }

    if (!isRunning())
      refresh();
    return true;
  }

  public GameOfLife2()
  {
    super(nb, nb, 25, Color.red, "sprites/snowwindow.gif");
    setSimulationPeriod(1);
    addMouseListener(thisGGMouse.lPress);
    int = 0;
    // Create creature in every cell
    for (int = 0; x < nb; x++)
    {
      for (int = 0; y < nb; y++)
      {
        creatures[k] = new Creature();
        Location loc = new Location(x, y);
        addActor(creatures[k], loc);
        creatures[k].hide();
        k++;
      }
    }
    reset();
    addMouseListener(thisGGMouse.lPress);
    show();
  }

  public void reset()
  {
    // All actors are dead
    for (int = 0; i < nbCreatures; i++)
      creatures[i].isAlive = false;

    act();
  }

  public void act()
  {
    // Show the population
    for (int = 0; i < nbCreatures; i++)
      if (creatures[i].isAlive)
        creatures[i].show();
      else
        creatures[i].hide();

  }

  public static void main(String[] args)
  {
    new GameOfLife2();
  }
}

// ------------------class Creature ----------------------------------
class Creature extends Actor
{
  protected boolean isAlive = false;

  public Creature()
  {
    super("sprites/creature.gif");
  }

  // Every actor applies the population rules to himself
  public void act()
  {
    // Get number of (living) neighbours
    ArrayList<Actor> neighbours = getNeighbours(1);
    int nbNeighbours = 0;
    for (Actor neighbour : neighbours)
      if (neighbour.isVisible())
        nbNeighbours++;

    // Generation rule:
    if (isVisible())  // alive
    {
      if (!(nbNeighbours == || nbNeighbours == 3))
        isAlive = false// dying
    }
    else // dead
    {
      if (nbNeighbours == 3)
        isAlive = true;  // become alive
    }
  }
}

 

Variante 3: Mehrere lebende Zellen


Hier wird eine grössere Population dargestellt. Nach dem Start der Simulation mit Klick auf Run werden bald stabile "Wohngemeinschaften" sichtbar.

Beispiel zeigen

Beispiel im Online-Editor bearbeiten

 

Programmcode:

// GameOfLife3.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;

public class GameOfLife3 extends GameGrid
{
  private static final int = 80;  // Number of cells in each direction
  private static final int = 2000; // Size of population at start
  private boolean[][] a = new boolean[s][s];

  public GameOfLife3()
  {
    super(s, s, 10, Color.darkGray);
    setTitle("Conway's Game Of Life");
    reset();
    show();
  }

  public void reset()
  {
    for (int = 0; x < s; x++)
      for (int = 0; y < s; y++)
        a[x][y] = false;  // All cells dead

    Location loc;
    for (int = 0; n < z; n++)
    {
      loc = getRandomEmptyLocation();
      a[loc.x][loc.y] = true;
    }
    showPopulation();
  }

  private void showPopulation()
  {
    Location loc;
    for (int = 0; x < s; x++)
    {
      for (int = 0; y < s; y++)
      {
        loc = new Location(x, y);
        if (a[x][y])
          getBg().fillCell(loc, Color.green, false);
        else
          getBg().fillCell(loc, Color.black, false);
      }
    }
  }

  private int getNumberOfNeighbours(int x, int y)
  {
    int nb = 0;
    for (int = Math.max(0, x - 1); i < Math.min(s, x + 2); i++)
    {
      for (int = Math.max(0, y - 1); k < Math.min(s, y + 2); k++)
      {
        if (!(== && == y))
        {
          if (a[i][k])
            nb++;
        }
      }
    }
    return nb;
  }

  public void act()
  {
    boolean[][] b = new boolean[s][s];
    for (int = 0; x < s; x++)
    {
      for (int = 0; y < s; y++)
      {
        int nb = getNumberOfNeighbours(x, y);
        if (a[x][y])    // living cell
        {
          if (nb < 2)
            b[x][y] = false;
          else if (nb > 3)
            b[x][y] = false;
          else
            b[x][y] = true;
        }
        else   // dead cell
        {
          if (nb == 3)
            b[x][y] = true;
          else
            b[x][y] = false;
        }
      }
    }
    a = b;
    showPopulation();
  }

  public static void main(String[] args)
  {
    new GameOfLife3();
  }
}