You are not logged in.

  • "Joachim" is male

Posts: 2,863

Date of registration: Dec 11th 2001

Location: Hämelerwald

Occupation: Wissenschaftlicher Mitarbeiter (Forschungszentrum L3S, TU Braunschweig)

21

Saturday, June 10th 2006, 2:41pm

Angesichts der vielen Probleme, die bei dieser Aufgabe aufgrund der Verwendung eines Arrays als Datenstruktur auftreten, wäre es vielleicht eine gute Idee, die Aufgabe "echt" objektorientiert zu modellieren. Das würde bedeuten:
  • Eine Klasse "Zelle", die eine einzelne Zelle des Spielfeldes darstellt. Jede Zelle enthält eine Menge aller ihrer Nachbarn (die Reihenfolge der Nachbarn ist für diese Aufgabenstellung egal, es reicht also aus, dafür Set als Datenstruktur zu verwenden). Zudem ist es sinnvoll, daß jede Zelle die Anzahl ihrer lebendigen Nachbarn speichert, um später Berechnungen einzusparen.
  • Eine Klasse Spielfeld, die das Spielfeld modelliert und in Form eines Arrays von Zellen repräsentiert. Bei der Erzeugung des Spielfeldes werden alle dazugehörigen Zellen-Objekte erzeugt und die jeweiligen Mengen der Nachbarn gesetzt.


Ein Schritt der Simulation läuft nun wie folgt ab:
  • Zunächst wird über eine Methode "bereiteSchrittVor" der Spielfeld-Klasse für jede Zelle bestimmt, ob sie im nächsten Schritt lebt oder nicht (diese Berechnungen können an die Zellen-Objekte delegiert werden)
  • Ist diese Berechnung erfolgt, so wird dieser eben vorbereitete Schritt mit einer Methode "fuehreSchrittDurch" der Spielfeld-Klasse durchgeführt. Dabei wird bei jeder Zelle, die (wie eben in der Vorbereitung des Schrittes ermittelt) ihren Zustand wechselt, auch dieser Zustandswechsel durchgeführt. Zudem benachrichtigt jede Zelle, deren Zustand sich ändert, alle ihre Nachbarn über eine Zelle-Methode "nachbarGestorben" oder "nachbarGeboren" darüber, daß sich ihr Zustand geändert hat. Diese Methoden sorgen dafür, daß die Zähler für die Anzahl der Nachbarn in diesen Zellen angepaßt wird.


Insgesamt erfordert dies also pro Simulationsschritt zwei Durchläufe über alle Zellen (das ließe sich noch optimieren, wenn sich das Spielfeld im Vorbereitungsschritt "merkt", welche Zellen sich überhaupt verändern und im zweiten Schritt überhaupt benachrichtigt werden müssen), dafür müssen jedoch weder Arrays kopiert werden noch werden unnötige Methodenaufrufe durchgeführt.

Dieser Lösungsansatz ist zwar vermutlich nicht im Sinne der Aufgabenstellung (deswegen poste ich ihn hier so ausführlich), ich halte ihn aber für "sauberes Design". Vielleicht hat ja von euch jemand Spaß daran, das so zu implementieren.

Was die Performance angeht, dürfte dieser Ansatz gleichwertig zu den anderen hier besprochenen sein. Es ist lediglich ein höherer Aufwand bei der Initialisierung des Spielfeldes vorhanden sowie ein etwas höherer Speicherbedarf. Dafür sollte der Code deutlich lesbarer sein, weil er ohne komplizierte Array-Änderungen auskommt.
The purpose of computing is insight, not numbers.
Richard Hamming, 1962

This post has been edited 4 times, last edit by "Joachim" (Jun 10th 2006, 2:48pm)


Nikelloo

Zuhörer

Posts: 3

Date of registration: May 22nd 2006

22

Sunday, June 11th 2006, 10:21pm

Hallo!
Hab noch eine Frage zur Visulalisierung. Also das Programm läuft soweit, liefert anständige true/false Werte und das Applet funktioniert auch (wohl mit den voreingestellten Werten, da man Spielfläche verändern kann und es selbst ohne meine Klassen funktioniert). Naja, jetz is die Frage wie bekomm ich das mit dem 20x20 Spielfeld hin? Oder ist das gar nicht gefordert und sollen diese (vielen!) Werte nur als boolean ausgegeben werden?
Gruß Nikelloo

sos1981

Alter Hase

  • "sos1981" is male

Posts: 1,562

Date of registration: Oct 28th 2003

