![]() |
Hilfe bei einer Simulation
Hallo
Ich arbeite derzeit an einer kleinen Simulation, bei der ich gerade ein paar kleine Probleme habe. Ich stell euch am besten mal den Quellcode erstmal zur Verfügung. Bitte nicht gleich über mich schimpfen, ist einfach erstmal erstellt worden, ohne ihn so weit wie möglich zu verkürzen oder alles in Proceduren auszulagern. Hier erstmal der Quellcode:
Delphi-Quellcode:
Also für alle die das erstmal nicht alles durchschauen wollen hier eine kurze Erklärung dazu. Es stellt erstmal eine Simulation einer einfachen Lebensform dar, die NAhrung und Wasser sammelt und sich auf dieser Grundlage wie die Einzeller durch Zellteilung fortpflanzt. Jetzt mein Problem. ab dem ca 1000 wird die Berechnungszeit sämtlicher "Aktivitäten" deutlich länger als das Intervall für den Timer. Kennt jemand eine Möglichkeit mit denen ich die Berechnungen deutlich schneller durchführen kann? Wäre über jede Idee dankbar.unit MainLeben; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ComCtrls; type TForm1 = class(TForm) Panel1: TPanel; Panel2: TPanel; PaintBox1: TPaintBox; Timer1: TTimer; Button1: TButton; TreeView1: TTreeView; procedure FormCreate(Sender: TObject); procedure PaintBox1Paint(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private-Deklarationen } Bmp: Tbitmap; public { Public-Deklarationen } end; const LEb1AnfZahl = 5; Leb1Bew = 10; Leb1FortPflanzungsWasser = 200; Leb1FortPflanzungsNahrung = 200; Leb1NahrungOhneBewegung = 5; Leb1WasserOhneBewegung = 5; Leb1Schwanger = 3; type TLebensform = record ix, iy, iNahrung, iWasser, iBewegung, iSchwanger: integer; bFortpflanzen: boolean; end; type TOrt = record iNahrung, iWasser, iSchwierigkeit: integer; end; var Form1: TForm1; Lebensform1: array of TLebensform; Welt: array of array of TOrt; implementation {$R *.dfm} procedure TreeView_anpassen; var i: integer; begin Form1.TreeView1.Items.Clear; for i:= 0 to Length(Lebensform1)-1 do begin Form1.Treeview1.Items.Add(nil,'Lebensform ' + inttostr(i+1)); Form1.Treeview1.Items.Add(nil,'X = ' + inttostr(Lebensform1[i].ix)); Form1.Treeview1.Items.Add(nil,'Y = ' + inttostr(Lebensform1[i].iy)); Form1.Treeview1.Items.Add(nil,'Nahrung = ' + inttostr(Lebensform1[i].iNahrung)); Form1.Treeview1.Items.Add(nil,'Wasser = ' + inttostr(Lebensform1[i].iWasser)); end; Form1.Treeview1.Items.Add(nil,'FeldWasser ' + inttostr(Welt[0,0].iWasser)); Form1.Treeview1.Items.Add(nil,'FeldNahrung ' + inttostr(Welt[0,0].iNahrung)); end; procedure Bildloeschen; var i: integer; begin Form1.Bmp.Canvas.Pen.Color := clWhite; for i := 0 to Length(Lebensform1)-1 do Form1.Bmp.Canvas.Rectangle(Lebensform1[i].ix-1,Lebensform1[i].iy-1,Lebensform1[i].ix+1,Lebensform1[i].iy+1); Form1.PaintBox1.Repaint; end; procedure Bildzeichnen; var i: integer; begin Form1.Bmp.Canvas.Pen.Color := clBlue; for i := 0 to Length(Lebensform1)-1 do Form1.Bmp.Canvas.Rectangle(Lebensform1[i].ix-1,Lebensform1[i].iy-1,Lebensform1[i].ix+1,Lebensform1[i].iy+1); Form1.PaintBox1.Repaint; end; procedure Weltinitialisieren; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin Welt[i,j].iNahrung := random(3); Welt[i,j].iWasser := random(3); Welt[i,j].iSchwierigkeit := random(3); end; end; end; procedure Weltzeichnen; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) < 20) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clgray; if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) in [20..50]) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clYellow; if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) > 50) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clgreen; end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin if Button1.Caption = 'Simulation starten' then begin Timer1.Enabled := true; Button1.Caption := 'Simulation stoppen'; end else begin Timer1.Enabled := false; Button1.Caption := 'Simulation starten'; end; end; procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin Bmp := TBitmap.create; Bmp.Width := 505; Bmp.Height := 497; SetLength(Welt, Bmp.Width, Bmp.Height); randomize; SetLength(Lebensform1,1); for i := 0 to 0 do begin Lebensform1[i].ix := random(20)+1; Lebensform1[i].iy := random(20)+1; Lebensform1[i].iNahrung := 0; Lebensform1[i].iWasser := 0; Lebensform1[i].iSchwanger := 0; Lebensform1[i].iBewegung := Leb1Bew; end; Weltinitialisieren; Weltzeichnen; Bildzeichnen; TreeView_anpassen; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin BitBlt(Paintbox1.Canvas.Handle, 0, 0, Paintbox1.Width, Paintbox1.Height, Bmp.Canvas.Handle, 0, 0, SRCCOPY); end; procedure Bewegen(var Objekt: TLebensform); var i: integer; begin repeat case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; until Objekt.ix > 1; repeat case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; until Objekt.iy > 1; end; procedure Feld_ueberpruefen(Var Objekt: TLebensform); begin if (Welt[Objekt.ix-1,Objekt.iy-1].iNahrung > 0) and (Objekt.iBewegung >0) then begin Objekt.iNahrung := Objekt.iNahrung + Welt[Objekt.ix-1,Objekt.iy-1].iNahrung; Welt[Objekt.ix-1,Objekt.iy-1].iNahrung := 0; Objekt.iBewegung := Objekt.iBewegung -1; end; if (Welt[Objekt.ix-1,Objekt.iy-1].iWasser > 0) and (Objekt.iBewegung >0) then begin Objekt.iWasser := Objekt.iWasser + Welt[Objekt.ix-1,Objekt.iy-1].iWasser; Welt[Objekt.ix-1,Objekt.iy-1].iWasser := 0; Objekt.iBewegung := Objekt.iBewegung -1; end; end; procedure Lebensform_versetzen; var i, iIndex, iIndey, iIndez: integer; LebenTemp: array of TLebensform; begin for i := 0 to Length(Lebensform1)-1 do begin Lebensform1[i].iBewegung := Leb1Bew; if (Lebensform1[i].iNahrung > (Leb1FortPflanzungsNahrung + (3*Leb1NahrungOhneBewegung))) and (Lebensform1[i].iWasser > (Leb1FortPflanzungsWasser + (3*Leb1WasserOhneBewegung))) and (Lebensform1[i].bFortpflanzen = false) then Lebensform1[i].bFortpflanzen := true; if Lebensform1[i].bFortpflanzen = true then begin if Lebensform1[i].iSchwanger < Leb1Schwanger then begin Lebensform1[i].iNahrung := Lebensform1[i].iNahrung - Leb1NahrungOhneBewegung; Lebensform1[i].iWasser := Lebensform1[i].iWasser - Leb1WasserOhneBewegung; Lebensform1[i].iSchwanger := Lebensform1[i].iSchwanger + 1; end else begin Lebensform1[i].iSchwanger := 0; Lebensform1[i].bFortpflanzen := false; Lebensform1[i].iNahrung := Lebensform1[i].iNahrung - Leb1FortPflanzungsNahrung; Lebensform1[i].iWasser := Lebensform1[i].iWasser - Leb1FortPflanzungsWasser; SetLength(LebenTemp,Length(Lebensform1)); for iIndex := 0 to Length(LebenTemp)-1 do begin LebenTemp[iIndex].ix := Lebensform1[iIndex].ix; LebenTemp[iIndex].iy := Lebensform1[iIndex].iy; LebenTemp[iIndex].iNahrung := Lebensform1[iIndex].iNahrung; LebenTemp[iIndex].iWasser := Lebensform1[iIndex].iWasser; LebenTemp[iIndex].iSchwanger := Lebensform1[iIndex].iSchwanger; LebenTemp[iIndex].bFortpflanzen := Lebensform1[iIndex].bFortpflanzen; end; SetLength(Lebensform1, Length(LebenTemp)+8); for iIndex := 0 to Length(LebenTemp)-1 do begin Lebensform1[iIndex].ix := LebenTemp[iIndex].ix; Lebensform1[iIndex].iy := LebenTemp[iIndex].iy; Lebensform1[iIndex].iNahrung := LebenTemp[iIndex].iNahrung; Lebensform1[iIndex].iWasser := LebenTemp[iIndex].iWasser; Lebensform1[iIndex].iSchwanger := LebenTemp[iIndex].iSchwanger; Lebensform1[iIndex].bFortpflanzen := LebenTemp[iIndex].bFortpflanzen; end; iIndez := 0; for iIndex := -1 to 1 do begin for iIndey := -1 to 1 do begin if (iIndey = 0) and (iIndex = 0) then else begin Lebensform1[Length(LebenTemp)+iIndez].ix := Lebensform1[i].ix-iIndex; Lebensform1[Length(LebenTemp)+iIndez].iy := Lebensform1[i].iy-iIndey; Lebensform1[Length(LebenTemp)+iIndez].iNahrung := 0; Lebensform1[Length(LebenTemp)+iIndez].iWasser := 0; Lebensform1[Length(LebenTemp)+iIndez].iSchwanger := 0; Lebensform1[Length(LebenTemp)+iIndez].bFortpflanzen := false; iIndez := iIndez+1; end; end; end; end; end else begin while Lebensform1[i].iBewegung > 0 do begin Feld_ueberpruefen(Lebensform1[i]); Bewegen(Lebensform1[i]); end; end; end; end; procedure Welt_aendern; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin Welt[i,j].iNahrung := Welt[i,j].iNahrung + random(3); Welt[i,j].iWasser := Welt[i,j].iWasser + random(3); end; end; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Lebensform_versetzen; Welt_aendern; Weltzeichnen; Bildzeichnen; TreeView_anpassen; end; end. Vielen Dank BAMatze |
Re: Hilfe bei einer Simulation
Zeige uns doch bitte deinen Quellcode als Anhang mit allen benötigten Dateien. Dann macht das ganze mehr sinn und eventuell auch spass.
|
Re: Hilfe bei einer Simulation
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
|
Re: Hilfe bei einer Simulation
Wenn du die Liste auf dem Fenster weglassen würdest, wäre es schon um einiges schneller.
|
Re: Hilfe bei einer Simulation
Also hab das jetzt mal getestet und bei mir ändert sich dadurch nicht allzu viel. Es fängt eventuell erst bei der folgenden Teilung an mit den "riesigen" PAuse aber es geht mir ja darum, ob es Möglichkeiten gibt, die Berechnungen anders durchzuführen und damit ein konstanten zeitlichen Zwischenraum zu erreichen, obwohl sich die Zahl der "Lebewesen" weiter vergrößert.
|
Re: Hilfe bei einer Simulation
Guten Morgen und ein frohes neues Jahr.
Ich habe mir mal Deinen Code angeschaut. Dies ist aus der Procedure Leben_versetzen.
Delphi-Quellcode:
Wenn Du dir das einmal genauer anschaust, wirst Du wahrscheinlich
SetLength(Lebensform1, Length(LebenTemp)+8);
for iIndex := 0 to Length(LebenTemp)-1 do begin Lebensform1[iIndex].ix := LebenTemp[iIndex].ix; Lebensform1[iIndex].iy := LebenTemp[iIndex].iy; Lebensform1[iIndex].iNahrung := LebenTemp[iIndex].iNahrung; Lebensform1[iIndex].iWasser := LebenTemp[iIndex].iWasser; Lebensform1[iIndex].iSchwanger := LebenTemp[iIndex].iSchwanger; Lebensform1[iIndex].bFortpflanzen := LebenTemp[iIndex].bFortpflanzen; end; auch feststellen, dass die letzten 8 Werte des Arrays Lebensform1 nicht initialisiert werden. In den .ix und .iy Feldern stehen irgendwelche undefinierten Werte und das führt zu Problemen in der Procedure
Delphi-Quellcode:
Wenn da sehr große negative Werte für ix und iy stehen
procedure Bewegen(var Objekt: TLebensform);
var i: integer; begin repeat case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; until Objekt.ix > 1; repeat case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; until Objekt.iy > 1; end; kann es eine Zeit lang brauchen bis .ix und .iy größer als 1 sind. Wenn dann Dein Timer immer noch Problem machen sollte, kannst Du ihn ja während der Berechnung uns Zeichnung deaktivieren.
Delphi-Quellcode:
.. und noch ein Nachtrag.
procedure TForm1.Timer1Timer(Sender: TObject);
begin (sender as TTimer).Enabled:=false; Lebensform_versetzen; Welt_aendern; Weltzeichnen; Bildzeichnen; TreeView_anpassen; (sender as TTimer).Enabled:=true; end; Wenn Du Deine Unterprogramme zu Methoden Deiner Form machst. Dann kannst Du dir Konstrukte wie diese:
Delphi-Quellcode:
Würde dann so aussehen:
procedure TreeView_anpassen;
var i: integer; begin Form1.TreeView1.Items.Clear; for i:= 0 to Length(Lebensform1)-1 do begin Form1.Treeview1.Items.Add(nil,'Lebensform ' + inttostr(i+1)); Form1.Treeview1.Items.Add(nil,'X = ' + inttostr(Lebensform1[i].ix)); Form1.Treeview1.Items.Add(nil,'Y = ' + inttostr(Lebensform1[i].iy)); Form1.Treeview1.Items.Add(nil,'Nahrung = ' + inttostr(Lebensform1[i].iNahrung)); Form1.Treeview1.Items.Add(nil,'Wasser = ' + inttostr(Lebensform1[i].iWasser)); end; Form1.Treeview1.Items.Add(nil,'FeldWasser ' + inttostr(Welt[0,0].iWasser)); Form1.Treeview1.Items.Add(nil,'FeldNahrung ' + inttostr(Welt[0,0].iNahrung)); end;
Delphi-Quellcode:
.. und hat den Vorteil, wenn Du das Formular mal umbenennst
procedure TForm1.TreeView_anpassen;
var i: integer; begin TreeView1.Items.Clear; for i:= 0 to Length(Lebensform1)-1 do begin Treeview1.Items.Add(nil,'Lebensform ' + inttostr(i+1)); Treeview1.Items.Add(nil,'X = ' + inttostr(Lebensform1[i].ix)); Treeview1.Items.Add(nil,'Y = ' + inttostr(Lebensform1[i].iy)); Treeview1.Items.Add(nil,'Nahrung = ' + inttostr(Lebensform1[i].iNahrung)); Treeview1.Items.Add(nil,'Wasser = ' + inttostr(Lebensform1[i].iWasser)); end; Treeview1.Items.Add(nil,'FeldWasser ' + inttostr(Welt[0,0].iWasser)); Treeview1.Items.Add(nil,'FeldNahrung ' + inttostr(Welt[0,0].iNahrung)); end; von Form1 nach Simulation o.ä. Du im QuellCode nicht mehr allzuviel ändern mußt. Grüße Klaus |
Re: Hilfe bei einer Simulation
Zitat:
Delphi-Quellcode:
Dies funktioniert auch. Dafür hatte ich das TreeView überhaupt erst eingeführt, damit ich die Werte welche die "Lebensformen" haben überprüfen kann. Insgesamt läuft das Programm so wie ich es hier online gestellt hab. Wie gesagt, das Problem ist einfach die Zeit zur Berechnung der gesammten Aktionen insgesamt.
iIndez := 0;
for iIndex := -1 to 1 do begin for iIndey := -1 to 1 do begin if (iIndey = 0) and (iIndex = 0) then else begin Lebensform1[Length(LebenTemp)+iIndez].ix := Lebensform1[i].ix-iIndex; Lebensform1[Length(LebenTemp)+iIndez].iy := Lebensform1[i].iy-iIndey; Lebensform1[Length(LebenTemp)+iIndez].iNahrung := 0; Lebensform1[Length(LebenTemp)+iIndez].iWasser := 0; Lebensform1[Length(LebenTemp)+iIndez].iSchwanger := 0; Lebensform1[Length(LebenTemp)+iIndez].bFortpflanzen := false; iIndez := iIndez+1; end; end; end; Hab jetzt gelesen, dass man Threats machen kann. Leider hab ich damit noch keine Erfahrung. vieleicht kann mal jemand, der sowas schonmal gemacht hat über den Code schauen und mir sagen, wie man das anlegen kann. Danke BAMatze |
Re: Hilfe bei einer Simulation
Habe mal versucht nach einem Beispiel von dieser Seite:
![]() Hier der neue Quellcode:
Delphi-Quellcode:
Hoffe jemand sieht meinen Fehler und kann ihn mir mitteilen.unit MainLeben; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ComCtrls; type TForm1 = class(TForm) Panel1: TPanel; Panel2: TPanel; PaintBox1: TPaintBox; Timer1: TTimer; Button1: TButton; TreeView1: TTreeView; procedure FormCreate(Sender: TObject); procedure PaintBox1Paint(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private-Deklarationen } Bmp: Tbitmap; public { Public-Deklarationen } end; const LEb1AnfZahl = 5; Leb1Bew = 10; Leb1FortPflanzungsWasser = 200; Leb1FortPflanzungsNahrung = 200; Leb1NahrungOhneBewegung = 5; Leb1WasserOhneBewegung = 5; Leb1Schwanger = 3; type TLebensform = record ix, iy, iNahrung, iWasser, iBewegung, iSchwanger: integer; bFortpflanzen: boolean; end; PLebensform = ^TLebensform; type TOrt = record iNahrung, iWasser, iSchwierigkeit: integer; end; var Form1: TForm1; Lebensform1: array of TLebensform; Welt: array of array of TOrt; brun: integer = 1; implementation procedure Bewegen(var Objekt: TLebensform); begin repeat case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; until Objekt.ix > 1; repeat case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; until Objekt.iy > 1; end; procedure Feld_ueberpruefen(Var Objekt: TLebensform); begin if (Welt[Objekt.ix-1,Objekt.iy-1].iNahrung > 0) and (Objekt.iBewegung >0) then begin Objekt.iNahrung := Objekt.iNahrung + Welt[Objekt.ix-1,Objekt.iy-1].iNahrung; Welt[Objekt.ix-1,Objekt.iy-1].iNahrung := 0; Objekt.iBewegung := Objekt.iBewegung -1; end; if (Welt[Objekt.ix-1,Objekt.iy-1].iWasser > 0) and (Objekt.iBewegung >0) then begin Objekt.iWasser := Objekt.iWasser + Welt[Objekt.ix-1,Objekt.iy-1].iWasser; Welt[Objekt.ix-1,Objekt.iy-1].iWasser := 0; Objekt.iBewegung := Objekt.iBewegung -1; end; end; procedure Lebensform_versetzen; var i, iIndex, iIndey, iIndez: integer; LebenTemp: array of TLebensform; begin for i := 0 to Length(Lebensform1)-1 do begin Lebensform1[i].iBewegung := Leb1Bew; if (Lebensform1[i].iNahrung > (Leb1FortPflanzungsNahrung + (3*Leb1NahrungOhneBewegung))) and (Lebensform1[i].iWasser > (Leb1FortPflanzungsWasser + (3*Leb1WasserOhneBewegung))) and (Lebensform1[i].bFortpflanzen = false) then Lebensform1[i].bFortpflanzen := true; if Lebensform1[i].bFortpflanzen = true then begin if Lebensform1[i].iSchwanger < Leb1Schwanger then begin Lebensform1[i].iNahrung := Lebensform1[i].iNahrung - Leb1NahrungOhneBewegung; Lebensform1[i].iWasser := Lebensform1[i].iWasser - Leb1WasserOhneBewegung; Lebensform1[i].iSchwanger := Lebensform1[i].iSchwanger + 1; end else begin Lebensform1[i].iSchwanger := 0; Lebensform1[i].bFortpflanzen := false; Lebensform1[i].iNahrung := Lebensform1[i].iNahrung - Leb1FortPflanzungsNahrung; Lebensform1[i].iWasser := Lebensform1[i].iWasser - Leb1FortPflanzungsWasser; SetLength(LebenTemp,Length(Lebensform1)); for iIndex := 0 to Length(LebenTemp)-1 do begin LebenTemp[iIndex].ix := Lebensform1[iIndex].ix; LebenTemp[iIndex].iy := Lebensform1[iIndex].iy; LebenTemp[iIndex].iNahrung := Lebensform1[iIndex].iNahrung; LebenTemp[iIndex].iWasser := Lebensform1[iIndex].iWasser; LebenTemp[iIndex].iSchwanger := Lebensform1[iIndex].iSchwanger; LebenTemp[iIndex].bFortpflanzen := Lebensform1[iIndex].bFortpflanzen; end; SetLength(Lebensform1, Length(LebenTemp)+8); for iIndex := 0 to Length(LebenTemp)-1 do begin Lebensform1[iIndex].ix := LebenTemp[iIndex].ix; Lebensform1[iIndex].iy := LebenTemp[iIndex].iy; Lebensform1[iIndex].iNahrung := LebenTemp[iIndex].iNahrung; Lebensform1[iIndex].iWasser := LebenTemp[iIndex].iWasser; Lebensform1[iIndex].iSchwanger := LebenTemp[iIndex].iSchwanger; Lebensform1[iIndex].bFortpflanzen := LebenTemp[iIndex].bFortpflanzen; end; iIndez := 0; for iIndex := -1 to 1 do begin for iIndey := -1 to 1 do begin if (iIndey = 0) and (iIndex = 0) then else begin Lebensform1[Length(LebenTemp)+iIndez].ix := Lebensform1[i].ix-iIndex; Lebensform1[Length(LebenTemp)+iIndez].iy := Lebensform1[i].iy-iIndey; Lebensform1[Length(LebenTemp)+iIndez].iNahrung := 0; Lebensform1[Length(LebenTemp)+iIndez].iWasser := 0; Lebensform1[Length(LebenTemp)+iIndez].iSchwanger := 0; Lebensform1[Length(LebenTemp)+iIndez].bFortpflanzen := false; iIndez := iIndez+1; end; end; end; //Form1.Button1Click(nil); end; end else begin while Lebensform1[i].iBewegung > 0 do begin Feld_ueberpruefen(Lebensform1[i]); Bewegen(Lebensform1[i]); end; end; end; end; function ThreadLeben(p: pointer):integer; begin result := 0; while brun = 0 do begin ShowMessage('Hallo'); Lebensform_versetzen; sleep(0); end; end; {$R *.dfm} procedure TreeView_anpassen; var i: integer; begin Form1.TreeView1.Items.Clear; for i:= 0 to Length(Lebensform1)-1 do begin Form1.Treeview1.Items.Add(nil,'Lebensform ' + inttostr(i+1)); Form1.Treeview1.Items.Add(nil,'X = ' + inttostr(Lebensform1[i].ix)); Form1.Treeview1.Items.Add(nil,'Y = ' + inttostr(Lebensform1[i].iy)); Form1.Treeview1.Items.Add(nil,'Nahrung = ' + inttostr(Lebensform1[i].iNahrung)); Form1.Treeview1.Items.Add(nil,'Wasser = ' + inttostr(Lebensform1[i].iWasser)); end; Form1.Treeview1.Items.Add(nil,'FeldWasser ' + inttostr(Welt[0,0].iWasser)); Form1.Treeview1.Items.Add(nil,'FeldNahrung ' + inttostr(Welt[0,0].iNahrung)); end; procedure Bildloeschen; var i: integer; begin Form1.Bmp.Canvas.Pen.Color := clWhite; for i := 0 to Length(Lebensform1)-1 do Form1.Bmp.Canvas.Rectangle(Lebensform1[i].ix-1,Lebensform1[i].iy-1,Lebensform1[i].ix+1,Lebensform1[i].iy+1); Form1.PaintBox1.Repaint; end; procedure Bildzeichnen; var i: integer; begin Form1.Bmp.Canvas.Pen.Color := clBlue; for i := 0 to Length(Lebensform1)-1 do Form1.Bmp.Canvas.Rectangle(Lebensform1[i].ix-1,Lebensform1[i].iy-1,Lebensform1[i].ix+1,Lebensform1[i].iy+1); Form1.PaintBox1.Repaint; end; procedure Weltinitialisieren; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin Welt[i,j].iNahrung := random(3); Welt[i,j].iWasser := random(3); Welt[i,j].iSchwierigkeit := random(3); end; end; end; procedure Weltzeichnen; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) < 20) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clgray; if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) in [20..50]) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clYellow; if ((Welt[i,j].iNahrung + Welt[i,j].iWasser) > 50) then Form1.Bmp.Canvas.Pixels[i+1,j+1] := clgreen; end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin if Button1.Caption = 'Simulation starten' then begin brun := 0; Timer1.Enabled := true; Button1.Caption := 'Simulation stoppen'; end else begin brun := 1; Timer1.Enabled := false; Button1.Caption := 'Simulation starten'; end; end; procedure TForm1.FormCreate(Sender: TObject); var i: integer; p: Pointer; ThreadLebenID: LongWord; begin getMem(p, Sizeof(TLebensform)); Bmp := TBitmap.create; Bmp.Width := 505; Bmp.Height := 497; SetLength(Welt, Bmp.Width, Bmp.Height); randomize; SetLength(Lebensform1,1); for i := 0 to 0 do begin Lebensform1[i].ix := random(20)+1; Lebensform1[i].iy := random(20)+1; Lebensform1[i].iNahrung := 0; Lebensform1[i].iWasser := 0; Lebensform1[i].iSchwanger := 0; Lebensform1[i].iBewegung := Leb1Bew; end; Weltinitialisieren; Weltzeichnen; Bildzeichnen; CloseHandle(BeginThread(nil, 0, @ThreadLeben, p, 0, ThreadLebenID)); TreeView_anpassen; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin BitBlt(Paintbox1.Canvas.Handle, 0, 0, Paintbox1.Width, Paintbox1.Height, Bmp.Canvas.Handle, 0, 0, SRCCOPY); end; procedure Welt_aendern; var i, j: integer; begin for i := 0 to 504 do begin for j := 0 to 496 do begin Welt[i,j].iNahrung := Welt[i,j].iNahrung + random(3); Welt[i,j].iWasser := Welt[i,j].iWasser + random(3); end; end; end; procedure TForm1.Timer1Timer(Sender: TObject); begin //Lebensform_versetzen; Welt_aendern; Weltzeichnen; Bildzeichnen; TreeView_anpassen; end; end. Danke |
Re: Hilfe bei einer Simulation
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich nochmal. Ich gehe immer noch davon aus, dass im Array Lebensform1 nicht alle Elemente initialisiert wurden denn woher sollten sonst Werte von -53433 für .ix kommen. (siehe Bild im Anhang). Damit die Procedure bewegen von diesem Wert auf einen Wert > 1 kommt, da geht schon einige Zeit ins Land.
Delphi-Quellcode:
Wenn das Problem nicht behoben wird, nützt auch ein Thread nichts.
procedure Bewegen(var Objekt: TLebensform);
var i: integer; begin repeat case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; until Objekt.ix > 1; repeat case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; until Objekt.iy > 1; end; Grüße Klaus |
Re: Hilfe bei einer Simulation
Liste der Anhänge anzeigen (Anzahl: 1)
Hmm das kann ich mir gerade auch nicht erklären. Habe jetzt mal das Programm so abgeändert, dass es genau nach der ersten Teilung stoppt und dann im TreeView alle Werte von den "Lebensformen" ausgegeben. Ich stelle dir die gesamte Datei nochmal rein, dann kannst du selber schauen. Ich hoffe es liegt nicht an unterschiedlichen Betriebssystemen. Ich verwende hier Vista.
|
Re: Hilfe bei einer Simulation
Hallo BamMatze,
ich hab mir die Quellen jetzt nicht so genau angeschaut aber mir fehlt noch ein TreeView1.Items.BeginUpdate bzw. TreeView1.Items.EndUpdate vor bzw. nach dem aktualisieren des Treeview. Das sollte das aktualisieren des Baums signifikant beschleunigen. cu cg |
Re: Hilfe bei einer Simulation
In dieser Methode kannst du dich schon mal recht lange aufhalten:
Delphi-Quellcode:
Nehmen wir mal an, ix ist am Anfang 1 (passiert dann, wenn der Elternteil auf 2 sitzt) und der erste Aufruf von Random(3) gibt 0 zurück, dann kann es recht lange dauern, bis ix > 1 wird. Wenn das Ganze erstmal ins Negative abdriftet, brauchst du schon eine ganze Menge 2er Ergebnisse um über 1 zu kommen, denn jede 0 zieht dich wieder zurück. Da du eh nur Werte > 1 akzeptierst, kannst due das Ganze auch direkt nach unten begrenzen anstatt das dem Zufallsgenerator zu überlassen.
procedure Bewegen(var Objekt: TLebensform);
var i: integer; begin repeat case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; until Objekt.ix > 1; repeat case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; until Objekt.iy > 1; end;
Delphi-Quellcode:
Nebenbei, was ist eigentlich mit den oberen Schranken?
procedure Bewegen(var Objekt: TLebensform);
begin case random(3) of 0: Objekt.ix := Objekt.ix - 1; 1: Objekt.ix := Objekt.ix; 2: Objekt.ix := Objekt.ix + 1; end; if Object.ix < 2 then Object.ix := 2; case random(3) of 0: Objekt.iy := Objekt.iy - 1; 1: Objekt.iy := Objekt.iy; 2: Objekt.iy := Objekt.iy + 1; end; if Object.iy < 2 then Object.iy := 2; end; Ein weiterer Geschwindigkeitsvorteil läßt sich herausholen, wenn du die Sequenz
Delphi-Quellcode:
durch folgendes ersetzt:
SetLength(LebenTemp,Length(Lebensform1));
for iIndex := 0 to Length(LebenTemp)-1 do begin LebenTemp[iIndex].ix := Lebensform1[iIndex].ix; LebenTemp[iIndex].iy := Lebensform1[iIndex].iy; LebenTemp[iIndex].iNahrung := Lebensform1[iIndex].iNahrung; LebenTemp[iIndex].iWasser := Lebensform1[iIndex].iWasser; LebenTemp[iIndex].iSchwanger := Lebensform1[iIndex].iSchwanger; LebenTemp[iIndex].bFortpflanzen := Lebensform1[iIndex].bFortpflanzen; end; SetLength(Lebensform1, Length(LebenTemp)+8); for iIndex := 0 to Length(LebenTemp)-1 do begin Lebensform1[iIndex].ix := LebenTemp[iIndex].ix; Lebensform1[iIndex].iy := LebenTemp[iIndex].iy; Lebensform1[iIndex].iNahrung := LebenTemp[iIndex].iNahrung; Lebensform1[iIndex].iWasser := LebenTemp[iIndex].iWasser; Lebensform1[iIndex].iSchwanger := LebenTemp[iIndex].iSchwanger; Lebensform1[iIndex].bFortpflanzen := LebenTemp[iIndex].bFortpflanzen; end; iIndez := 0;
Delphi-Quellcode:
iIndez := Length(Lebensform1); SetLength(Lebensform1, iIndez + 8); Allerdings wird dir das Ganze irgendwann auch nichts mehr nützen, da bei entsprechend vielen Lebensformen der Berechnungsuafwand halt immer größer wird und auch mehr Zeit beansprucht. In dem Fall muss das Simulationsintervall Wohl oder Übel erhöht werden. |
Re: Hilfe bei einer Simulation
Dein größtes Problem sind die dynamischen Arrays. Dort muss das Array immer komplett umkopiert werden, wenn sich die Größe ändert. Dies ist erforderlich, damit die Elemente garantiert hintereinander liegen und man so indiziert darauf zugreifen kann.
Dieser direkte Indexzugriff ist für das Programmieren ja ganz angenehm, aber hier führt es eben zu den erwähnten Nachteilen. Bau dir verkette Listen, damit wirst du auf jeden Fall glücklicher. Trotzdem wird dir auch ein Speicherproblem entgegen treten. Deine Struktur wächst immens, das solltest du ebenfalls bedenken. Die Verwendung von Threads klingt ja ganz interessant, allerdings sollte man in einer Anwendung niemals mehr als 15 Threads benutzen. Das ist natürlich nur ein Richtwert, bei dir wird das dann aber eher >1000 Threads und das wird Windows nicht lange mitmachen. Also du siehst, dieses Problem kann man nur mit einer adäquaten Datenstruktur lösen. Und diese muss gut durchdacht sein. |
Re: Hilfe bei einer Simulation
Liste der Anhänge anzeigen (Anzahl: 1)
Schade das du dich nicht mehr gemeldet hast. Ich habe mich mal dran versucht und das ganze ein bischen umgebaut. Hoffe ich habe nicht zu viel von der urspünglichen Funktionalität rausgenommen.
|
Re: Hilfe bei einer Simulation
Hallo Omata,
schaue mir jetz mal an, was du mir geschickt hast, hab gestern um die Zeit schon im Bett gelegen, konnte mich also nicht mehr melden :D. Aber danke schon mal für deine Hilfe. |
Re: Hilfe bei einer Simulation
@Omata super Ding das.
Genau so hab ich mir das vorgestellt. Hab gerade nur mal laufen lasse, bis 50000 Lebensformen existiert haben und in der Rechnerperformence war über haupt nichts auszusetzen. Muss zwar jetzt erstmal deinen Quellcode analysieren, um zu verstehen, wie du die Effektivietät mehr als verfünfzig facht hast, aber noch mal ein großes Danke. BAMatze |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz