# Zweidimensionales Array durchsuchen und ändern



## banthrass (30. Mrz 2011)

Hallo zusammen,

wie schon mal erwähnt bin ich neu in Java. Aktuell stehe ich vor eine Aufgabe an der Uni. Wir sollen das GameOfLife programmieren....oder zumindest einen Teil davon. Aber mir fehlt irgendwie der richtige Ansatz. Ich will hier keine Lösung nur ein wenig Hilfe.

Es gibt ein zweidimensionales Array, das ich durchsuchen muss. Wenn bestimmte Vorgaben erfüllt werden, muss ich im Array etwas ändern.

Diese Bedingungen sind folgende:


> Eine lebende Zelle lebt auch in der Folgegeneration, wenn genau zwei oder drei der acht
> benachbarten Zellen in der aktuellen Generation leben.
>  Eine lebende Zelle stirbt in der Folgegeneration an Einsamkeit oder Überbevölkerung, wenn
> in der aktuellen Generation weniger als zwei oder mehr als drei der acht Nachbarzellen
> ...



Hier mal das Array:
True ist eine lebende Zelle. Wird eine lebende Zelle gefunden, muss die Umgebung überprüft werden. Je nach Ergebnis muss der Zustand ja geändert werden.

```
boolean[][] feld = { 
	{ false, false, false, false, false },
	{ false, false, true, false, false },
	{ false, false, true, false, false },
	{ false, false, true, false, false },
	{ false, false, false, false, false } }
```

Ich will mich erst mal an der ersten Bedingung versuchen. Leider find ich gerade keinen Ansatz dafür. Eine Lösung wäre sicherlich alle mit IF-Abfragen zu machen, wobei mir das sehr unelegant vorkommt. Im Forum habe ich bereits ansätze dazu gefunden. Teilweise hab ich sie nicht verstanden und teilweise waren sie in meinen Augen nicht so gut, da Sie probleme gemacht haben wenn man an den Rand des Arrays kommt.

Hat jemand einen guten Ansatz für mich?

Danke an alle


----------



## nrg (30. Mrz 2011)

erstmal musst du die erste lebendige zelle finden. das machst du mit einer verschachtelten for-schleife


```
for (int i = 0; i < feld.length; i++) {
     for (int j = 0; j < feld[i].length; j++) {
          if (feld[i][j]) doSomething(i, j);
     }
}
```

doSomething könnte dann einfach die benachbarten Zellen überprüfen:
feld[i-1][j-1]...     
feld[i+1][j+1]...     
feld[i-1][j]...
feld_[j-1]... 
etc.

vermeide dabei aber AIOOBE's mit Abfragen a la i >= 0 && i < länge_


----------



## AmunRa (30. Mrz 2011)

Eine Sache noch bei den For Schleifen,

da die Rand Zellen immer tot sind, bruachst du diese nicht zu besuch ob diese leben, 


daher kannst:

```
for ( int i=1 ;i<feld.legnth-1;i++){
   for (int j= 1; j<feld[i].length -1;j++){

        if (feld[i][j]) doSomething();

   }
}
```

daher brauchst du dir dann in do something keine gedanken machen ob du vl eine ArrayIndexOutOfBoundsException bekommst, weil garantiert ist, dass es immer ein i+-1 und j+-1 feld gibt.


----------



## banthrass (30. Mrz 2011)

danke für die Unterstützung. Bin gerade an diesem Punkt angekommen, wo ich mir um den Rand gedanken gemacht habe . der Tip kam zur richtigen Zeit.
danke 

PS.:


> Wo kämen wir denn hin, wenn jeder nur sagen würde "Wo kämen wir denn
> hin" und niemand ginge, um zu sehen, wohin man käme, wenn man ginge.



sehr cool :lol:


----------



## Samuel72 (30. Mrz 2011)

Noch ein kleiner Hinweis:
Du kannst nicht einfach die Zellen der Reihe nach durchgehen und im Bedarfsfall setzen/löschen,
da dann das Ergebnis für die folgenden Nachbarzellen falsch sein kann.

Eine Möglichkeit ist, in einem neuen zweidimensionalen Array die nächste Generation anzulegen
und dann, wenn alle Zellen fertig berechnet sind, zurückzukopieren.


----------



## banthrass (30. Mrz 2011)

Hallo zusammen,

ich bin eben fertig geworden . Danke für die Hilfe. Vielleicht hilft einem mein Code ja weiter:


