Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Wator-Simulation - Werte in packed record nicht abfragbar
galagher - Fr 01.03.13 17:57
Titel: Wator-Simulation - Werte in packed record nicht abfragbar
Hallo!
Ich bastle mir gerade eine Wator-Simulation, ich habe folgendes deklariert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| type TElement = (srtWater, srtShark, srtFish, srtBorder);
type TSort = packed record Element: TElement; X, Y, Age, Dir, Satt: Integer; aBoard: array [-1..66, -1..64] of TElement; end;
const iMaxH = 66; iMaxV = 64;
var Form1: TForm1; Waqua: TSort; |
aBoard ist, wie der Name schon sagt, das Spielbrett, damit kann ich auf einem TImage die zugehörigen Grafiken darstellen.
Aber ich kann nicht überprüfen, welches TElement das ist:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.FishTimerTimer(Sender: TObject); var x, y: Integer; begin for x := 0 to iMaxH-1 do for y := 0 to iMaxV-1 do begin if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = 1 then begin end; end; end; end; |
Ich kann also
Waqua.Dir und vermutlich auch
X, Y, Age, Dir, Satt nicht abfragen.
Warum nicht? Was mache ich falsch?
Moderiert von
Narses: Doppelposting entfernt.
Mathematiker - Fr 01.03.13 18:22
Hallo,
ich habe Deinen Text 1:1 übernommen und in einer Methode
Delphi-Quelltext
1: 2:
| waqua.aBoard[2,4] := srtFish; waqua.dir:=1; |
gesetzt. Die nachfolgende Prozedur
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.Button2Click(Sender: TObject); var x, y: Integer; begin for x := 0 to iMaxH-1 do for y := 0 to iMaxV-1 do begin if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = 1 then begin showmessage('Jetzt'); end; end; end; end; |
stoppt genau dann, wenn Deine beiden Bedingungen erfüllt sind. Es funktioniert also.
Der Fehler liegt also wo anders. Du musst etwas mehr Quelltext zeigen, um den Fehler zu lokalisieren.
Nebenbei: srtfish, srtshark, ... sieht eher nach einer Wator-Simulation aus, weniger nach Game of Life.
Beste Grüße
Mathematiker
galagher - Fr 01.03.13 18:31
Mathematiker hat folgendes geschrieben : |
stoppt genau dann, wenn Deine beiden Bedingungen erfüllt sind. Es funktioniert also.
Der Fehler liegt also wo anders. Du musst etwas mehr Quelltext zeigen, um den Fehler zu lokalisieren. |
Zunächst ist alles srtWater, dann befülle ich per Random mit srtShark und srtFish:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
| procedure TForm1.InitBoard; var i, x, n: Integer; begin ClearBoard;
for i := 0 to 500 do begin n := Random(12); case n of 0, 5 : begin Waqua.Element := srtWater; Waqua.Dir := dirWater; end; 6, 7 : begin Waqua.Element := srtShark; if Random(2) = 0 then Waqua.Dir := dirSharkLeft else Waqua.Dir := dirSharkRight; end; 8..11: begin Waqua.Element := srtFish; if Random(2) = 0 then Waqua.Dir := dirFishLeft else Waqua.Dir := dirFishRight; end; end;
Waqua.X := Random(iMaxH-1); Waqua.Y := Random(iMaxV-1);
Waqua.aBoard[Waqua.X, Waqua.Y] := Waqua.Element;
DrawSort(Waqua); end;
if Waqua.aBoard[0, 0] = srtWater then label1.Caption := 'Water'; if Waqua.aBoard[0, 0] = srtShark then label1.Caption := 'Shark';if Waqua.aBoard[0, 0] = srtFish then label1.Caption := 'Fish'; end; |
Mathematiker hat folgendes geschrieben : |
Nebenbei: srtfish, srtshark, ... sieht eher nach einer Wator-Simulation aus, weniger nach Game of Life. |
Habe mich in der Eile geirrt :oops: und den Titel jetzt korrigiert!
//Edit: jetzt gibt's meine Eröffnung 2x, könnte das überflüssige 2. bitte jemand löschen?
Mathematiker - Fr 01.03.13 18:39
Hallo,
funktioniert perfekt. Nach der Initialisierung stoppt die Testroutine mehrfach, wenn dir=1 ist und das Feldelement srtFish. Der Fehler ist also an anderer Stelle.
Allerdings habe ich dirSharkLeft, dirSharkRight, usw... Zahlwerte von 0 bis 2 zugewiesen, da ich nicht weiß, welche Werte diese bei Dir haben sollen.
Beste Grüße
Mathematiker
galagher - Fr 01.03.13 18:50
Mathematiker hat folgendes geschrieben : |
funktioniert perfekt. Nach der Initialisierung stoppt die Testroutine mehrfach, wenn dir=1 ist und das Feldelement srtFish. Der Fehler ist also an anderer Stelle. |
Mathematiker hat folgendes geschrieben : |
Allerdings habe ich dirSharkLeft, dirSharkRight, usw... Zahlwerte von 0 bis 2 zugewiesen, da ich nicht weiß, welche Werte diese bei Dir haben sollen. |
Ich habe das so gemacht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| const dirWater = 0; dirSharkLeft = 1; dirSharkRight = 2; dirFishLeft = 3; dirFishRight = 4; |
Ich habe einfach "1" angegeben, weil ich der einfacheren Lesbarkeit hier keine Konstantenbezeichnungen verwenden wollte! Diese Konstanten geben den Index der Grafik in einer TImageList an, zugleich verwende ich sie, um abzufragen, welches "Vieh" sich gerade wo befindet.
Wenn ich es testweise mit nur einem srtFish initialisiere, klappt es, aber noch bekomme ich es nicht hin, dass der "alte" Bereich mit srtWater überzeichnet wird:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.InitBoard; var i, x, n: Integer; begin ClearBoard;
Waqua.Element := srtFish;
if Random(2) = 0 then Waqua.Dir := dirFishLeft else Waqua.Dir := dirFishRight;
Waqua.X := Random(iMaxH-1); Waqua.Y := Random(iMaxV-1);
Waqua.aBoard[Waqua.X, Waqua.Y] := Waqua.Element;
DrawSort(Waqua); end; |
Mathematiker - Fr 01.03.13 18:56
Hallo,
da hast Du ja das Problem!
Delphi-Quelltext
1: 2: 3:
| const dirFishLeft = 3; dirFishRight = 4; |
Wenn Du das Feld mit srtFish füllst, gibst Du entweder dirFishLeft = 3 oder dirFishRight = 4 an, d.h. niemals eine 1.
Damit kann
Delphi-Quelltext
1: 2: 3: 4: 5:
| if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = 1 then begin ... |
nie erreicht werden.
Beste Grüße
Mathematiker
Nachtrag: Blödsinn. Jetzt zitiere ich mich schon selbst. Bitte nachfolgenden Eintrag entfernen.
galagher - Fr 01.03.13 19:06
Hallo!
Mathematiker hat folgendes geschrieben : |
Wenn Du das Feld mit srtFish füllst, gibst Du entweder dirFishLeft = 3 oder dirFishRight = 4 an, d.h. niemals eine 1.
Damit kann
Delphi-Quelltext 1: 2: 3: 4: 5:
| if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = 1 then begin ... |
nie erreicht werden. |
Der Code sieht jetzt so aus, es klappt aber nur mit einem einzigen srtFish:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| for x := -1 to iMaxH do for y := -1 to iMaxV do begin if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = dirFishLeft then begin Waqua.Dir := dirWater; Waqua.aBoard[x, y] := srtWater; DrawSort(Waqua);
Waqua.X := Waqua.X-1; Waqua.Dir := dirFishLeft; Waqua.aBoard[x, y] := srtFish; DrawSort(Waqua); end; end; end; |
Wenn ich mit Random initialisiere, tut sich gar nichts.
Ausserdem habe ich an den "Rändern" mit -1, iMaxV und iMaxH srtBorder gesetzt, das sind unsichtbare Dinger, die ausserhalb des sichtbaren Bereichs liegen und die Viecher einfach dort die Richtung ändern lassen soll, soweit bin ich aber noch nicht.
Mathematiker - Fr 01.03.13 19:15
Hallo,
Du änderst nach dem Erkennen von srtfish die Variable dir auf dirwater:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| if Waqua.aBoard[x, y] = srtFish then begin if Waqua.Dir = dirFishLeft then begin Waqua.Dir := dirWater; |
Da Waqua.Dir für das ganze(!) Feld gilt, wird dirfishleft nicht mehr erreicht.
Ich vermute, Du möchtest für jedes Feld die Größe dir haben, d.h.
Delphi-Quelltext
1: 2: 3: 4:
| aBoard: array [-1..66, -1..64] of record X, Y, Age, Dir, Satt: Integer; irgendetwas : TElement; end; |
wäre besser, oder so ähnlich.
Beste Grüße
Mathematiker
Nachtrag: Ich melde mich erst einmal ab. Jetzt geht's zu Dieter Nuhr. :D
galagher - Fr 01.03.13 20:07
Mathematiker hat folgendes geschrieben : |
Da Waqua.Dir für das ganze(!) Feld gilt, wird dirfishleft nicht mehr erreicht.
Ich vermute, Du möchtest für jedes Feld die Größe dir haben, |
Genau das! Habe den Code aleso entsprechend umgebaut, sodass jedes einzelne (Teil-)Feld sowohl das Array als auch Dir, Age usw haben.
Allerdings funktioniert der Code im Timer jetzt nicht mehr...
//Edit: Hab's hinbekommen!
Mathematiker, vielen Dank!
Melde mich wieder, wenn ich nicht weiterkomme!
galagher - Sa 02.03.13 11:44
Hallo!
Jetzt schaffe ich es, dass srtFish waagrecht hin- und herlaufen, an einem "Hindernis" wie zB. srtShark die Richtung und zusätzlich die vertikale Position ändern.
Der Grundgedanke ist:
Bei links -> rechts: Setzt srtFish 1 Feld nach recht und überschreibe das Ursprungsfeld mit srtWater.
Bei rechts :> links: Setzt srtFish 1 Feld nach links und überschreibe das Ursprungsfeld mit srtWater.
Bei einem Hindernis wie zB. srtShark: Per Random ein Feld nach unten/oben.
Die Anzahl der srtFish müsste dabei doch eigentlich gleich bleiben,
es werden aber immer weniger die Anzahl schwankt aber: wird zuerst weniger und schwankt dann!
Hier der Code - warum verringert sich die Anzahl an srtFish?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155:
| procedure TForm1.FishTimerTimer(Sender: TObject); var x, y, i: Integer; begin try for x := -1 to iMaxH do for y := -1 to iMaxV do begin if Waqua.aBoard[x, y].Element = srtFish then begin if Waqua.aBoard[x, y].Dir = dirFishLeft then begin if Waqua.aBoard[x-1, y].Element <> srtWater then begin if (y = 0) then begin Waqua.aBoard[x, y+1].Dir := dirFishRight; Waqua.aBoard[x, y+1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; if (y = iMaxV-1) then begin Waqua.aBoard[x, y-1].Dir := dirFishRight; Waqua.aBoard[x, y-1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end;
if (x < iMaxH-1) then if (Random(2) = 0) then begin Waqua.aBoard[x, y-1].Dir := dirFishRight; Waqua.aBoard[x, y-1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end else begin Waqua.aBoard[x, y+1].Dir := dirFishRight; Waqua.aBoard[x, y+1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; end else begin Waqua.aBoard[x-1, y].Dir := dirFishLeft; Waqua.aBoard[x-1, y].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; end; end; end;
for x := iMaxH downto -1 do for y := iMaxV downto -1 do begin if Waqua.aBoard[x, y].Element = srtFish then begin if Waqua.aBoard[x, y].Dir = dirFishRight then begin if Waqua.aBoard[x+1, y].Element <> srtWater then begin if (y = 0) then begin Waqua.aBoard[x, y+1].Dir := dirFishLeft; Waqua.aBoard[x, y+1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; if (y = iMaxV-1) then begin Waqua.aBoard[x, y-1].Dir := dirFishLeft; Waqua.aBoard[x, y-1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end;
if (x > 0) then if (Random(2) = 0) then begin Waqua.aBoard[x-1, y-1].Dir := dirFishLeft; Waqua.aBoard[x-1, y-1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end else begin Waqua.aBoard[x-1, y+1].Dir := dirFishLeft; Waqua.aBoard[x-1, y+1].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; end else begin Waqua.aBoard[x+1, y].Dir := dirFishRight; Waqua.aBoard[x+1, y].Element := srtFish;
Waqua.aBoard[x, y].Dir := dirWater; Waqua.aBoard[x, y].Element := srtWater; end; end; end; end;
finally i := 0; for x := -1 to iMaxH do for y := -1 to iMaxV do begin if Waqua.aBoard[x, y].Element = srtFish then Inc(i); end; Label2.Caption := inttostr(i);
for x := -1 to iMaxH do for y := -1 to iMaxV do DrawSort(x, y, Waqua); end; end; |
Blup - Di 05.03.13 18:49
Der Grundgedanke sollte sein:
1. Ermittle das Feld zu dem sich der Fisch bewegen soll.
1.a Kann die bisherige Bewegungsrichtung beibehalten werden, bewege den Fisch dort hin.
1.b Wenn nicht ermittle für alle möglichen Bewegungsrichtungen die freien Felder.
1.b.a Wenn mindestens ein Feld frei ist, wähle eines der Felder aus, übernimm die Richtung und bewege den Fisch.
1.b.b Wenn kein Feld frei ist, tu nichts.
2. Markiere den Fisch als bereits in dieser Runde bewegt!
galagher - Di 05.03.13 20:02
Blup hat folgendes geschrieben : |
Der Grundgedanke sollte sein:
1. Ermittle das Feld zu dem sich der Fisch bewegen soll.
1.a Kann die bisherige Bewegungsrichtung beibehalten werden, bewege den Fisch dort hin.
1.b Wenn nicht ermittle für alle möglichen Bewegungsrichtungen die freien Felder.
1.b.a Wenn mindestens ein Feld frei ist, wähle eines der Felder aus, übernimm die Richtung und bewege den Fisch.
1.b.b Wenn kein Feld frei ist, tu nichts.
2. Markiere den Fisch als bereits in dieser Runde bewegt! |
Ok, das habe ich so ähnlich umgesetzt: Die Fische und Haie bewegen sich im Wesentlichen waagrecht, können dabei aber jeweils 1 Feld nach oben oder unten wechseln. Habe das natürlich nicht in der letzten Stunde seit deinem Beitrag gemacht, das hat ein bisschen länger gedauert!
Jetzt läuft es korrekt, die Anzahl bleibt konstant, ich habe auch schon eingebaut, dass sich die Haie die Fische schnappen. Funktioniert alles.
Das mache ich mit zwei Timern, und ich dachte, ein optisch guter Effekt wäre, wenn
SharkTimer.Interval etwas kürzer ist als
FishTimer.Interval und sich die Haie dann schneller bewegen. Man merkt erst ab
SharkTimer.Interval := FishTimer.Interval-10; einen Unterschied, aber dann ruckelt alles. Wenn
Interval für beide Timer gleich ist, läuft es flüssig.
Kurz: Wie kann ich einen Timer schneller laufen lassen, ohne das die Grafik dann ruckelt? Und warum ist das so?
Tranx - Di 05.03.13 23:03
Möglicherweise ist das mit dem Ruckeln sowas wie ein Moirée-Effekt (nur in der Zeit, statt im Raum. Moirée-Muster entstehen, wenn zwei Muster transparent übereinander mit einer geringfügig anderen Wellenlänge/Frequenz liegen. Dann gibt es dunklere und hellere Stellen.
Das in die Zeit übertragen, wäre dann dein Ruckeln. Warum machst Du das nicht in einem Timer?
galagher - Di 05.03.13 23:17
Tranx hat folgendes geschrieben : |
Warum machst Du das nicht in einem Timer? |
Wollte ich zuerst, dann dachte ich, ich teile den Code besser auf zwei Timer auf, weil ich dann unterschiedliche Geschwindigkeiten einstellen kann, nur das klappt nicht so, wie ich will.
Habe
Interval schon in den Timern selbst gesetzt, aber das Ruckeln bleibt. :nixweiss:
Mathematiker - Di 05.03.13 23:31
Hallo,
galagher hat folgendes geschrieben : |
Habe Interval schon in den Timern selbst gesetzt, aber das Ruckeln bleibt. :nixweiss: |
Da ich nicht weiß, wie schnell Dein Rechner ist, wie kurz die Intervalle des Timers sind und wie aufwendig das Erstellen der Grafik ist, rate ich einmal:
Die Intervalle sind zu kurz, d.h. der Computer kommt mit dem Zeichnen nicht nach. Dadurch siehst Du nicht jeden Zwischenschritt und somit ruckelt es.
Genaueres kann man aber nur sagen, wenn man von der Umsetzung mehr wüsste.
Wenn Du unter
http://de.wikipedia.org/wiki/Wator nachliest, siehst Du, dass im Originalmodell Fische und Haie gleich schnell sind, d.h. ein Timer genügt. Die Effekte werden dann über die Lebensdauer der Haie ohne Futter gesteuert.
Mir ist aber klar, dass es reizvoll ist, auch unterschiedliche Geschwindigkeiten auszuprobieren.
Das kannst Du aber auch in einem Timer simulieren, in dem Du einer gewissen Anzahl von zufällig gewählten Haien z.B. zwei Bewegungsschritt gönnst. Im Mittel sind die Haie dann schneller.
Beste Grüße
Mathematiker
Blup - Mi 06.03.13 16:58
Speichere dir bei jedem Fisch bzw. Hai, wann er sich das nächste mal bewegen soll.
Dann gehst du alle Fische periodisch in kurzem Abstand durch.
Die Fische, die gerade bewegt werden sollen, werden bewegt und der Zeitpunkt für die nächste Bewegung je nach Flinkheit des Fisches aktualisiert. Wurden Fische bewegt, muss das Bild anschließend in den betreffenden Bereichen aktualisiert werden.
Horst_H - Mi 06.03.13 18:49
Hallo,
da würde ich aber lieber mit Listen/Stacks für Zeitscheiben arbeiten.
Ich stelle mir das dann so vor:
Du hast einen Taktgeber z.B alle 10 ms ein Takt einer inneren Uhr.
Fische bewegen sich maximal alle 73 Takte { ~random (44)+30 } und Haie maximal alle 31.
Die längste Zeit zwischen zwei Bewegungen ist also 73 also erstellst Du 73 Listen/Stacks.
Die Uhr läuft nun modulo maximaleTakteZwischenBewegungen
Du schiebst jeden Fisch/pointer darauf entsprechend seiner Zeit auf den passenden Stack
Mit jedem Takt werden alle Elemente des Stacks für diesen Takt verarbeitet/entfernt und entsprechend ihrer Geschwindigkeit auf den neuen passenden Stack mit der Nummer {Jetzige Zeit + Geschwindigkeit des Fisches) MOD maximaleTakteZwischenBewegungen} geschoben.
Damit braucht kein Fisch eine Zeit speichern, sondern nur seine Geschwindigkeit, und Du mußt nicht immer alle 3000 Fische abklappern.
Die Geschwingkeit kann dann nämlich extrem erhöht werden, indem Du völlig ohne Timer arbeitest, sondern jeden Durchlauf als einen Takt nimmst zudem werden immer nur Zeiger umgehängt und keine Daten verschoben, der Speicheraufwand bleibt konstant.
Gruß Horst
P.S:
Wieso überlege ich so lang, um etwas schneller hinzubekomen, was ich gar nicht brauche....
galagher - Mi 06.03.13 20:13
Horst_H hat folgendes geschrieben : |
da würde ich aber lieber mit Listen/Stacks für Zeitscheiben arbeiten.
Ich stelle mir das dann so vor:
Du hast einen Taktgeber z.B alle 10 ms ein Takt einer inneren Uhr. |
Das wäre ja dann wie ein Timer, oder? Es geht doch darum, regelmässig und andauernd das gesamte Array zu durchlaufen, um alle darin enthaltenen Daten "zu verschieben", also irgendeine Veränderung darin zu erzeugen (ein zweidimensionales Array kann ich mir gut als ein reales Schachbrett vorstellen). Danach wird das Array grafisch umgesetzt.
Horst_H hat folgendes geschrieben : |
Wieso überlege ich so lang, um etwas schneller hinzubekomen, was ich gar nicht brauche.... |
Kannst es ja immer noch in eine Wator-Simulation umsetzen! :mrgreen:
Deinen Lösungsansatz kann ich aber, denke ich, nicht umsetzen...
Ich habe aber eine andere Lösung gefunden: Haie und Fische laufen zwar gleich schnell, aber die Haie wechseln im Gegensatz zu den Fischen per Random die horizontale Linie, das wirkt dann optisch so, also ob sie "jagen" würden, und zugleich ist die Einförmigkeit der Bewegungen aufgehoben!
Warum habe ich zwei Timer?
Zum Einen ist der Code jeweils doch unterschiedlich, zum anderen kann ich so den Code sauber trennen. Natürlich könnte ich die Sub-Prozeduren und -Funktionen mit Parametern versehen, sodass sie einmal für Fische, dann für Haie arbeiten, dann könnte ich noch mit
if's Fisch- und Haie-Code trennen; klar geht das.
Aber ich denke, dann wird der Code zu unübersichtlich.
Mal sehen, wohin ich da noch komme, ich denke nämlich daran, dass das "Plankton" nicht wie im Original einfach da ist, sondern, dass man die Fische füttern muss, damit sie überleben.
Die Haie fressen ja die Fische, und im Moment ist es so, dass die Fische einfach weggefressen werden.
Mathematiker - Mi 06.03.13 23:08
Hallo,
ich habe mein Wator ausgekramt und noch ein paar kleine Änderungen vorgenommen.
Vielleicht hilft es ja etwas; wenn nicht, dann einfach ignorieren. :P
Beste Grüße
Mathematiker
Tranx - Do 07.03.13 05:30
Zum Plankton: Das ist auch in der Natur nicht einfach da. Wenn z.B. widrige Umweltbedingungen (Extrem kalt, Vergiftung des Wassers, Dunkelheit) vorherrschen, ist auch da Ebbe. Eine komplexe Umweltsituation ist schwer nachzusimulieren, weil sich viele Faktoren gegenseitig beeinflussen. Viele Fische, viel Fäkalien, viele Algen, wenig Fische, wenig Fäkalien, wenig Algen, Und bei den Räubern noch extremer, da sie zumeist größer sind. Dann noch äußere Einflusse (z.B. durch den Menschen) All dies zu berücksichtigen, ist eben nicht ganz so trivial. Aber im Kleine zu zeigen, dass das Drehen an einer Schraube eben nicht immer das gewünschte Ergebnis liefert, ist - bei aller Ungenauigkeit des Ergebnisses - schon die Anstrengung wert.
Steffen: Eine realistische Umsetzung des Themas. Bei einem Screensaver zu dem Thema ernährten häufig 7000 Fische 10000 Haie, total unrealistisch!
galagher - Do 07.03.13 19:42
Tranx hat folgendes geschrieben : |
Zum Plankton: Das ist auch in der Natur nicht einfach da. |
Ja, eben! Und ausserdem soll man das Programm nicht nur ansehen, sondern durch das Füttern der Fische auch eine Aufgabe haben!
Tranx hat folgendes geschrieben : |
Aber im Kleine zu zeigen, dass das Drehen an einer Schraube eben nicht immer das gewünschte Ergebnis liefert, ist - bei aller Ungenauigkeit des Ergebnisses - schon die Anstrengung wert. |
Ich werde noch einige Einstellungsmöglichkeiten einbauen.
galagher - Do 07.03.13 23:31
Mathematiker hat folgendes geschrieben : |
Ich vermute, Du möchtest für jedes Feld die Größe dir haben, d.h.
Delphi-Quelltext 1: 2: 3: 4:
| aBoard: array [-1..66, -1..64] of record X, Y, Age, Dir, Satt: Integer; irgendetwas : TElement; end; |
wäre besser, oder so ähnlich. |
Genau so habe ich es gemacht, ich will für jedes Feld des Arrays Integer-Werte setzen. Jetzt möchte auf die Integer-Variablen Age und Satt zugreifen. Dazu dachte ich mir, vor dem Durchlaufen des Array lese ich sie aus, sobald ich auf srtShark treffe, versetze dann srtShark auf das Zielfeld und schreibe die Werte dann für das neue Feld im Array:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| if Waqua.aBoard[x, y].Sort = srtShark then begin tmpAge := Waqua.aBoard[x, y].Age; tmpSatt := Waqua.aBoard[x, y].Satt; Caption:=inttostr(tmpsatt); Waqua.aBoard[x, y].Age := tmpAge; Waqua.aBoard[x, y].Satt := tmpSatt; |
Der Code ist vereinfacht, zeigt aber, was ich machen möchte.
Unmittelbar nach dem Befüllen des Arrays, wenn ich zum Testen die Timer nicht starte, haben alle Felder die korrekten Werte. Sobald sich im Array aber etwas ändert, stimmen die Variablen Age und Satt nicht mehr.
Was sehe ich da nicht, was ist falsch?
Mathematiker - Do 07.03.13 23:44
Hallo,
das sind wieder zu wenig Informationen um das Problem zu lokalisieren.
Es gibt da mehrere Möglichkeiten und ich kann nur raten:
1. Du durchläufst sicherlich das Feld mit Schleifen für x und y. Damit kann es sein, dass Du später noch einmal auf das vorher geänderte Feld zugreifst. Was dann? Wird der Status "Hai" gleich gesetzt? Dann bekommst Du die geplanten Maßnahme doppelt.
2. Was geschieht mit dem Feld, von dem sich der Hai wegbewegt. Auf welche Werte wird das gesetzt? Behält das den Status "Hai"?
3. Wie sieht Dein Record jetzt ganz konkret aus? Auch da könnte sich noch ein Fehler verstecken.
usw. usf.
Für eine genaue Fehlersuche wirst Du wohl mehr von den Methoden zeigen müssen.
Beste Grüße
Mathematiker
Horst_H - Fr 08.03.13 11:07
Hallo,
was
Mathematiker mit
Zitat: |
1. Du durchläufst sicherlich das Feld mit Schleifen für x und y. Damit kann es sein, dass Du später noch einmal auf das vorher geänderte Feld zugreifst. Was dann? Wird der Status "Hai" gleich gesetzt? Dann bekommst Du die geplanten Maßnahme doppelt. |
beschreibt kannst Du leicht mit der Abspeicherung einer Kopie der jetzigen Zeile y vor der Bearbeitung, die Du anschliessend als vorherige Zeile y-1 nutzt und der rechtesten Spalte ( x= max )( x->0..max und y vonn 0-> max) ,die Du dann bei (y-1) und (x= -1== max) nutzt.
So braucht es keine vollständige Kopie bei einem sehr großen Feld.
Von der Verarbeitung her wäre es aber sicher viel einfacher, mit zwei kompletten Feldern zu arbeiten, bei denen man zur Verarbeitung von einem Feld in das andere schreibt.Wenn man bei der Verarbeitung Zeiger verwendet, kann man durch Zeigertausch Alt und Neu tauschen, ohne Speicher kopieren zu müssen, was ja bei der Verarbeitung ohnehin passiert.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var Board_Alt,Board_neu: tBoard; p_BAlt,p_BNeu,p_temp : tpBoard; ... procedure Verarbeitung( p_Neu,pAlt:tpBoard); ... p_neu^[x,y] := f(p_Alt,x,y); ausgabe(p_neu); tausche(p_neu,p_alt); end; |
Gruß Horst
galagher - Fr 08.03.13 16:49
Mathematiker hat folgendes geschrieben : |
1. Du durchläufst sicherlich das Feld mit Schleifen für x und y. |
Ja, genau, das passiert innerhalb der Timer!
Mathematiker hat folgendes geschrieben : |
Damit kann es sein, dass Du später noch einmal auf das vorher geänderte Feld zugreifst. Was dann? Wird der Status "Hai" gleich gesetzt? |
Ja, das passiert weiter unten in meinem Code, immer noch innerhalb der x-y-Schleife, nachdem ermittelt wurde, was im Zielfeld ist.
Mathematiker hat folgendes geschrieben : |
2. Was geschieht mit dem Feld, von dem sich der Hai wegbewegt. Auf welche Werte wird das gesetzt? Behält das den Status "Hai"? |
Das Feld, von dem sich der Hai wegbewegt, wird mit srtWater besetzt. Ist das Zielfeld srtWater oder srtFish, dann Hai dorthin = dieses eine Feld ist dann mit dem Hai überschreiben.
Mathematiker hat folgendes geschrieben : |
3. Wie sieht Dein Record jetzt ganz konkret aus? Auch da könnte sich noch ein Fehler verstecken.
usw. usf. |
Hier mein dafür relevanter Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| type TSort = (srtWater, srtShark, srtFish, srtBorder);
type TElement = packed record aBoard: array [-1..70, -1..70] of record X, Y, Age, Satt, Dir: Integer; Sort: TSort; end; Plankton: Integer; end; var Form1: TForm1; Waqua: TElement; |
Dann erfolgt das Befüllen des Arrays Waqua mit srtWater, danach werden mit Random srtShark und srtFish im Array "verteilt". Nun folgt
SharkTimer.Enabled := True; und
FishTimer.Enabled := True;. Der relevante Code in diesen Timers sieht so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| for x := 0 to iMaxH-1 do for y := 0 to iMaxV-1 do if not RunRightToLeft then break;
for x := iMaxH-1 downto 0 do for y := iMaxV-1 downto 0 do if not RunLeftToRight then break; |
Die beiden Funktionen sehen so aus (sind beide ähnlich, aber natürlich nicht identisch), zB
RunRightToLeft:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function RunRightToLeft: Boolean; begin Result := True;
if Waqua.aBoard[x, y].Sort = srtShark then begin tmpAge := Waqua.aBoard[x, y].Age; tmpSatt := Waqua.aBoard[x, y].Satt; Caption:=inttostr(tmpAge)+' '+inttostr(tmpSatt); |
Und zwar klappt es auch nicht mit nur einem einzigen srtShark. Die Variablen tmpAge und tmpSatt haben dann die Werte jenes Feldes, auf das srtShark gesetzt werden soll. Aber zu diesem Zeitpunkt ist dieses Zielfeld ja entweder srtWater oder srtFish, der Code KANN demnach gar nicht ausgeführt werden! Und noch dazu kapiere ich nicht, warum sich x, y hier offenbar nicht auf das Feld mit srtShark bezieht, dessen Werte ausgelesen werden sollen! Da steht doch klar
if Waqua.aBoard[x, y].Sort = srtShark then, also muss doch x, y genau das Feld mit srtShark bezeichnen, und zwar,
bevor srtShark im Array versetzt wird!
1) Lies Werte vom Ursprungsfeld in Variablen, 2) verändere das Array, 3) schreibe die Werte an das Zielfeld im Array. Obiger Code realisiert 1) und 2).
Ich hoffe, das Prinzip ist verständlich von mir dargelegt!
Mathematiker - Fr 08.03.13 19:16
Hallo,
ich vermute, dass die Funktionen RunRightToLeft und RunLeftToRight innerhalb der Timer-Routine stehen.
Selbst dann ist nicht garantiert, dass die aktuellen Werte x und y der Schleifen an beide Prozeduren korrekt übergeben werden. Mein Vorschlag, x und y übergeben:
Delphi-Quelltext
1:
| function RunRightToLeft(x,y :integer): Boolean; |
Außerdem hast Du zwei Timer laufen. Die Variablen tmpAge und tmpSatt müssen dann lokal deklariert sein. Andernfalls beeinflussen sich beide Timer gegenseitig.
Beste Grüße
Mathematiker
galagher - Fr 08.03.13 19:57
Mathematiker hat folgendes geschrieben : |
ich vermute, dass die Funktionen RunRightToLeft und RunLeftToRight innerhalb der Timer-Routine stehen. |
Da vermutest du völlig richtig!
Mathematiker hat folgendes geschrieben : |
Die Variablen tmpAge und tmpSatt müssen dann lokal deklariert sein. Andernfalls beeinflussen sich beide Timer gegenseitig. |
tmpAge und tmpSatt als lokale Variablen werde ich noch machen. Solange ich teste, ist der ganze Code sowieso ziemlich "schmutzig". Jetzt habe ich an verschiedenen Stellen die Werte dieser beiden Variablen in das Zielfeld zurückgeschrieben. Bei einigen srtShark stimmen sie, bei anderen habe ich immer noch falsche Werte.
Irgendwo habe ich etwas vergessen oder übersehen. Zurückschreiben muss ich sie jedenfalls bei allen Richtungsänderungen, also immer dann, wenn sich das Array bezüglich der Hai-Felder ändert. Das wird schon.
Da es jetzt immerhin teilweise stimmt, bin ich wohl auf dem richtigen Weg, meine Überlegungen waren also grundsätzlich richtig.
Dann das Ganze nochmal bei den Fischen...
Weisst du eine Möglichkeit, wie man das automatisieren kann? Ich meine, "ändert sich im Array etwas, dann nimm alle Variablen mit, setze sie im neuen Feld ein und überschreibe sie im alten". Wäre doch viel eleganter!
Danke und Grüsse
galagher
Mathematiker - Fr 08.03.13 20:30
Hallo,
galagher hat folgendes geschrieben : |
Weisst du eine Möglichkeit, wie man das automatisieren kann? Ich meine, "ändert sich im Array etwas, dann nimm alle Variablen mit, setze sie im neuen Feld ein und überschreibe sie im alten". Wäre doch viel eleganter! |
Sehe ich im Moment leider nicht.
Wenn Du hier nicht alles veröffentlichen möchtest :wink: , kannst Du das Projekt mir auch ja per PN senden. Ich sehe dann besser, wie ich helfen kann.
Beste Grüße
Mathematiker
galagher - Sa 09.03.13 19:20
Mathematiker hat folgendes geschrieben : |
Wenn Du hier nicht alles veröffentlichen möchtest :wink: , kannst Du das Projekt mir auch ja per PN senden. Ich sehe dann besser, wie ich helfen kann. |
Ich komme ggf. darauf zurück! Leider kann ich derzeit nicht am PC arbeiten, weil vermutlich das Netzteil den Geist aufgegeben hat.
Ich hoffe, ab Montag läuft's wieder!
Zum Glück hab ich mein aktuelles Projekt auf USB-Stick gesichert. Gleich danach beim Testen schaltete sich plötzlich der PC ab und das war's!
Jedenfalls vielen Dank und Grüsse!
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!