Location: Wolfsburg

Occupation: Testentwickler

23

Sunday, June 11th 2006, 10:33pm

Steht doch eigentlich in der Aufgabe:

Quoted

Implementieren Sie folgende Methoden:
ausgeben Gibt das aktuelle Spielfeld auf die Konsole aus.
...Schreiben Sie eine Applikation, die ein 20x20 Spielfeld mit Zufallswerten instanziiert und 10 Iterationen vergehenj läßt (und auf der Konsole ausgibt).

Das Liest sich doch wie: Schreiben Sie eine Klasse, die eine Main-Methode enthält und eine 20x20 Spielfeld instanziiert...und später die Methode ausgeben aufruft, um den ganzen Kram auf der Konsole ausgeben zu lassen.


PS: wenn du Probleme mit der Methoden ausgeben haben solltest, dass denk doch mal darüber nach, evtl. eine Art graphische Ausgabe auf der Konsole zu versuchen, indem du viell. für jedes lebendige Feld ein + und für ein totes Feld ein leerzeichen printest.
Damit müsste dann auch die Applikation kein Problem mehr darstellen.

Gruss
Florian
Der Einzigste ist noch viel einziger als der Einzige!

This post has been edited 2 times, last edit by "sos1981" (Jun 11th 2006, 11:39pm)


Nadja

Trainee

  • "Nadja" is female

Posts: 74

Date of registration: Apr 11th 2006

24

Monday, June 12th 2006, 8:47am

hallo ,
kann mir jemand sagen ,wie ich das miz dem
Interface kannGrafischAngezeigtWerden machen muß?

zuerst muß man doch folgendes machen:
kannGrafischAngezeigtWerden.class erzeugen!

dann muß ich doch das Interface auch in der Klasse Spielfeld implementieren ,oder????
Wie sollte es jetzt gehen?????
Muß ich jetzt jede Methode des Interfaces ausführlich definieren?

  • "Joachim" is male

Posts: 2,863

Date of registration: Dec 11th 2001

Location: Hämelerwald

Occupation: Wissenschaftlicher Mitarbeiter (Forschungszentrum L3S, TU Braunschweig)

25

Monday, June 12th 2006, 9:23am

Quoted

Original von Nadja
kann mir jemand sagen ,wie ich das miz dem
Interface kannGrafischAngezeigtWerden machen muß?
Einfach implementieren.

Quoted

zuerst muß man doch folgendes machen:
kannGrafischAngezeigtWerden.class erzeugen!
Nö, das ist doch schon vorgegeben: http://www.sim.uni-hannover.de/~xmb/SS06/uebungen/applet/.

Quoted

dann muß ich doch das Interface auch in der Klasse Spielfeld implementieren ,oder????
Genau.

Quoted

Wie sollte es jetzt gehen?????
Muß ich jetzt jede Methode des Interfaces ausführlich definieren?
Ganz einfach das Interface implementieren gemäß der zugehörigen Dokumentation. Dazu mußt Du natürlich nur die Methoden vollständig neu schreiben, deren Funktion Du noch nicht bereits durch andere Methoden abgedeckt hast. Diese kannst Du nämlich implementieren, indem Du die entsprechenden Methoden aufrufst, die Du bereits hast.
The purpose of computing is insight, not numbers.
Richard Hamming, 1962

This post has been edited 2 times, last edit by "Joachim" (Jun 12th 2006, 9:31am)


Nadja

Trainee

  • "Nadja" is female

Posts: 74

Date of registration: Apr 11th 2006

26

Monday, June 12th 2006, 9:48am

muß man dann die Methoden vom Interface in meiner Applikation aufrufen können? oder nur in der Klasse Spielfeld implementieren ?

maffe

Unregistered

27

Monday, June 12th 2006, 11:31am

Hallöle,
ich hab da auch mal ein Problemchen.

Bei diesem Code:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Spielfeld {
	private boolean[][] spielfeld;
	
	public void Spielfeld(int sizeX, int sizeY) {
		spielfeld = new boolean[sizeX][sizeY];
	}
	
	public void Spielfeld() {
		this(20, 20, -1);
	}
	
	public void Spielfeld(int sizeX, int sizeY, int startWert) {
		this(sizeX, sizeY);
		for(int i=0;i<sizeX;i++) {
		// ...
		}
	}

bekomme ich beim Versuch des Kompilierens folgende Fehlermeldungen:

Source code

1
2
3
4
5
6
Spielfeld.java:25: call to this must be first statement in constructor
                this(20, 20, -1);
                    ^
Spielfeld.java:29: call to this must be first statement in constructor
                this(sizeX, sizeY);
                    ^

Kann mir jemand bei der Lösung dieses Problems helfen? =) Ich versteh nicht, was er daran auszusetzen hat.

