AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Tipps und Ratschläge für Spiel & für effizientes Programmieren
Thema durchsuchen
Ansicht
Themen-Optionen

Tipps und Ratschläge für Spiel & für effizientes Programmieren

Ein Thema von Danny92 · begonnen am 27. Aug 2017 · letzter Beitrag vom 5. Sep 2017
Antwort Antwort
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#1

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 2. Sep 2017, 16:34
Wird randomize zum Programmstart aufgerufen?
Bei Verwendung der VCL wird das automatisch erledigt, weil Viele es sändig vergessen.
(in der Initialisierung der VCL wird einmal Randomize ausgeführt)
Ich weiß nicht, auf welche Delphiversion bzw. ab welcher Delphiversion Du Dich beziehst, aber bis Delphi 7, das ich zur Compilierung meines Sortieranimationsprogrammes benutze, ist es sehr wohl unterschiedlich, ob ich randomize (im Initialisationsteil der ersten VCL-Unit) aufrufe oder es unterlasse. Verzichte ich auf diesen Befehl, sind die Zufallszahlen nach jedem Programmstart die gleichen.

Edit: Ein "automatisches" Randomize ist ein zweischneidiges Schwert. Wie will man "vernünftig", "produktiv" debuggen, wenn man keine reproduzierbaren Ergebnisse erhält?

