# Array einem Array zuweisen



## tapioca (1. Feb 2009)

hi zusammen!

ich möchte gerne ein (boolean) 2D-Array einem anderen (boolean) 2D-Array zuweisen. 
Hintergedanke dabei ist, dass ich auf dem Array "fields" Abfragen mache, im Genaueren untersuche ich die Nachbarn auf true oder false eines jeden Elementes. Im Zusammenhang mit bestimmten Regeln setze ich dann das untersuchte Element selber auf true oder false. Dazu muss ich aber dieses newFields Array extra anlegen, damit ich mir das alte Array zum Vergleichen merken kann.
Dabei hab ich's fehlerhafter Weise am Anfang einfach mit newFields=fields versucht, wobei aber wohl nur der Pointer newFields auf das Array fields zeigt. Was heißt, wenn ich newFields verändere, verändert sich am Ende auch fields, was ich ja nicht möchte.
Dann hab ich's mit folgender Methode versucht, ich geh also jedes einzelne Element durch und weise es einzeln dem anderen zu. Ist dies so richtig, weil am Ende bekomme ich doch einen Fehler heraus? Die Zuweisung sieht folgendermaßen aus:

```
for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[0].length; j++) {
                newFields[i][j] = fields[i][j];
            }
        }
```

Die gesamte Methode sieht so aus, zwischen Zeile 11 und 98 passiert nicht viel, es werden nur die Nachbartypen bestimmt:

```
//hiermit zähle ich die nachbarn
int neighbourCounter;

//zuweisen des "Merke-Arrays"
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[0].length; j++) {
                newFields[i][j] = fields[i][j];
            }
        }
//das gemerkte Array durchlaufen und Ecken, Ränder und Innenfeld durchgehen
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[0].length; j++) {
                neighbourCounter = 0;
//                (0;0)
                if (i == 0 && j == 0) {
                    for (int k = i; k < i + 2; k++) {
                        for (int l = j; l < j + 2; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                //                (0;y)
                } else if (i == 0 && j == fields[0].length - 1) {
                    for (int k = i; k < i + 2; k++) {
                        for (int l = j - 1; l < j + 1; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                //                (x;0)
                } else if (i == fields.length - 1 && j == 0) {
                    for (int k = i - 1; k < i + 1; k++) {
                        for (int l = j; l < j + 2; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                //                (x;y)
                } else if (i == fields.length - 1 && j == fields[0].length - 1) {
                    for (int k = i - 1; k < i; k++) {
                        for (int l = j - 1; l < j; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                //                raender
                } else if (i == 0) {
                    for (int k = i; k < i + 2; k++) {
                        for (int l = j - 1; l < j + 2; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                } else if (j == 0) {
                    for (int k = i - 1; k < i + 2; k++) {
                        for (int l = j; l < j + 2; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                } else if (i == fields.length - 1) {
                    for (int k = i - 1; k < i; k++) {
                        for (int l = j - 1; l < j + 1; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                } else if (j == fields[0].length - 1) {
                    for (int k = i - 1; k < i + 1; k++) {
                        for (int l = j - 1; l < j; l++) {
                            if (fields[l][k]) {
                                neighbourCounter++;
                            }
                        }
                    }
                } //                    innenfeld
                else {
                    for (int k = i - 1; k < i + 1; k++) {
                        for (int l = j - 1; l < j + 1; l++) {
                            if (fields[k][l]) {
                                if (fields[l][k]) {
                                    neighbourCounter++;
                                }
                            }
                        }
                    }
                }


           
                if (fields[i][j]) {
//da beim Arraydurchlauf das Element selber auch mitgezählt wird, muss es abgezogen werden, wenn es true ist
    neighbourCounter--;
                    newFields[i][j] = neighbourCounter == ue ? true : false;
                } else {
                    newFields[i][j] = neighbourCounter == g ? true : false;
                }
            }

        }
// das Array wieder zurückzuweisen
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[0].length; j++) {
                fields[i][j] = newFields[i][j];
            }
        }
```

