Autor |
Beitrag |
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 07.03.13 19:42
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: 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?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: 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 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: 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!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: 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
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1448
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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  , kannst Du das Projekt mir auch ja per PN senden. Ich sehe dann besser, wie ich helfen kann.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 09.03.13 19:20
Mathematiker hat folgendes geschrieben : | Wenn Du hier nicht alles veröffentlichen möchtest , 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!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
|