Autor |
Beitrag |
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 07.06.14 11:07
Jann1k hat folgendes geschrieben : | Also irgendwie hakt es ja ganz schön bei dir. Hidden möchte nur, dass du jedesmal aus atmpBoard[x, y] ein atmpBoard[x mod 97, y mod 97] machst. Durch die modulo Funktion bleiben die Indices immer im Bereich [0..96] und du kriegst deinen Torus. Die Konstruktion mit dem Rand voller toter Zellen kannst du dir dann sparen. |
Und warum habe ich das nicht längst gemacht? Geht ja!
Jann1k hat folgendes geschrieben : | Also irgendwie hakt es ja ganz schön bei dir. |
Jetzt nicht mehr!
Sorry, aber ich konnte (kann) mir das einfach nicht vorstellen! Ein zweidimensionales Array ist ja kein Problem, aber mit so etwas habe ich mich noch nie beschäftigt.
Jetzt funktioniert es so, wie ich mir das wünsche: Eine "Kugel"-Welt ist einfach eleganter, denn da werden Objekte am Rand nicht einfach aufgelöst, sondern treten gegenüber wieder ein - eine Kugel eben. Danke!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 07.06.14 12:27
Zitat: | catweasel hat folgendes geschrieben : | Der Quellcode ist nicht kommentiert, aber auch nicht sonderlich schwierig... |
Jedenfalls ist er völlig anders als mein Code! |
Ja, weil der Ansatz ein Anderer ist
Dein Ansatz ist : Array nehmen und analysieren und Ergennisse temporär speichern und dann die Ergebnisse in das Array zurückschreiben.
Und das macht es unnötig kompliziert. Vergegenwärtige dir das das "temp" array wenn es gefüllt ist, im Prinzip schon die nächste Generation darstellt. Wenn ich WorldA berechne dient WorldA quasi als temp array für WorldB. (Geschieht bei WorldA.Process(WorldB) )
Da pro Generation nr ein Array einmal glesen/geschrieben wird ist es auch schneller als Arry -> temp und dann temp -> array.
Die Sache mit den Koordinaten und dem Torus steckt in TWorldClass.Transform() die dann von TWorldClass.CountNeighbors() aufegrufen wird.
Da steckt der ganze Gag drin
Aber wenn du willst kann ich gerne den Rest des Codes kommentieren...
Wie du siehst ist wes wirklich simpler. Der ganze Quellcode ist weniger als deine TimerRoutine...
Evtl. könntest du auch die Timer Prozedur in kleinere Subroutinen zerlegen. Das würde die Übersichtlichkeit erhöhen.
Ich persönlich vermeide Methodenkörper mit mehr als 30 Zeilen.
Ist jetzt wirklich nur aus Neugier gefragt: Wie lange programmierst du schon mit Delphi?
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 07.06.14 13:57
catweasel hat folgendes geschrieben : | Wenn ich WorldA berechne dient WorldA quasi als temp array für WorldB. (Geschieht bei WorldA.Process(WorldB) )
Da pro Generation nr ein Array einmal glesen/geschrieben wird ist es auch schneller als Arry -> temp und dann temp -> array. |
Naja, jetzt läuft es und ich belasse es so!
catweasel hat folgendes geschrieben : | Evtl. könntest du auch die Timer Prozedur in kleinere Subroutinen zerlegen. Das würde die Übersichtlichkeit erhöhen. |
Ist sicher sinnvoll und werde ich auch umsetzen.
catweasel hat folgendes geschrieben : | Ist jetzt wirklich nur aus Neugier gefragt: Wie lange programmierst du schon mit Delphi? |
Schon etliche Jahre, aber ich habe nur wenige Spiele programmiert. Und über ein torusförmiges Array habe ich mir noch nie Gedanken gemacht, ich brauchte es schlicht nicht.
lg
galagher
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 07.06.14 14:25
Zitat: | Naja, jetzt läuft es und ich belasse es so! |
Ja klar. Wenns einaml fertig ist
Ich wollte dir eigentlich nur aufzeigen wie der objektorientierte Ansatz hier die Aufgabenstellung radikal vereinfachen kann.
Mann müsste noch nichtmal Objekte nehmen. Das ganze ginge auch mit ein paar globalen Variablen....
Mal so gefragt: Wenn du das nochmal programmieren müsstest, würdest du wieder den gleichen Ansatz wählen?
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 08.06.14 09:41
catweasel hat folgendes geschrieben : | Mal so gefragt: Wenn du das nochmal programmieren müsstest, würdest du wieder den gleichen Ansatz wählen? |
Ja, würde ich. Es fällt mir ganz einfach leichter, ein quadratisches oder rechteckiges Spielfeld, das ich am Bildschirm ja sehen kann, im Kopf in ein zweidimensionales Array umzurechnen und umgekehrt.
Was ich mir nicht vorstellen konnte, war das Verbinden der Ränder. Aber dazu muss ich sagen, dass ich Mathematik seit der Schulzeit nicht mag. War immer der blanke Horror! 
_________________ 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: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 08.06.14 10:47
Hallo,
galagher hat folgendes geschrieben : | Aber dazu muss ich sagen, dass ich Mathematik seit der Schulzeit nicht mag. War immer der blanke Horror!  |
Richtig!
Augustinus: "Der gute Christ soll sich hüten vor den Mathematikern und all denen, die leere Voraussagen zu machen pflegen, schon gar dann, wenn diese Vorhersagen zutreffen. Es besteht nämlich die Gefahr, dass die Mathematiker mit dem Teufel im Bunde den Geist trüben und in die Bande der Hölle verstricken."
Paul Epstein: "Die Mehrheit bringt der Mathematik Gefühle entgegen, wie sie nach Aristoteles durch die Tragödie geweckt werden sollen, nämlich Mitleid und Furcht. Mitleid mit denen, die sich mit der Mathematik plagen müssen, und Furcht, dass man selbst einmal in diese gefährliche Lage geraten könne."
Robert Niemann: "Mathematik ist nichts für den Wühltisch - Mathematik ist etwas für eine Handvoll Erleuchtete. Und das soll auch so bleiben."
In dem Sinne. Lass dich nicht von der Mathematik ärgern. Als Programmierer kann man darauf sicher verzichten.
Beste Grüße
Mathematiker
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: So 08.06.14 12:31
Diese Männer habane natürlich völlig Recht
Mthematik ist natürlich nicht nur Teufelszeug (Zubersprüche des Herrn Binomi), sondern erfüllt sogar alle hinreichenden Bedingungen für total nerdige Freakscheisse
Dafür können Mthematiker ber sehr gut Löwen fangen...
(Bei meiner Version arbeit ich auch mit 2D arrays, ich meinte der Ansatz mit dem Double buffering)
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: So 08.06.14 22:00
Hallo,
catweasel hat folgendes geschrieben : | Mthematik ... erfüllt sogar alle hinreichenden Bedingungen für total nerdige Freakscheisse |
Das ist nicht mehr "lustig"!
Mathematiker
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Mo 09.06.14 02:18
Leider bekomme ich das immer zu hören wenn ich mit Mathematik anfange ...
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Sa 14.06.14 09:35
Hallo,
ich habe ein wenig an der "Berechnung" herumgeschraubt.
Meine Uralt Version mit 3 _Zeilen als Zwischenspeicher ist heutzutage nicht mehr schnell
Ich habe catweasel Einwand, gegen das unnötige Kopieren beherzigt, aber schöner wird es durch Zeiger auf die Boards nicht.
Tatsächlich braucht es bei mir ohne Ausgabe pro Koordinatenpunkt nur 11 CPU-Takte.
Wie immer gilt, Entscheidungen fallen auch einer CPU schwer  , also mittels cSurvives die möglichen Werte vorgeben.
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:
| Program Gol; {$IFDEF FPC} {$Mode delphi} {$ELSE} {$Apptype Console} {$ENDIF} uses sysutils,crt;
const colMax = 79; rowMax = 23; type tFeld = byte; tRow = array[0..colMax+1] of tFeld; tprow = ^tRow; tBoard = array[0..rowMax+1] of tRow; tpBoard = ^tBoard; tpBoards = array[0..1] of tpBoard; const dr = sizeOf(trow); type tIntArr = array[0..2*dr+2] of tFeld; tpIntArr = ^tIntArr;
var aBoard,bBoard : tBoard; pBoards :tpBoards; gblAktBoard : integer;
gblGenCount : integer;
function Survive(p: tpIntArr):byte; const cSurvives : array[boolean,0..8] of integer= ((0,0,0,1,0,0,0,0,0), (0,0,1,1,0,0,0,0,0)); var sum : integer; begin sum := integer(p[ 0])+integer(p[ 1]) +integer(p[ 2]); sum := sum+ integer(p[ dr+0]) +integer(p[ dr+2]); sum := sum +integer(p[2*dr+0])+integer(p[2*dr+1])+integer(p[2*dr+2]);
survive := cSurvives[p[dr+1]<>0,sum]; end;
procedure Raender; var p0 : tpIntArr; row: integer; begin p0 := @pBoards[gblAktBoard]^[1,0]; For row := 1 to rowMax do begin p0^[0] := p0^[colMax]; p0^[colmax+1] := p0^[1]; p0 := Pointer(PtrUint(p0)+SizeOf(tRow)); end; move(pBoards[gblAktBoard]^[1,0],pBoards[gblAktBoard]^[rowMax+1,0],sizeof(trow)); move(pBoards[gblAktBoard]^[rowMax,0],pBoards[gblAktBoard]^[0,0],sizeof(trow)); end;
procedure NextGen; var p0,p1 : tpIntArr; col,row: integer; begin Raender; For row := 1 to rowMax do begin p0 := @pBoards[gblAktBoard]^[row-1,0]; p1 := @pBoards[1-gblAktBoard]^[row,0]; For col := 1 to colMax do p1[col] := Survive(@p0[col-1]); end; gblAktBoard :=1-gblAktBoard; inc(gblGenCount); end;
procedure PrintGen; const cChar: array[0..1] of char = (' ','#'); var p0 : tpIntArr; col,row: integer; s : string; begin setlength(s,colmax); gotoxy(1,1); writeln(gblGenCount:10); For row := 1 to rowMax do begin p0 := @pBoards[gblAktBoard]^[row,0];; For col := 1 to colMax do s[col] := cChar[p0[col]]; writeln(s); end; end;
procedure Init; var col,row : integer; begin randseed := 1; clrscr; fillchar(aBoard,SizeOf(aBoard),#0); pBoards[0] := @aBoard; pBoards[1] := @bBoard; For row := 1 to rowMax do For col := 1 to colMax do aBoard[row,col]:= Byte(random>0.9); gblAktBoard := 0; end;
var cnt : integer; T1,T0 :TDateTime; begin Init; cnt := 100000; T0 := Time; repeat PrintGen; NextGen; dec(cnt); until (cnt <= 0) OR keypressed; T1 := Time; Writeln((T1-t0)*86400*1000:0:3,' ms'); end. |
Wie so oft ist die Ausgabe die Bremse schlechthin.
Es lohnt sich also bei grafischer Ausgabe, zwischen den beiden Boards zu vergleichen und nur die Unterschiede auszugeben.
Bei sehr großen Boards könnte sogar die Bestimmung von aktiven Lebenszonen etwas bringen.
Gruß Horst
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: So 15.06.14 22:56
Zitat: | Wie so oft ist die Ausgabe die Bremse schlechthin.
Es lohnt sich also bei grafischer Ausgabe, zwischen den beiden Boards zu vergleichen und nur die Unterschiede auszugeben.
Bei sehr großen Boards könnte sogar die Bestimmung von aktiven Lebenszonen etwas bringen. |
Hmm bei einer Konsolenanwendung weiss ich nicht ob man da noch etwas optimieren kann, evtl Textausgabe per Assembler, anstelle von writeln. Müsste dann irgendwas mit MOV und dem guten alten INT 21h sein
Ich hatte es ja mit einer VCL Komponente gelöst.
Ich habe festgestellt das hier das OnPaint eines TDrawGrid schnell genug ist. Vorteil ist auch das sich die Zellengröße leicht anpassen kann, man einzele Zellen schön über SelectCell ansprchbar machen kann. Die Scrollbars für große Felder gibts auch gratis dazu; und dann werden auch nir die sichtbaren Zellen gezeichnet.
Das mit der aktiven Lebenszone kann schwierig werden. Ein Glider zum beispiel schleppt seine Zone immer mit sich rum. Einen Test in der Umgebung von zwei Zellen zu machen (Glider trifft auf Rand, die Zelle auf der anderen Seite der Randzelle muss auch gestet werden, deshalb zwei), ist aufwändiger als jede Zelle zu testen.
Wenn ich ein Array darstellen will ist das bei mir die Standardlösung, zumal ja die ACol und ARow Variablen sich gleich bequem als Arrayindizes einsetzen lassen (ausser man hat Fixed Rows/Cols).
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Fiete
      
Beiträge: 617
Erhaltene Danke: 364
W7
Delphi 6 pro
|
Verfasst: Di 17.06.14 11:23
Moin galagher,
vielleicht helfen diese Anregungen
www.entwickler-ecke....highlight=life+fiete
Gruß Fiete
_________________ Fietes Gesetz: use your brain (THINK)
|
|
catweasel
      
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Di 17.06.14 12:22
Jau.
Wenn man mit den Lebensregeln herumspielt kommen interessante Dinge raus.
Versuchmal : Bei ungeraden Nachbarn stirbt die Zelle, bei geraden Nachbarn lebt sie (nachbarn MOD 2 // 0 =leben; 1=tot)
Dann erhältst du die "Kopierwelt"... Zeichne ein Smiley oder sonstwas. Es werden dann Kopien darum erstellt, usw...
Cheers,
Ctweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 29.06.14 20:21
Hallo!
War auf Urlaub ohne Laptop (!) und antworte daher erst jetzt.
Danke für die Tipps, ich werde das eine oder andere eventuell noch einbauen!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
|