Geändert von Delphi-Laie ( 2. Sep 2017 um 17:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.336 Beiträge
 
Delphi 12 Athens
 
#2

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 2. Sep 2017, 18:20
Edit: Ein "automatisches" Randomize ist ein zweischneidiges Schwert. Wie will man "vernünftig", "produktiv" debuggen, wenn man keine reproduzierbaren Ergebnisse erhält?
Nicht mit Zufalls werten arbeiten, oder vorher den Test "ordentlich" initialisieren (RandSeed), wenn es nötig ist.

Das mit der Automatik wurde nicht gleich zu beginn eingebaut.
Dachte bei D7 ist es schon da, aber spätestens mit XE ist es so.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Danny92
Danny92

Registriert seit: 18. Aug 2014
55 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 3. Sep 2017, 20:50
Ja es wird alles beachtet was beim Plazieren der Schiffe notwenig ist; dass es aus dem Feld nicht herausragt, dass dieses Schiff mit anderen nicht kollidiert oder sie sich berühren. Und solange nicht all diese Bedingungen erfüllt sind, wird das Schiff zufällig neu plaziert. Und mir ist schon unverständlich wie man da aus der Schleife rauskommt, solange noch nicht alle Schiffe plaziert worden sind^^
Wenn ich randomize in FormCreate (wird ja nur einmal aufgerufen) auskommentiere, bleibt der Fehler weiterhin.
  Mit Zitat antworten Zitat
Benutzerbild von Danny92
Danny92

Registriert seit: 18. Aug 2014
55 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#4

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 3. Sep 2017, 21:09
Hier noch einmal die Prozedur zum Setzen der Flotte:

Delphi-Quellcode:
procedure TForm1.SetzeFlotte(ofPlayer: boolean);
var
  zahl, i, j, k, fehlenNoch, vofPlayer: Integer;
  done, alleProbiert: Boolean;
  richtungProbiert: array[0..3] of Boolean;
begin
  vofPlayer:=StrToInt(BoolToStr(ofPlayer, false)) + 1;
  flotte[vofPlayer].Free;
  flotte[vofPlayer]:=TFlotte.Create(flottengroesse[5], flottengroesse[4],
  flottengroesse[3], flottengroesse[2], flottengroesse[1]);
  for i:=5 downto 1 do
  begin
    j:=1;
    fehlenNoch:=flotte[vofPlayer].AnzahlFehlenderSchiffeDerGroesse(i);
    while j <= fehlenNoch do
    begin
      done:=false;
      repeat
        zahl:=random(feldgroesse * feldgroesse) + 1;
        for k:=0 to 3 do richtungProbiert[k]:=false;
        a:=Point(((zahl - 1) mod feldgroesse) + 1, ((zahl - 1) div feldgroesse) + 1);
        repeat
          k:=random(4);
          alleProbiert:=true;
          case k of
          0: if a.Y >= i then b:=Point(a.X, a.Y - i + 1);
          1: if a.Y + i - 1 <= feldgroesse then b:=Point(a.X, a.Y + i - 1);
          2: if a.X >= i then b:=Point(a.X - i + 1, a.Y);
          3: if a.X + i - 1 <= feldgroesse then b:=Point(a.X + i - 1, a.Y);
          end;
          if not richtungProbiert[k]
          then done:=flotte[vofPlayer].SetzeSchiff(a, b);
          richtungProbiert[k]:=true;
          for k:=0 to 3 do
            if not richtungProbiert[k] then alleProbiert:=false;
        until alleProbiert or done;
      until done;
      Inc(j);
    end;
  end;
  FeldPlayer.Repaint;
end;
Hier die darin benutzte boolsche Funktion SetzeSchiff(a, b: TPoint) aus der Klasse TFlotte, die genau dann true zurückgibt, wenn das Platzieren des Schiffes im Feld unter den bekannten Regeln erfolgreich war:

Delphi-Quellcode:
function TFlotte.SetzeSchiff(a: TPoint; b: TPoint): boolean;
var
  laenge, vmin, vmax, i: integer;
begin
  if IstGueltig(a, b) then
  begin
    if a.X=b.X
    then laenge:=max(a.Y,b.Y)-min(a.Y,b.Y)+1
    else laenge:=max(a.X,b.X)-min(a.X,b.X)+1;
    if laenge>1
    then Inc(schiffsanzahl);
    SetLength(vSchiff[laenge],Length(vSchiff[laenge])+1);
    vSchiff[laenge,high(vSchiff[laenge])]:=TSchiff.Create;
    if a.X=b.X then
    begin
      vmin:=min(a.Y,b.Y); vmax:=max(a.Y,b.Y);
      for i:=vmin to vmax do
      if laenge=1
      then feld[a.X-1,i-1]:=3
      else feld[a.X-1,i-1]:=1;
      result:=vSchiff[laenge,high(vSchiff[laenge])].SetzeSchiff(Point(a.X,vmin),Point(a.X,vmax));
    end else
    if a.Y=b.Y then
    begin
      vmin:=min(a.X,b.X); vmax:=max(a.X,b.X);
      for i:=vmin to vmax do
      if laenge=1
      then feld[i-1,a.Y-1]:=3 //Setze Mine
      else feld[i-1,a.Y-1]:=1;
      result:=vSchiff[laenge,high(vSchiff[laenge])].SetzeSchiff(Point(vmin,a.Y),Point(vmax,a.Y));
    end
    else
      result:=false
  end
  else
    result:=false
end;
Und hier zuletzt die darin benutzte boolsche Funktion SetzeSchiff(a, b: TPoint) aus der Klasse TSchiff, die bei Erfolg ebenfalls true liefert:

Delphi-Quellcode:
function TSchiff.SetzeSchiff(a,b: TPoint): boolean;
var
  istSchiff: boolean;
  i: integer;
begin
  istSchiff:=(a.X=b.X) and (abs(a.Y-b.Y)<5) or (a.Y=b.Y) and (abs(a.X-b.X)<5);
  if istSchiff then
  begin
    vStart:=a; vEnde:=b;
    if a.X=b.X
    then laenge:=abs(a.Y-b.Y)+1
    else laenge:=abs(a.X-b.X)+1;
    vWaagerecht:=a.Y=b.Y;
    SetLength(vSchiff,laenge);
    for i:=1 to laenge do vSchiff[i-1]:=false;
  end;
  result:=istSchiff;
end;
So und jetzt kommt das Irre: bleibt die äußerste Zählschleife in SetzeFlotte als i:=5 downto 1, wird in manchen Fällen das 5er Schiff nicht gezeichnet, die Flotte besteht also nur aus dem 3er (linkes Bild im Anhang). Ändere ich die Zählschleife aber in i:=1 to 5, wird (wenn auch noch seltener) das 3er Schiff vergessen und nur das 5er Schiff plaziert (rechtes Bild im Anhang).

Was ist da los?! Bug?
Miniaturansicht angehängter Grafiken
5fehlt_downto.jpg   3fehlt_to.jpg  

Geändert von Danny92 ( 3. Sep 2017 um 21:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Danny92
Danny92

Registriert seit: 18. Aug 2014
55 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 3. Sep 2017, 23:33
Ok ich habe den Fehler gefunden^^
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
981 Beiträge
 
Delphi 6 Professional
 
#6

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 4. Sep 2017, 05:19
Hmm..


Ok ich habe den Fehler gefunden^^
Und was war es?
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#7

AW: Tipps und Ratschläge für Spiel & für effizientes Programmieren

  Alt 5. Sep 2017, 16:38
Edit: Ein "automatisches" Randomize ist ein zweischneidiges Schwert. Wie will man "vernünftig", "produktiv" debuggen, wenn man keine reproduzierbaren Ergebnisse erhält?
Nicht mit Zufalls werten arbeiten, oder vorher den Test "ordentlich" initialisieren (RandSeed), wenn es nötig ist.

Das mit der Automatik wurde nicht gleich zu beginn eingebaut.
Dachte bei D7 ist es schon da, aber spätestens mit XE ist es so.
Nein, und auch bei Turbo-Delphi (das wohl intern einem Delphi 2006 entsprechen dürfte) gibt es noch kein "automatisches" Randomize.
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:26 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