Autor Beitrag
galagher
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2556
Erhaltene Danke: 45

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: So 13.07.14 13:01 
Hallo!

Schone wieder habe ich irgendwo einen Denkfehler bei einem torusförmigen Spielfeld! Ich möchte "Wator" programmieren: de.wikipedia.org/wiki/Wator
Erstmal nur mit Fischen, aber schon das klappt nicht. Fische, die über den Rand "schwimmen", tauchen an der gegenüberliegenden Seite nicht wieder auf. Wo ist da der Fehler?
ausblenden volle Höhe 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:
var
  x, y, i: Integer;
  b: Boolean;
begin
(*
  Regeln für Fische
    - Jeder Fisch schwimmt zufällig auf eines der vier angrenzenden Felder,
      sofern es leer ist.
    - Jeder Fisch hat ein Alter; überschreitet dieses die Fisch-Lebenszeit,
      so wird auf einem leeren, angrenzenden Feld ein neuer Fisch geboren.
*)

  {Temporäres Array zunächst "mit Wasser füllen"}
  for x := iBoardMin-1 to iBoardMax+1 do
    for y := iBoardMin-1 to iBoardMax+1 do
      atmpBoard[x, y].clCell := clWater;

  for x := iBoardMin to iBoardMax do
    for y := iBoardMin to iBoardMax do
    begin
      if (aBoard[x, y].clCell = clFish) then
      begin
        case Random(4of
          0if aBoard[x+1, y].clCell = clWater then
             begin
               atmpBoard[x+1, y].clCell := clFish;
             end;
          1if aBoard[x-1, y].clCell = clWater then
             begin
               atmpBoard[x-1, y].clCell := clFish;
             end;
          2if aBoard[x, y+1].clCell = clWater then
             begin
               atmpBoard[x, y+1].clCell := clFish;
             end;
          3if aBoard[x, y-1].clCell = clWater then
             begin
               atmpBoard[x, y-1].clCell := clFish;
             end;
        end;
      end;
    end;

  {Vom temporären Array zurückschreiben}
  for x := iBoardMin-1 to iBoardMax+1 do
    for y := iBoardMin-1 to iBoardMax+1 do
    begin
      aBoard[x, y].clCell :=
        atmpBoard[x mod iBoardMax, y mod iBoardMax].clCell;
    end;

 {Zuletzt zeichnen}
 DrawBoard;
end;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: So 13.07.14 14:55 
Zum einen sind deine Arraygrößen irgendwie verwirrend. Vermutlich liegt dort der Fehler.
Zum anderen ist -1 mod 5 = -1 in Delphi, weil mod nunmal den Rest bei Ganzzahldivision bestimmt, und -1/5 ist nunmal 0 Rest -1. Da in deinem Codeabschntt iBoardMin und iBoardMax nicht angegeben sind, ist dies aber eventuell kein Problem :nixweiss:

Ich würde folgendermaßen vorgehen und den ganzen Torus-Quatsch in einer Klasse verstecken:

ausblenden volle Höhe 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:
type TDoubleBufferedTorusMap = class
  private
    vMap: array [0..1of array of array of TCell;
    vActiveMap: integer;
    vWidth, vHeight: integer;
  public
    constructor Create( width,height: integer );
    function GetActiveCell(x,y: integer): ^TCell; 
    function GetBackupCell(x,y: integer): ^TCell; 
    procedure SwapBuffers(); 
end;

constructor TDoubleBufferedTorusMap.Create( width,height: integer );
begin
  SetLength( vMap[0], width, height );
  SetLength( vMap[1], width, height );
  vActiveMap := 0
  vWidth := width;
  vHeight := height;
end

function TDoubleBufferedTorusMap.GetActiveCell(x,y: integer): ^TCell; 
var posX,posY: integer
begin
  posX := (x + vWidth) mod vWidth;
  posY := (y + vHeight) mod vHeight;
  Result := @vMap[vActiveMap][posX,posY];
end;

function TDoubleBufferedTorusMap.GetBackupCell(x,y: integer): ^TCell; 
var posX,posY: integer
begin
  posX := (x + vWidth) mod vWidth;
  posY := (y + vHeight) mod vHeight;
  Result := @vMap[(vActiveMap+1)mod 2][posX,posY];
end;

procedure TDoubleBufferedTorusMap.SwapBuffers(); 
begin
  vActiveMap := (vActiveMap+1mod 2;
end;


Nun kannst du ganz einfach darauf zugreifen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//--- initialisierung
map := TDoubleBufferedTorusMap.create(100,100);
for X:= 0 to 99 do
  for Y:= 0 to 99 do
    map.GetActiveCell(X,Y).clCell := clWater;

//--- Simulations-Beispiel: rotiere Torus nach unten
while true do
  begin
    for X:= 0 to 99 do
      for Y:= 0 to 99 do
        map.GetActiveCell(X,Y+1).clCell := map.GetBackupCell(X,Y).clCell;
    map.SwapBuffers();
  end;


Mit Potential für schönere Objektorientierung :)

Noch eine weitere Anmerkung zu deiner Simulation: Es genügt nicht zu gucken, ob auf der alten Karte an dieser Stelle kein Fisch war. Sonst kann es passieren, dass danach mehrere Fische auf ein (vorher leeres) Feld zusammenfallen und es weniger Fische sind, als vorher. Ich nehme mal an, das soll so nicht sein bei der Wator-Simulation.

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)

Für diesen Beitrag haben gedankt: galagher
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: So 13.07.14 17:24 
Hallo,

wobei
ausblenden Delphi-Quelltext
1:
  posX := (x + vWidth) mod vWidth;					

auch nur für x > -vWidth funktioniert.
Im Paranoia-Modus wäre eine Verschiebung auf Maxint/2/vWidth optimaler ;-)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
..in create ..
 cWidth := (maxint div 2+1DIV vWidth;

und dann 
 posX := (x + cWidth) mod vWidth;

aber das rechnet noch etwas langsamer.

Ohne Objektorientierung und ohne modulo, weil man darauf achtet, das man es nicht braucht.
Dort ist das Originalspielfeld von 1..n und tmp von 0..n+1. Das weitere wird dort beschrieben.
Siehe Game of Life - wie torusförmiges Spielfeld erstellen und im Programm

Gruß Horst

Für diesen Beitrag haben gedankt: galagher
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: So 13.07.14 19:37 
Hallo,
hattest Du das Thema nicht schon einmal, irgendwie?
siehe www.entwickler-ecke....&highlight=wator

Ich verweise noch einmal auf mein kleines Beispielprogramm unter www.entwickler-ecke.....php?p=674090#674090. Vielleicht hilft es ja doch etwas.

Beste Grüße
Mathematiker

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2556
Erhaltene Danke: 45

Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
BeitragVerfasst: Mo 14.07.14 19:13 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
hattest Du das Thema nicht schon einmal, irgendwie?
siehe www.entwickler-ecke....&highlight=wator

Irgendwie, ja! :mrgreen:

Habe jetzt keine Lust mehr, mich - unter den geänderten Bedingungen - da nochmal durchzubeissen, jetzt bleibt alles innerhalb des Spielfeldes und gut ist's.

//Edit: Damit's keine Missverständnisse gibt nach dem Motto: "Da fragt er was, dann sagt man ihm was dazu, und dann sagt der, er will das nicht":
Ich wollte das mit meinem Code machen, so, wie ich mir das denke. Ist ja von euch gut gemeint, doch wenn ich es mit meinem Ansatz nicht schaffe, dann möchte ich auch nichts anderes machen!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!