Schiffe zufällig setzen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Jochim
Beiträge: 32
Registriert: Mi 20. Mär 2013, 13:44
OS, Lazarus, FPC: Win7 HP x64
CPU-Target: Bit

Schiffe zufällig setzen

Beitrag von Jochim »

Hallo,
ich habe eine Procedur geschrieben, die die Schiffe des Computers setzen soll. Dabei ist es wichtig, dass das Schiff nicht über den Rand geht und nicht durch ein anderes "fährt".
jetzt habe ich das Problem, dass sich das Programm aufhängt und auch nur noch durch Lazarus zu schließen ist, sobald die Prozedur ausgeführt wird.

Mg Jochim

Die Prozedur:

Code: Alles auswählen

procedure TForm1.schiffsetzencom;
var c,i:integer; dasetzcom:boolean;
begin
 for i:=1 to 4 do begin //jedes Schiff
  repeat //Solange kein Schiff über Rand, und nicht Schiffe aufeinander sind
    dasetzcom:=true; //wenn True ist setzen möglich
    schiffcom[i].x:=random(iraster-1)+1;  //x koordinate iraster=spielfeldgröße
    schiffcom[i].y:=random(iraster-1)+1;  //y koordinate
    c:=random(2); //zufällige ausrichtung
  If c=1 then schiffcom[i].ausrichtung:=True else schiffcom[i].ausrichtung:=False;
    schiffcom[i].leng:=i+1; //schifflänge festsetzen
  if ((schiffcom[i].ausrichtung=true) and (schiffcom[i].leng+schiffcom[i].y<iraster)) then
  begin  //Schiffsetzen wenn ausrichtung true und schiff dann nicht über rand herrausguckt
      for c:=0 to schiffcom[i].leng-1 do begin //kennzeichnen des schiffes in einem array of String mit der kompletten länge
        If (sgcom[schiffcom[i].x,schiffcom[i].y+c]<>'') then begin //überprüfung ob schon ein Schiff vorhanden ist
          dasetzcom:=false; //setz variable auf false setzen fals vorhanden
        end else sgcom[schiffcom[i].x,schiffcom[i].y+c]:=bt[i]; //kennzeichnen des schiffes
      end;
  end else dasetz:=False;
  if ((schiffcom[i].ausrichtung=False) and (schiffcom[i].leng+schiffcom[i].x<iraster)) then
  begin  //schiffsetzen wenn ausrichtung false und schiff dann nicht über rand herrausguckt
      for c:=0 to schiffcom[i].leng-1 do begin
        If (sgcom[schiffcom[i].x+c,schiffcom[i].y]<>'') then begin
          dasetzcom:=false;
        end else sgcom[schiffcom[i].x,schiffcom[i].y+c]:=bt[i];
      end;
  end else dasetz:=False;
  //end;
  until dasetzcom=True;  //überprüfung ob setzen mörglich
 
  //zeichnen ins StringGrid (sgcomputer
  for i:=1 to 4 do begin
  //komplette schiff länge
      for c:=0 to schiffcom[i].leng-1 do begin
        //ausrichtung prüfen
        if schiffcom[i].ausrichtung=True then begin
          sgcomputer.cells[schiffcom[i].x,schiffcom[i].y+c]:=bt[i];
          end;
        if schiff[i].ausrichtung=False then begin
          sgcomputer.cells[schiffcom[i].x+c,schiffcom[i].y]:=bt[i];
        end;
      end;
  end;
end;

Benutzeravatar
theo
Beiträge: 10874
Registriert: Mo 11. Sep 2006, 19:01

Re: Schiffe zufällig setzen

Beitrag von theo »

Wenn's "hängt" wird meistens eine Abbruchbedingung in einem Loop nicht erfüllt.
Vermutlich bei reapat..until dasetzcom=True;

Jochim
Beiträge: 32
Registriert: Mi 20. Mär 2013, 13:44
OS, Lazarus, FPC: Win7 HP x64
CPU-Target: Bit

Re: Schiffe zufällig setzen

Beitrag von Jochim »

Jetzt hängt es nicht mehr, allerdings setzt er die schiffe horizontal und vertikal und auch schiffe aufeinander.

Horst_h
Beiträge: 74
Registriert: Mi 20. Mär 2013, 08:57

Re: Schiffe zufällig setzen

Beitrag von Horst_h »

Hallo,