in Zeile 99 taucht der Fehler auf, wenn ich das Programm mit bestimmter true false Belegung durchlaufen lasse, zieht er einmal neighbourCounter-- ab, obwohl das fields-Element false sein sollte. Ich schließe darauf, dass die Zuweisung wieder nur durch Pointerarythmetik geschehen ist und kein neues Feld angelegt wurde, weil im neuberechneten (newFields) Array dieses Element tatsächlich auf true steht, obwohl ich doch fields abfragen möchte.
Die Arrays werden natürlich folgendermaßen deklariert:
boolean[][] fields, newFields;
fields = new boolean[x][y];
newFields = new boolean[x][y];


----------



## hdi (1. Feb 2009)

Ist das 2d-Array quadratisch? Wenn nicht, musst du


```
for (int j = 0; j < fields[0].length; j++) {
```
immer durch


```
for (int j = 0; j < fields[i].length; j++) {
```

ersetzen.

Ansonsten wäre es mal gut, wenn du eine kleine Sys-out printmeldung in jeden if-Block reinschreibst,
mit sinnvollem Kommentar. So dass du anhand eines Beispiels dann genau siehst, WO hier ein Wert, der eigentlich
false sein sollte, als true angesehen wird.


----------



## Marco13 (2. Feb 2009)

Ansonsten ist EVTL nicht entscheidend, wie du da irgendwelche (wie du selbst gesagt hast) vollkommen irrelevanten (und IMHO unhübschen) Berechnungen machst, sondern eher, wie du die beiden Arrays erstellst...


----------



## Guest (2. Feb 2009)

danke für eure hilfe, ich hab mitlerweile wohl die lösung.

das erstellen der Arrays war schon korrekt, aber ich hab Missverstanden, wie die arrays durchlaufen werden, bzw. ich hab bei den Abfragen zudem noch l und k vertauscht. Ich hab die ganze Zeit gedacht, das Array läuft erst durch jedes Zeilenelement und wechselt dann die Spalte, aber es ist genau umgekehrt. Darin lag dann mein Fehler.

Zu der Sache mit dem quadratischen 2D-Array: ist das nicht egal? Das Array ist zwar nur rechteckig, aber das heißt ja im Endeffekt, dass jedes fields_.length gleichgroß ist. Eine Rolle würde das doch nur spielen, wenn das Array quasi pyramidisch (also: erste Zelle zeigt auf Array mit einer Zelle, zweite Zelle zeigt auf Array mit zwei Zellen, usw.) oder anders asymmetrisch wäre.

zu Marco: wie könnte man die Abfragen schöner erstellen? hab schon versucht zu kürzen, aber eleganter seh ich's gerade nicht._


----------



## SlaterB (2. Feb 2009)

was genau passiert in 11-98?
werden da lediglich die 8 bzw. 9 ArrayFelder um ein Feld herum geprüft?
deine Indexe in den for-Schleifen verwirren mich etwas,
im letzten else, also im Fall 'innenfeld', werden beispielweise gerade mal 4 Felder geprüft statt 9

man könnte das etwas vereinfachen wenn man sich 4 Variablen definiert
minX, maxX, minY, maxY

danach 4x if,
if (zeile 0)
if (zeile ende)
if (spalte 0)
if (spalte ende)
und jeweils die Werte anpassen, beispielsweise bei Spalte 0 minY erhöhen oder ähnliches,
vier einzelne ifs reichen, nicht Kombinationen abfragen wie 
if (zeile 0 & spalte 0)
if (zeile 0 & spalte ende)

danach dann EINE doppelte for-Schleife mit den korrekten min-max-Werten

-----

noch einfacher: alle 9 umliegenden Felder mit einer doppelten for-Schleife durchlaufen, ohne auf die Grenzen zu achten,
dann aber nicht direkt das Array abfragen, sondern eine Hilfsmethode hatNachbarAnPosition(array, x,y),
die false zurückgibt, wenn die übergebene Position außerhalb des Arrays liegt,

