/*
 * "Grundkurs Programmieren in Java - Band 1 (4. Auflage, 2007)"
 * 2001-2007, Carl Hanser Verlag
 * Loesungsvorschlag zu Aufgabe 12.4 (Version 4.0)
 * (c) 2001-2007 D. Ratz, J. Scheffler, D. Seese, J. Wiesenberger
 *
 */

import Prog1Tools.IOTools;

public class SpielDesLebens {


  // erzeugt Gewebe der Dim n*m mit zufaelligem Inhalt *** */
  public static boolean[][] erzeugeGewebe (int n, int m) {

    boolean[][] g = new boolean[n][m];

      for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
          g[i][j] = ( ((int)(Math.random()*10))%2 == 0 ) ? true : false;
          // damit der triadische Operator auch mal zur Anwendung kommt ;-)

    return g;
  }


  // liest Gewebe der Dim n*m von stdin ein
  public static boolean[][] leseGewebe (int  n, int m) {

    boolean[][] g = new boolean[n][m];

    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        g[i][j] = IOTools.readBoolean("Zelle (" + (i+1) + "/" + (j+1) + ") > ");

    return g;
  }


  // gibt Gewebe auf stdout aus
  public static void druckeGewebe (boolean[][] g) {
    
    System.out.println();

    for (int i = 1; i <= g[0].length+2; i++)     // obere Begrenzung ausgeben
      System.out.print("-");
    System.out.println();

    for (int i = 0; i < g.length; i++) {
      System.out.print("|");   // linke Begrenzung ausgeben
      for (int j = 0; j < g[i].length; j++)
        System.out.print( g[i][j] ? "*" : " "); // wenn Zelle lebt '*' ausgeben
      System.out.println("|"); // rechte Begrenzung und Zeilenvorschub
    }

    for (int i = 1; i <= g[0].length+2; i++)     // untere Begrenzung ausgeben
      System.out.print("-");
    System.out.println();

    System.out.println();


  }



  // berechnet die Anzahl der Nachbarzellen von Zelle an Pos (x,y)
  public static int getAnzNachbarn (boolean[][] g, int x, int y) {

    int zaehler = 0;

    for (int i = x-1; i <= x+1; i++)
      for (int j = y-1; j <= y+1; j++)
        if ( (i >= 0) && ( i < g.length )   && // k. "Bereichsueberschreitung" vertikal
             (j >= 0) && ( j < g[i].length) && // k. "Bereichsueberschreitung" horizontal
             ( ( i != x) || ( j != y) )     && // n. Zelle (x,y) selbst als Nachbar
             g[i][j]                           // Zelle lebt
           ) zaehler++;

     return zaehler;
  }



  // erzeuge die naechste Generation
  public static boolean[][] nextGeneration (boolean[][] g) {

    int anzNachbarn;
    boolean[][] nextGeneration = new boolean[g.length][g[0].length];

    for (int i = 0; i < g.length; i++)
      for (int j = 0; j < g[i].length; j++) {
        anzNachbarn = getAnzNachbarn(g, i, j);
        if ( (anzNachbarn < 2) ||           // Vereinsamung  ... oder ...
             (anzNachbarn > 3)               // Übervoelkerung
           ) nextGeneration[i][j] = false;  // ... Zelle in der n. Generation
        else
          if (anzNachbarn == 2)             // mit genau zwei lebenden Nachbarn ...
            nextGeneration[i][j] = g[i][j]; // ... keine Zustandsaenderung
          else nextGeneration[i][j] = true; // ... ansonsten lebt Zelle
      } // for

    return nextGeneration;
  }



  /*
   *
   * ****** main-Methode ******
   *
   */
  public static void main (String[] args) {

     boolean[][] gewebe;
     int n, m;
     char answer;

     n = IOTools.readInteger("Anz. Zeilen?  > ");
     m = IOTools.readInteger("Anz. Spalten? > ");


     do {
       answer = Character.toLowerCase(
                IOTools.readChar(
                  "Gewebe von Tastatur (t) einlesen  oder zufaellig (z) erzeugen? (t/z)> ")
                );
       if ((answer != 't') && (answer != 'z'))
         System.out.println("Bitte nur 't' oder 'z' eingeben!");
     } while ((answer != 't') && (answer != 'z'));

     if (answer == 't')
       gewebe = leseGewebe(n, m);
     else
       gewebe = erzeugeGewebe(n, m);

    System.out.println("Erste Generation:");
    druckeGewebe(gewebe);

    for (int i = 1; i <= 5; i++) { // über 5 Generationen iterieren
        System.out.println(i + "te Folgegeneration:");
        gewebe = nextGeneration(gewebe);
        druckeGewebe(gewebe);
        System.out.println();
    }

  }

}