Warui

Turner, Serveradmin & Workaholic

  • "Warui" is male

Posts: 717

Date of registration: Apr 25th 2006

Location: Südstadt

Occupation: (iter (B.Sc. Inf, 8)) \n (be-a-slave ("SRA", "Bachelor Thesis")) \n (be-a-programmer-slave ("Freelancer", "Programming"))

28

Monday, June 12th 2006, 12:08pm

Verkette sie doch so:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Spielfeld {
	private boolean[][] spielfeld;
	
	public void Spielfeld() {
		this(sizeX, sizeY);
	}

	public void Spielfeld(int sizeX, int sizeY) {
		this(sizeX, sizeY, -1);
	}
	
	public void Spielfeld(int sizeX, int sizeY, int startWert) {
		spielfeld = new boolean[sizeX][sizeY];
		for(int i=0;i<sizeX;i++) {
		// ...
		}
	}

Das wäre zumindest transparent, und vielleicht ist es das, was er meint oO

Möglicherweise stört er sich daran, dass nach this(sizeX, sizeY); noch was kommt, obwohl der eigentliche Konstruktor doch anscheinend schon abgearbeitet ist :)
.oO(Oder liegts an dem Rückgabewert des Konstruktors?)

Mata ne
Warui
Erwachsenwerden? Ich mach ja viel Scheiß mit, aber nicht jeden!

maffe

Unregistered

29

Monday, June 12th 2006, 12:24pm