entspricht in etwa den 4 if von oben, die man hier zu einem if zufassenfassen könnte und man spart sich auch die ganzen Variablen min/ max


----------



## hdi (2. Feb 2009)

> Zu der Sache mit dem quadratischen 2D-Array: ist das nicht egal?



Hast Recht, mein Fehler  

Aber um mich nicht aus dieser Diskussion zurückzuziehen, ohne dir geholfen zu haben:



> Der Term magische Zahl (engl. magic number) bezeichnet auch den schlechten Programmier-Stil, Zahlen direkt im Quellcode zu benutzen. In vielen Fällen macht dies Programme schwerer lesbar und unverständlich. Besser kann es sein, Zahlen mit Bedeutung als Konstante zu definieren und so mit einem Namen zu versehen



...das heisst was du - rein von der Logik her - willst, ist *.length* durchlaufen, für jede Reihe. 
Dass die Reihen alle gleichlang sind ist halt jetzt (zufällig oder nicht) so. 
Deswegen solltest du das auch so hinschreiben, das Programm tut zwar das selbe, aber deine Absichten
kommen einfach besser rüber. Eine Zahl bei Array-Zugriffen ist zwar nicht wirklich eine "Magic Number",
aber es geht in die gleiche Richtung..


----------



## tapioca (3. Feb 2009)

kein problem hdi 

verstehe aber natürlich auch was du meinst, werde es also mal so machen. die abfragen hab ich soweit (korrekt) fertig (auch das innenfeld). wenn noch zeit bleibt werde ich die schleifen und abfragen noch nach den vorschlägen hier verbessern, ansonsten gilt erstmal 'never change a running system'. 

Vielen Dank an alle!


----------



## tapioca (3. Feb 2009)

Nochmal als Nachtrag wie ich's jetzt (dank SlaterBs Vorschlag) gelöst habe:


```
boolean hasNeighbour(int k, int l, int xmax, int ymax) {
        if (k < 0 || l < 0 || k > xmax - 1 || l > ymax - 1) {
            return false;
        } else {
            return true;
        }
    }


    public void inferNextGeneration() {
        int neighbourCounter;
        
//Gesamtes Feld durchlaufen
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[i].length; j++) {
                neighbourCounter = 0;

//                Alle Nachbarn durchlaufen
                for (int k = i - 1; k < i + 2; k++) {
                    for (int l = j - 1; l < j + 2; l++) {
                        if (hasNeighbour(k, l, fields.length, fields[i].length) && fields[k][l]) {
                            neighbourCounter++;
                        }
                    }
                }

//                    alive
                if (fields[i][j]) {
                    neighbourCounter--;
                    for (int k = 0; k < ue.size(); k++) {
                        if (neighbourCounter == (Integer) ue.elementAt(k)) {

                            newFields[i][j] = true;
                            break;
                        } else {
                            newFields[i][j] = false;
                        }
                    }
                //                    dead
                } else {
                    for (int k = 0; k < g.size(); k++) {
                        if (neighbourCounter == (Integer) g.elementAt(k)) {
                            newFields[i][j] = true;
                            break;
                        } else {
                            newFields[i][j] = false;
                        }
                    }
                }
            }
        }
        for (int i = 0; i < fields.length; i++) {
            for (int j = 0; j < fields[i].length; j++) {
                fields[i][j] = newFields[i][j];
            }
        }
    }
```

ich musste das Projekt auch gleich mehrere Male re-(clean-)builden, weil ich garnicht glauben konnte, dass das so reibungslos klappt 
Vielen Dank nochmal!


----------



## SlaterB (3. Feb 2009)

if (hasNeighbour(k, l, fields.length, fields_.length) && fields[k][l]) { 
                            neighbourCounter++; 
                        } 

-> 

if (hasNeighbour(k, l, fields) { 
                            neighbourCounter++; 
                        } 

weniger Parameter und hasNeighbour kann gleich prüfen, ob da true im Feld drinsteht,
meinetwegen in hasNeighbourTrue umbenennen_


----------

