/** Eine Kolonie von Zellen */
public class Petrischale {

  /** Ein Feld von Zellen */
  private Zelle[][] inhalt;

  /** Mische ein Feld von Objekten */
  private static void mischen(Object[] feld) {
    for (int i=0;i<feld.length;i++) {
      int j=(int)(feld.length*Math.random());
      Object dummy=feld[i];
      feld[i]=feld[j];
      feld[j]=dummy;
    }
  }
  
  /** Konstruktor */
  public Petrischale(int breite, int laenge, int zahlDerLebenden) {
    // Zuerst erzeugen wir ein vorbelegtes Feld von Zellen
    Zelle[] zellen = new Zelle[breite * laenge];
    java.util.Arrays.fill(zellen,
                          0,
                          zahlDerLebenden,
                          new Zelle(true));
    java.util.Arrays.fill(zellen,
                          zahlDerLebenden,
                          zellen.length,
                          new Zelle(false));
    mischen(zellen);
    // Nun tragen wir diesen Inhalt in unsere Zellen ein
    inhalt = new Zelle[breite][laenge];
    for (int i = 0; i < breite; i++) {
      System.arraycopy(zellen,i*laenge,inhalt[i],0,laenge);
    }
  }

  /** Gib die Breite der Petrischale zurueck */
  public int getBreite() {
    return inhalt.length;
  }

  /** Gib die Laenge der Petrischale zurueck */
  public int getLaenge() {
    return inhalt[0].length;
  }

  /** Gibt die Zelle an einer bestimmten Position zurueck.
   Liegt der Index ausserhalb des darstellbaren Bereiches,
   wird eine tote Zelle zurueckgegeben.
   */
  public Zelle getInhalt(int x, int y) {
    if (x < 0 || x >= inhalt.length ||
        y < 0 || y >= inhalt[0].length)
      return new Zelle(false);
    return inhalt[x][y];
  }

  /** Gib die Zahl der lebenden Nachbarn einer Zelle zurueck */
  private int zahlDerNachbarn(int x,int y) {
    int res = 0;
    // Summiere die Zelle und die acht umgebenden Felder
    for (int i = x-1; i <= x+1; i++) {
      for (int j = y-1; j <= y+1; j++) {
        res += (getInhalt(i,j).istLebendig()) ? 1 : 0;
      }
    }
    // Ziehe die eigentliche Zelle wieder ab
    if (getInhalt(x,y).istLebendig())
      res--;
    // Gib das Resultat zurueck
    return res;
  }

  /** Konstruktor. Erzeugt aus einer alten Petrischale die
   neue Generation.
   */
  public Petrischale(Petrischale alt) {
    inhalt = new Zelle[alt.getBreite()][alt.getLaenge()];
    for (int i = 0; i < inhalt.length; i++)
      for (int j = 0; j < inhalt[i].length; j++)
        inhalt[i][j] = new Zelle(alt.getInhalt(i,j),
                                 alt.zahlDerNachbarn(i,j));
  }

  /** Setzt die Zelle an der Position (x,y) vom Zustand
   lebendig auf tot (oder umgekehrt).
   */
  public void schalteUm(int x,int y) {
    inhalt[x][y] = new Zelle( ! inhalt[x][y].istLebendig() );
  }
  
}