```
public class GameOfLife {

	//Deklaration und Initialisierung des zweidimensionalen Felds
	boolean[][] feld = { { false, false, false, false, false },
			{ false, false, true, false, false },
			{ false, false, true, false, false },
			{ false, false, true, false, false },
			{ false, false, false, false, false } };
	
	//Deklaration und Initialisierung von privaten Variablen ( Sind nur in dieser Klasse sichtbar)
	private final int MaxRows = 5;
	private final int MaxCols = 5;
	
	//Programmeinstieg
	public static void main(String[] args) {
		GameOfLife myGame = new GameOfLife();
		for (int i = 0; i < 10; i++) {
			myGame.nextGeneration();
			myGame.print();
			System.out.println();
		}
	}

	//Funktion zur Ausgabe
	void print() {
		for (int i = 0; i < MaxRows; i++) {
			for (int j = 0; j < MaxCols; j++) {
				if (feld[i][j] == true)
					System.out.print(" o ");
				else
					System.out.print(" . ");
			}
			System.out.println();
		}
	}

	//Funktion zum zählen der lebenden Zellen
	int lifeCounter(int row, int col) {
		int counter = 0;
		
		try {
			if (feld[row - 1][col] == true)
				counter++;
			if (feld[row + 1][col] == true)
				counter++;
			if (feld[row][col - 1] == true)
				counter++;
			if (feld[row][col + 1] == true)
				counter++;
			if (feld[row - 1][col - 1] == true)
				counter++;
			if (feld[row + 1][col + 1] == true)
				counter++;
			if (feld[row + 1][col - 1] == true)
				counter++;
			if (feld[row - 1][col + 1] == true)
				counter++;
		} catch (ArrayIndexOutOfBoundsException e) {
			counter = 0; //Randzellen die nicht genau 8 Nachbarn haben sind tot
		}
		return counter;
	}

	void nextGeneration() {
		//Temp. zweidimensionales Array 
		boolean[][] tmpFeld = new boolean[MaxRows][MaxCols];
		
		//Iteration der Zeilen
		for (int i = 0; i < MaxRows; i++) {
			//Iteration der Spalten
			for (int j = 0; j < MaxCols; j++) {
				// Übergibt Anzahl lebender Zellen an alive
				int alive = lifeCounter(i, j);
				if (feld[i][j] == true) {
					if(alive == 2 || alive == 3) { 
						tmpFeld[i][j] = true;
					}
					else
						tmpFeld[i][j] = false;
				} else {
					tmpFeld[i][j] = alive == 3;
				}
			}
		}
		feld = tmpFeld;
	}
}
```


----------



## AmunRa (31. Mrz 2011)

so ich hab noch nen kleinen kritik Punkt anzubringen. 
wie ich in meinem oberen Post schon geschrieben hab musst du die Randfelder nicht durchlaufen.
daher kann man das so machen und spart sich einen try-catch-Block den ich ehrlich gesagt nicht schön finde.


```
public class GameOfLife2{
 
    //Deklaration und Initialisierung des zweidimensionalen Felds
    boolean[][] feld = { { false, false, false, false, false },
            { false, false, true, false, false },
            { false, false, true, false, false },
            { false, false, true, false, false },
            { false, false, false, false, false } };
    
    //Deklaration und Initialisierung von privaten Variablen ( Sind nur in dieser Klasse sichtbar)
    private final int MaxRows = 5;
    private final int MaxCols = 5;
    
    //Programmeinstieg
    public static void main(String[] args) {
        GameOfLife2 myGame = new GameOfLife2();
        for (int i = 0; i < 10; i++) {
            myGame.nextGeneration();
            myGame.print();
            System.out.println();
        }
    }
 
    //Funktion zur Ausgabe
    void print() {
        for (int i = 0; i < MaxRows; i++) {
            for (int j = 0; j < MaxCols; j++) {
                if (feld[i][j] == true)
                    System.out.print(" o ");
                else
                    System.out.print(" . ");
            }
            System.out.println();
        }
    }
 
    //Funktion zum zählen der lebenden Zellen
    int lifeCounter(int row, int col) {
        int counter = 0;
        
       
            if (feld[row - 1][col] == true)
                counter++;
            if (feld[row + 1][col] == true)
                counter++;
            if (feld[row][col - 1] == true)
                counter++;
            if (feld[row][col + 1] == true)
                counter++;
            if (feld[row - 1][col - 1] == true)
                counter++;
            if (feld[row + 1][col + 1] == true)
                counter++;
            if (feld[row + 1][col - 1] == true)
                counter++;
            if (feld[row - 1][col + 1] == true)
                counter++;
       
        return counter;
    }
 
    void nextGeneration() {
        //Temp. zweidimensionales Array 
        boolean[][] tmpFeld = new boolean[MaxRows][MaxCols];
        
        //Iteration der Zeilen
        for (int i = 1; i < MaxRows-1; i++) {    //<- HIER muss man die Randfelder nicht durchlaufen
            //Iteration der Spalten
            for (int j = 1; j < MaxCols-1; j++) {    //<- HIER muss man die Randfelder nicht durchlaufen
                // Übergibt Anzahl lebender Zellen an alive
                int alive = lifeCounter(i, j);
                if (feld[i][j] == true) {
                    if(alive == 2 || alive == 3) { 
                        tmpFeld[i][j] = true;
                    }
                    else
                        tmpFeld[i][j] = false;
                } else {
                    tmpFeld[i][j] = alive == 3;
                }
            }
        }
        feld = tmpFeld;
    }
}
```


----------



## banthrass (31. Mrz 2011)

Also die Geschichte mit dem try/catch und auch den Randzellen war teil der Aufgabe die ich lösen sollte. Von daher ist das okay. Andernfalls wäre deine Lösung sicherlich besser.

Danke nochmal.
Gruß


----------



## AmunRa (31. Mrz 2011)

Natürlich wenn der Lehrer das so will sollst du so abgeben, aber ich find es eben eleganter wenn man keine try-catch-Blöcke verwendet


----------

