# Spiel des Lebens Nachbarn zählen



## demarc (16. Dez 2009)

Hallo zusammen ich hätte mal eine Frage zur meiner momentanen Uni-Hausaufgabe.

Es geht um das bekannte Game of Life von Conway.
Die Regeln sind wie folgt

Das Programm beinhaltet


eine n X n Matrix aus Nullen und Einsen einliest. Eine Eins bedeutet eine lebende Zelle eine Null eine tote Zelle.


 Jede Zelle hat 8 Nachbarn.
 Randzellen haben die Zellen des gegenüberliegenden Randes als Nachbarn.
 Aus der momentanen Zellpopulation kann man die Population der nächsten Generation durch folgende Regeln berechnen:
– – –
Hat eine tote Zelle genau 3 lebende Nachbarn, erwacht sie zum Leben. Hat eine Zelle 2 oder 3 lebende Nachbarn, bleibt sie am Leben. Alle anderen lebenden Zellen sterben.


Soweit bin ich gut durchgekommen und habe die Matrix mit einem Array erstellt und auch mit 0 und 1 gefüllt.

Mein Problem ist es jetzt die einzelnen Werte der Matrix anzusteuern und zu zählen, um sagen zu können ob und wieviele lebenden Zellen vorhanden sind.

Also wie gesagt eingelesen sind alle Werte und meine Matrix steht.
Meine Methode zur Nachbarzählung sieht nun wie folgt aus

```
public static void countNeighbours() {
		for (int x = 0; x < spielfeld.length; x++){
			for (int y = 0; y < spielfeld.length; y++){
           }
	}
}
```
Jetzt hänge ich daran wie weiter mache. Bei den meisten Versuchen bekamm ich die Meldung
ArrayIndexOutOfBoundException , also dass ich außerhalb des Arrays arbeiten wollte.

Danke für Tipps!
LG


----------



## Gast2 (16. Dez 2009)

Ich hatte das damals so gelöst:


```
public int getLivingNeighboursCount(int x, int y) throws IllegalArgumentException {
        if (x >= getSize()) throw new IllegalArgumentException("x >= size");
        if (y >= getSize()) throw new IllegalArgumentException("y >= size");

        int counter = 0;
        for (int i = Math.max((x-1), 0); i <= Math.min((x+1), size-1); i++) {
            for (int j = Math.max((y-1), 0); j <= Math.min((y+1), size-1); j++) {
                if (!(i == x && j == y)) {
                    if (getCellState(i, j)) counter++;
                }
            }
        }
        return counter;
    }
```

getCellState(i, j) gibt zurück ob die Zelle [i, j] lebt.


----------



## Marco13 (16. Dez 2009)

Das ist formal richtig, und in gewisser Hinsicht auch recht geschickt, aber... Als Alternative: Man kann auch einfach die Methode "getCellState" "index-sicher" machen:

```
int x = ...
int y = ...
for (int dx = -1; dx<=1; dx++) 
{
     for (int dy=-1; dy<=1; dy++)
     {
         if (dx != 0 || dy != 0)
         {
             if (getCellState(x+dx, y+dy)) counter++;
         }
     }
 }
 
 
 private boolean getCellState(int x, int y)
 {
     x %= sizeX;
     y %= sizeY;
     if (x<0) x+=sizeX;
     if (y<0) y+=sizeY;
     return array[x][y];
 }
```
 
Theoretisch könnte man EikeB's Ansatz (wenn man die Min/max aus den Köpfen rauszieht und so...) vielleicht leichter optimieren, aber ... das müßte man Profilen und vergleichen...


----------



## Gast2 (17. Dez 2009)

Ja stimmt, das wäre wirklich ein wenig eleganter.
(Werd ich bei mir auch mal ändern )

Soweit ich deinen code verstanden hab hast du allerdings eine "runde" welt, also da kommt man wieder an der anderen seite an wenn man über die grenzen hinaus geht.
das is im klassischen GameOfLife nicht vorgesehen glaub ich.


----------



## Landei (17. Dez 2009)

Eine "klassische" Lösung solcher Probleme ist, ringsrum einen Rand von einer Zelle stehenzulassen. Diese Zellen werden niemals geupdated (die Schleifen müssen entsprechend angepasst werden). Funktioniert bei vielen Anwendungen (z.B. bei Tetris oder Schach - dort allerdings zwei Reihen wegen Springerzügen)


----------



## Painii (17. Dez 2009)

EikeB hat gesagt.:


> das is im klassischen GameOfLife nicht vorgesehen glaub ich.


Das klassische geht soweit ich mich errinner von einer unendlichen Fläche aus, was allerdings halt ziemlich unmöglich ist für uns 

Ich hab damals auch die Lösung mit der "runden" Welt genommen.


----------



## Marco13 (17. Dez 2009)

_Ja stimmt, das wäre wirklich ein wenig eleganter.
(Werd ich bei mir auch mal ändern )_

Nicht einfach ändern. Beides ausprobieren, und schauen, was besser ist. (Ich finde meins zwar "verständlicher", aber das ist immer so, beim Vergleich von Sachen die man selbst geschrieben hat, und die andere geschrieben haben  )

_
Soweit ich deinen code verstanden hab hast du allerdings eine "runde" welt, also da kommt man wieder an der anderen seite an wenn man über die grenzen hinaus geht.
das is im klassischen GameOfLife nicht vorgesehen glaub ich._

Naja, rund... es ist eine Torus-Welt. Aber so hatte ich den Teil der Aufgabenstellung
_Randzellen haben die Zellen des gegenüberliegenden Randes als Nachbarn._
verstanden - genau das ist das nämlich. Dass man mit der beschriebenen Methode auch auf einem 4x4-Feld auf die Zelle (123,456) zugreifen kann, kann gewünscht, vorteilhaft, oder unerwünscht sein - in bezug auf die Nachbarschaftsrelation sind unsere Ansätze aber gleich, soweit ich das sehe...


----------