nur eine Kleinigkeit.
Wenn Du zuerst die Ausrichtung und Länge festlegst und dann erst den Startpunkt des Schiffes brauchst Du diesen undurchdringlichen Wust an Begingungen nicht, um die "Rand"bedingung zu testen.
StrinGrids gehen von 0 los, aber Vielleicht stehen dort bei Dir die Koordinaten.

Code: Alles auswählen

 
const
  StartZeile = 1;
  StartSpalte = 1;
   ....
     dasetzcom:=true; //wenn True ist setzen möglich
 
     laenge := i+1;
     schiffcom[i].leng:=laenge; //schifflänge festsetzen
 
     c:=random(2); //zufällige ausrichtung
     senkrecht := C=1; //alles <> 1 wird zu false 
 
     schiffcom[i].ausrichtung:=senkrecht;
     //Startpunkt so, dass das Schiff NICHT ueber den Rand kommt
     IF senkrecht then begin
       schiffcom[i].x:=random(iraster)+StartZeile;  //x koordinate 0..iraster-1 =spielfeldgröße
       schiffcom[i].y:=random(iraster-laenge)+StartSpalte;  //y koordinate
       end
     else Begin
       schiffcom[i].x:=random(iraster-laenge)+StartZeile;
       schiffcom[i].y:=random(iraster)+StartSpalte;
       end; 
Und bitte mehr Variablen mit passendem Namen.Wenn man in der Lazarus IDE mit dem Mauszeiger auf ein end oder until geht, zeigt es einem das passende Begin oder repeat an.
Mal ist das Begin hintenan, mal eine Zeile darunter
Gibt es da nicht auch einen JEDI-Codeformartierer im Reiter/Tab Quelltext-> ganz unten.
Es ist nicht verboten mehrere kleine Prozeduren und Funktionen zu schreiben. Im Alter lassen sich kleine Häppchen besser verdauen und verstehen.

Gruß Horst

Jochim
Beiträge: 32
Registriert: Mi 20. Mär 2013, 13:44
OS, Lazarus, FPC: Win7 HP x64
CPU-Target: Bit

Re: Schiffe zufällig setzen

Beitrag von Jochim »

Hallo,
auf diese idee bin ich auch schon gekommen, doch wie setze ich es denn um, dass nicht 2 schiffe aufeinander sind? Dort muss ja dann evtl alles neu sein.

mg jochim

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Schiffe zufällig setzen

Beitrag von Socke »

Jochim hat geschrieben:doch wie setze ich es denn um, dass nicht 2 schiffe aufeinander sind? Dort muss ja dann evtl alles neu sein.
Zuerst überlegst du dir eine Position und eine Ausrichtung für ein neues Schiff. Dann überprüfst du, ob dort schon ein Schiff ist; wenn ja, kannst du dir eine neue Position suchen, falls nicht, kannst du das Schiff setzten.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Horst_h
Beiträge: 74
Registriert: Mi 20. Mär 2013, 08:57

Re: Schiffe zufällig setzen

Beitrag von Horst_h »

Hallo,

eigentlich müsste man auch einen Abstand um das Schiff einhalten.
Ein einfacher Ansatz wäre zum StringGrid parallel ein Spielfeld zu verwalten.

Code: Alles auswählen

 
const
  iRaster = 10;
type
  TIndex  = 1..iRaster;
  tFeldBelegung = (frei,Belegt,UmrahmungSchiff);
  tSpielFeldInhalt = record 
                       FeldBelegung: tFeldBelegung;
                       Beschuss : boolean;
                     end;
  tSpielFeld = array[tIndex,tIndex] of tSpielFeldInhalt;
 
  tSpieler  = record 
                Armada : tSchiff;// selber ausdenken...
                SpielFeldSelbst,
                SpielfeldGegner : tSpielfeld;
              end;    
var
  Spieler1,
  Spieler2 : tSpieler;
...  // Wird wohl Zeit eine Spieler Klasse zu erzeugen...
 
Damit hat man in einem Spielfeld die eigenen Schiffe und die Schüsse des Gegners eintragen und in dem anderem die Schiffe des Gegenspielers und die eigenen Schüsse, wie auf Papier auch.
Also Spielfelder vor belegen mit frei und ohne Beschuss durch jemanden.
Wenn man ein Schiff erzeugt versucht man einzutragen, das heißt das alle Felder und die Umrahmung frei sein muss.
Wenn Du wirklich nur gerade Schiffe hast, kannst Du natürlich auch ein Umhüllendes Rechteck ( Linke obere Ecke und rechte untere Ecke ) nehmen und alle anderen Schiffe abfragen ob es eine Überschneidung gibt "bounding box test" .

Gruß Horst

Antworten