Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Problem mit game of life


Schoppi - Sa 20.02.16 10:59
Titel: Problem mit game of life
Nach langem herumprobieren habe ich mich nun entschlossen mal hier zu schreiben, weil ich einfach nicht weiterkomme.





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:
procedure TForm1.FormClick(Sender: TObject);
const xmax=100;
      ymax=100;
var gitter:array[1..xmax,1..ymax] of boolean;
    alt:array[1..xmax,1..ymax] of boolean;
    i,y,s,u:integer;
begin

for i:=1 to xmax do           //alles auf false setzen
  for y:=1 to ymax do
    gitter[i,y]:=false;

for i:=1 to xmax do           //eingabe frür startleben
  for y:=1 to ymax do
    if StringGrid1.Cells[i,y]='X' then gitter[i,y]:=true;



for u:=1 to 200 do
begin

for i:=1 to xmax do
      for y:=1 to ymax do
        alt[i,y]:=gitter[i,y];

for i:=1 to xmax do
  for y:=1 to ymax do
    begin
    s:=0;
      if alt[i,y-1]=true then s:=s+1;     //ermitteln von nachbarn
      if alt[i,y+1]=true then s:=s+1;
      if alt[i-1,y]=true then s:=s+1;
      if alt[i-1,y-1]=true then s:=s+1;
      if alt[i-1,y+1]=true then s:=s+1;
      if alt[i+1,y]=true then s:=s+1;
      if alt[i+1,y-1]=true then s:=s+1;
      if alt[i+1,y+1]=true then s:=s+1;
    if alt[i,y]=true then                 //zelle lebt
      begin
      if s<2 then gitter[i,y]:=false;      //bedingungen für lebende
      if s>3 then gitter[i,y]:=false;
      if gitter[i,y]=true then StringGrid2.Cells[i,y]:='X' else StringGrid2.Cells[i,y]:='';
      end
    else
      begin                                    //zelle tot
      if s=3 then gitter[i,y]:=true;      //bedingungen für tote
      if gitter[i,y]=true then StringGrid2.Cells[i,y]:='X' else StringGrid2.Cells[i,y]:='';
      end;
    end;


end;
end;




Ich habe zwei Stringgrids, eins zur Eingabe und eins zur Ausgabe. Momentan ist es allerdings so, dass er nur das Bild nach dem Ablauf der 200 Generationen im 2. StringGrid anzeigt. Ich würde aber auch gern "bewegte Bilder" haben wie man sie sonst auch überall sieht. Ich habe es schon mit sleep() versucht, das problem ist aber ,dass das Programm sehr sehr langsam wird. Ich bin noch recht am Anfang beim programmieren, also bitte ich jetzt mal hier um Hilfe.

Vielen Dank im Vorraus,
Schoppi


Mathematiker - Sa 20.02.16 11:20

Hallo Schoppi,
und :welcome:

In deiner Lösung rechnest du immer 200 Generationen in einer Zählschleife aus.
Während dieser Rechnung erfolgt keine "sichtbare" Aktualisierung des Stringgrids.
Eine Lösung wäre

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
for u:=1 to 200 do
begin
  // deine Berechnung
  application.processmessages; 
end;
end;

Durch application.processmessages wird kurzzeitig deine Routine unterbrochen und das Formular erneut gezeichnet.
Diese Lösung ist aber nicht besonders schön, da du keine Möglichkeit hast die Rechnung zu unterbrechen. Eine einfache Möglichkeit wäre, dass du in einer Timerroutine jeweils die nächste Generation berechnest.

Hier in der EE gibt es mehrere (schönere) Lösungen zu "Game of Life", u.a. http://www.entwickler-ecke.de/viewtopic.php?t=114059&highlight=game+life. Mehr findest du über "Suchen".

Beste Grüße
Mathematiker


ub60 - Sa 20.02.16 11:21

Einmal am Ende der 200er-Schleife "Application.ProcessMessages" einfügen.

ub60

Edit: oh, da war der Mathematiker mal wieder eine Minute schneller :? .


Schoppi - Sa 20.02.16 11:40

Ok, vielen Dank jetzt funktioniert es!! :dance2:


Delphi-Laie - Sa 20.02.16 22:46

1. Die Zählschleife bis 200 ist für mich nicht nachvollziehbar. Was kommt dann? Man möchte doch das Spielfeld sehen, bis es - in der Regel - ausgebrannt ist, mit konstanten Klumpen, blinkenden Ampeln und anderen kümmerlich-jämmerlichen Resten. Das ist in 200 Schleifendurchgängen kaum erledigt. Deshalb ist eine Nichtzählschleife besser.

2. Statt neun Abfragen kann man auch einfach eine Summe mit 9 Summanden (je Nachbarfeld ein Summand) bilden.

3. Statt s:=s+1 ist der Inkrementor "inc(s)" eleganter.

4. Vergleich auf true (=true) ist bestenfalls redundant, genaugenommen sogar unsinnig. Mit "if" wird bereits auf "true" (bzw. "false") geprüft.