Bringt auch nichts :(

Source code

1
2
3
4
5
6
Spielfeld.java:11: call to this must be first statement in constructor
                this(20, 20);
                    ^
Spielfeld.java:15: call to this must be first statement in constructor
                this(sizeX, sizeY, -1);
                    ^

  • "Joachim" is male

Posts: 2,863

Date of registration: Dec 11th 2001

Location: Hämelerwald

Occupation: Wissenschaftlicher Mitarbeiter (Forschungszentrum L3S, TU Braunschweig)

30

Monday, June 12th 2006, 12:49pm

Quoted

Original von Nadja
muß man dann die Methoden vom Interface in meiner Applikation aufrufen können? oder nur in der Klasse Spielfeld implementieren ?
Diese Interface dient ja nur dazu, daß die vorgefertigte GUI Deine Spielfeld-Implementierung verwenden kann. Also muß auch nur die Klasse Spielfeld dieses Interface implementieren.
The purpose of computing is insight, not numbers.
Richard Hamming, 1962

Informatik Minister

Senior Schreiberling

  • "Informatik Minister" is male

Posts: 1,234

Date of registration: Dec 11th 2001

31

Monday, June 12th 2006, 12:51pm

Quoted

Original von Warui
.oO(Oder liegts an dem Rückgabewert des Konstruktors?)

Müsste so sein. Konstruktoren haben keine Rückgabewerte. Die Betonung bei der Fehlermeldung liegt dann also auf "in constructor".
"Fliegenpilze! Löwen!! Das Leben ist gefährlich." -- www.katzundgoldt.de

This post has been edited 1 times, last edit by "Informatik Minister" (Jun 12th 2006, 12:58pm)


donnergurgler

Praktikant

  • "donnergurgler" is male

Posts: 27

Date of registration: Jun 22nd 2004

Location: Vierbach

32

Monday, June 12th 2006, 1:06pm

Quoted

Original von Warui

.oO(Oder liegts an dem Rückgabewert des Konstruktors?)

Mata ne
Warui


ja genau.

maffe

Unregistered

33

Monday, June 12th 2006, 1:09pm

Aber da wird doch gar nichts zurückgegeben ?(

This post has been edited 1 times, last edit by "maffe" (Jun 12th 2006, 1:09pm)


Informatik Minister

Senior Schreiberling

  • "Informatik Minister" is male

Posts: 1,234

Date of registration: Dec 11th 2001

34

Monday, June 12th 2006, 1:17pm

Quoted

Original von maffe
Aber da wird doch gar nichts zurückgegeben ?(

Du gibst aber den Typ des Rückgabewertes (void) an und definierst damit eine Methode. Das müsstes du streichen, damit ein Konstruktor "entsteht".

Source code

1
public Spielfeld() {..}
"Fliegenpilze! Löwen!! Das Leben ist gefährlich." -- www.katzundgoldt.de

This post has been edited 2 times, last edit by "Informatik Minister" (Jun 12th 2006, 1:18pm)


maffe

Unregistered

35

Monday, June 12th 2006, 1:34pm

Ah, stimmt. Jetzt geht's. Das Leben kann so einfach sein :D Schönen Dank =) Scheme war irgendwie einfacher :P

This post has been edited 1 times, last edit by "maffe" (Jun 12th 2006, 1:36pm)


ruffy85

Trainee

  • "ruffy85" is male

Posts: 103

Date of registration: Oct 12th 2005

Location: Hildesheim

Occupation: B.Sc. Informatik / 1. Semester

36

Monday, June 12th 2006, 2:18pm

Nun drängt die Zeit und ich komme einfach nicht weiter mit der Randüberschreitung, alles Andere arbeitet fehlerfrei. Hier mal die Ausschnitte aus meinem Code, die sich auf die Bestimmung der Anzahl der Nachbarn beziehen, vielleicht sieht ja einer etwas, was ich übersehe :D Solange man nicht an einen der Ränder kommt, werden alle Nachbarn korrekt berechnet. Sobald man am Rand ist, fehlen die Nachbarn, die den Rand überschreiten würden...

Definition von Nachbarn...

Source code

1
2
3
4
final int nachbarn[][] = {
  {-1,-1}, { 0,-1}, { 1,-1},
  {-1, 0},          { 1, 0},
  {-1, 1}, { 0, 1}, { 1, 1}};

Überprüfung auf Nachbarn...

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
protected int gibAnzahlNachbarn(int zeile, int spalte){
    int zaehler = 0;
       for (int k = 0; k < 8; ++k) {
        int nbzeile = zeile + nachbarn[k][0];
        int nbspalte = spalte + nachbarn[k][1];
         if (nbzeile >= 0 && nbzeile < this.yAusdehnung() && nbspalte >= 0 && nbspalte < this.xAusdehnung()) {
          if (SSpielfeld[nbzeile][nbspalte]) {
             ++zaehler;
          }
         }
       }
    return zaehler;
  }

Mutzkow

Junior Schreiberling

  • "Mutzkow" is male

Posts: 129

Date of registration: Oct 10th 2003

Location: Hannover

Occupation: Informatik

37

Monday, June 12th 2006, 2:50pm

@ruffy: Wenn ich deinen Code richtig verstehe, dann hast du ja als erstes ein Array von Nachbarn angelegt. Daraufhin untersuchst du für alle acht möglichen Nachbarn, ob sie INNERHALB der Grenzen des Arrays liegen.

Source code

1
2
3
4
5
6
7
8
         if (nbzeile >= 0 && nbzeile < this.yAusdehnung() && nbspalte >= 0 && nbspalte < this.xAusdehnung()) {
          if (SSpielfeld[nbzeile][nbspalte]) {
             ++zaehler;
          }
         }
       }
    return zaehler;
  }

Also wenn die Nachbarzeile größer als Null UND die Nachbarzeile KLEINER als yAusdehnung (und das gleiche nochmal auf die x-Ausdehnung bezogen) ist, soll geguckt werden, ob der entsprechende Nachbar true=lebendig ist und entsprechend der zaehler hochgezählt werden.

Wo ist denn aber deine else-Anweisung? Was passiert denn, wenn der Punkt nicht innerhalb der Grenze ist? Ich seh da nichts, was da einem entsprechenden Fehler vorbeugt.

Außerdem:
Wie hast du denn yAusdehnung definiert? Das müsste doch zB auf die Aufgabe bezogen 20 sein. Aber das Array zählt ab Null, demnach ist doch das zB. rechteste x-Feld 19 und nicht 20, oder?
Es ist ein einförmiges Ding um das Menschengeschlecht. Die meisten verarbeiten den größten Teil der Zeit, um zu leben, und das bisschen, das ihnen von Freiheit übrig bleibt, ängstigt sie so, dass sie alle Mittel aufsuchen, um es los zu werden.

  • "Joachim" is male

Posts: 2,863

Date of registration: Dec 11th 2001

Location: Hämelerwald

Occupation: Wissenschaftlicher Mitarbeiter (Forschungszentrum L3S, TU Braunschweig)

38

Monday, June 12th 2006, 3:10pm

Quoted

Original von ruffy85
Nun drängt die Zeit und ich komme einfach nicht weiter mit der Randüberschreitung, alles Andere arbeitet fehlerfrei. Hier mal die Ausschnitte aus meinem Code, die sich auf die Bestimmung der Anzahl der Nachbarn beziehen, vielleicht sieht ja einer etwas, was ich übersehe :D Solange man nicht an einen der Ränder kommt, werden alle Nachbarn korrekt berechnet. Sobald man am Rand ist, fehlen die Nachbarn, die den Rand überschreiten würden...
Kein Wunder, die Betrachtung solcher Nachbarn schließt Du mit der Bedingung "nbzeile >= 0 && nbzeile < this.yAusdehnung() && nbspalte >= 0 && nbspalte < this.xAusdehnung()" ja auch aus. Der Ansatz mit Modulo, der in diesem Thread schon mehrfach erwähnt wurde, ist schon der richtige. Das Problem an der Sache ist nur leider, daß Java anders verhält, als man es als Rechnen in der Restklasse Z_... erwarten würde.

Ich würde erwarten (Beispiel mit modulo 3):
6 % 3 = 0
5 % 3 = 2
4 % 3 = 1
3 % 3 = 0
2 % 3 = 2
1 % 3 = 1
0 % 3 = 0
-1 % 3 = 2
-2 % 3 = 1
-3 % 3 = 0
-4 % 3 = 2
-5 % 3 = 1

Java macht es aber so:
6 % 3 = 0
5 % 3 = 2
4 % 3 = 1
3 % 3 = 0
2 % 3 = 2
1 % 3 = 1
0 % 3 = 0
-1 % 3 = -1
-2 % 3 = -2
-3 % 3 = 0
-4 % 3 = -1
-5 % 3 = -2

Java verhält sich jedoch wie erwartet, wenn man nur mit positiven Werten rechnet, also vorher ein vielfaches von 3 addiert.

Für Deinen Fall bedeutet das "int nbzeile = (zeile + nachbarn[k][0] + this.yAusdehnung()) % this.yAusdehnung();" (die If-Abfrage kann dann entfallen)

Quoted

Definition von Nachbarn...

Source code

1
2
3
4
final int nachbarn[][] = {
  {-1,-1}, { 0,-1}, { 1,-1},
  {-1, 0},          { 1, 0},
  {-1, 1}, { 0, 1}, { 1, 1}};
Die würde ich als "static" deklarieren, weil sie nicht von der jeweiligen Instanz abhängen; zudem als "private".
The purpose of computing is insight, not numbers.
Richard Hamming, 1962

This post has been edited 1 times, last edit by "Joachim" (Jun 12th 2006, 3:12pm)


ruffy85

Trainee

  • "ruffy85" is male

Posts: 103

Date of registration: Oct 12th 2005

Location: Hildesheim

Occupation: B.Sc. Informatik / 1. Semester

39

Monday, June 12th 2006, 3:38pm

Wow... und das ist der gesamte Fehler? Hatte vorher betrachte bis <ausdehnung+1 um ausdehnung zu erwischen, funktionierte nicht. und ich wollte links mit -1 anfangen, aber was sollte ich schon als -1 setzen, daran scheiterte ich bisher, daher hab ich meinen code zurückgesetzt auf die erste version, die mir in den sinn kam ^^

So, gerade probiert und es läuft endlich... hab ganze 5 Tage über das problem nachgedacht und die Modulo Lösung gleich am Anfang verworfen... Melde dich mal per PN, hast was gut bei mir ^^

This post has been edited 1 times, last edit by "ruffy85" (Jun 12th 2006, 3:43pm)


Horseboy

Junior Schreiberling

  • "Horseboy" is male

Posts: 129

Date of registration: Oct 26th 2005

Location: Hannover

Occupation: B. Sc. Informatik

40

Monday, June 12th 2006, 3:45pm

Quoted

Original von sos1981
PS: wenn du Probleme mit der Methoden ausgeben haben solltest, dass denk doch mal darüber nach, evtl. eine Art graphische Ausgabe auf der Konsole zu versuchen, indem du viell. für jedes lebendige Feld ein + und für ein totes Feld ein leerzeichen printest.
Damit müsste dann auch die Applikation kein Problem mehr darstellen.

Gruss
Florian


Hättest du dazu evtl. 'nen Tip? Ich bekomme das nicht so richtig hin =/

Edit: Ok, danke, hab's jetzt ;)
Zeit ist eine Illusion, und die Schlafenszeit erst recht.

This post has been edited 1 times, last edit by "Horseboy" (Jun 12th 2006, 4:07pm)