Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Schiffe versenken, Platzierung (https://www.delphipraxis.net/151288-schiffe-versenken-platzierung.html)

m2zer0 11. Mai 2010 14:39


Schiffe versenken, Platzierung
 
Hi :)
Ich soll für die Schule das Spiel Schiffe versenken mit Delphi 5 programmieren, nur weiß ich nicht wie ich die Platzierung der Schiffe hinbekommen soll. Für das Feld will ich ein Drawgrid benutzen.Ich weiß nicht wie ich es hinbekomme, dass das Feld auf das ich klicke und das rechts daneben rot gefärbt wird. Bis jetzt wird nur das angeklickte Feld rot.

Ich hoffe ihr könnt mir helfen :)

stho 11. Mai 2010 15:04

Re: Schiffe versenken, Platzierung
 
du kannst dich bestimmt irgendwie die position in x und y des angeklickten Feldes heraus finden, oder?
Und dann zählst du einfach das Feld mit den Eigenschaften Y und X + 1 an ;-)
Ich kenne diese komponente leider nicht...

m2zer0 11. Mai 2010 19:13

Re: Schiffe versenken, Platzierung
 
Delphi-Quellcode:
procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  with sender as TDrawgrid do
  begin
   if arr[acol,arow]or arr[acol-1,arow]
    then canvas.brush.color := clred
     else canvas.brush.color := clwhite;
   canvas.fillrect(rect);
  end;

end;

procedure TForm1.DrawGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var arow,acol:integer;
begin
  DrawGrid1.MouseToCell(X, Y,ACol, ARow);
  arr[acol,arow]:= not arr[acol,arow];
  DrawGrid1.Repaint;
end;
Das ist meine momentane Aushilfe für mein Problem, aber sie scheint noch stark sub-optimal zu sein, da ich von hier aus nicht wüsste wie ich dann die Schiffe mit 3/4/5 Plätzen platzieren könnte...

m2zer0 24. Mai 2010 11:07

Re: Schiffe versenken, Platzierung
 
Ich bin jetzt schon relativ weit gekommen, nur wie überprüfe ich ob die Schiffe nebeneinanderliegen? Denn das sollte ja eigentlich nicht möglich sein.

Momentan sieht der Quelltext bei mir so aus:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    DrawGrid1: TDrawGrid;
    BHori: TButton;
    Image1: TImage;
    Image2: TImage;
    BVerti: TButton;
    IHori: TImage;
    IVerti: TImage;
    Image3: TImage;
    Image4: TImage;
    DrawGrid2: TDrawGrid;
    procedure DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure DrawGrid1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure BHoriClick(Sender: TObject);
    procedure BVertiClick(Sender: TObject);
  private
   arr2:array[0..9,0..9] of boolean;

    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  a,b,c,d,e,f,g,h,z:integer;

implementation

{$R *.DFM}

procedure TForm1.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
    begin
      with sender as TDrawgrid do
        begin
          if arr2[acol,arow]
            then canvas.brush.color := clred
            else canvas.brush.color := clwhite;
           canvas.fillrect(rect);
        end;
    end;
end;


procedure TForm1.DrawGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var row,col:integer;
begin

  DrawGrid1.MouseToCell(X, Y,Col, Row); //Mausposition auslesen

  if z=5 then                                        //5er Schiff
   if a=1 then
    begin
     if col<6 then
      begin
       arr2[col,row] := not arr2[col,row];
       arr2[col+a,row+e]:= not arr2[col+a,row+e];
       arr2[col+b,row+f]:= not arr2[col+b,row+f];
       arr2[col+c,row+g]:= not arr2[col+c,row+g];
       arr2[col+d,row+h]:= not arr2[col+d,row+h];
       image4.visible:=false;
       z:=z+1;
      end;
    end
   else
    if row<6 then
     begin
      arr2[col,row] := not arr2[col,row];
      arr2[col+a,row+e]:= not arr2[col+a,row+e];
      arr2[col+b,row+f]:= not arr2[col+b,row+f];
      arr2[col+c,row+g]:= not arr2[col+c,row+g];
      arr2[col+d,row+h]:= not arr2[col+d,row+h];
      image4.visible:=false;
      z:=z+1;
     end;

  if z=4 then                                           //4er Schiff
   if a=1 then
    begin
     if col<7 then
      begin
       arr2[col,row] := not arr2[col,row];
       arr2[col+a,row+e]:= not arr2[col+a,row+e];
       arr2[col+b,row+f]:= not arr2[col+b,row+f];
       arr2[col+c,row+g]:= not arr2[col+c,row+g];
       image3.visible:=false;
       z:=z+1;
      end;
    end
   else
     if row<7 then
      begin
       arr2[col,row] := not arr2[col,row];
       arr2[col+a,row+e]:= not arr2[col+a,row+e];
       arr2[col+b,row+f]:= not arr2[col+b,row+f];
       arr2[col+c,row+g]:= not arr2[col+c,row+g];
       image3.visible:=false;
       z:=z+1;
      end;

  if z=3 then                                      //3er Schiff
   if a=1 then
    begin
     if col<8 then
      begin
       arr2[col,row] := not arr2[col,row];
       arr2[col+a,row+e]:= not arr2[col+a,row+e];
       arr2[col+b,row+f]:= not arr2[col+b,row+f];
       image2.visible:=false;
       z:=z+1;
      end;
    end
   else
    if row<8 then
     begin
      arr2[col,row] := not arr2[col,row];
      arr2[col+a,row+e]:= not arr2[col+a,row+e];
      arr2[col+b,row+f]:= not arr2[col+b,row+f];
      image2.visible:=false;
      z:=z+1;
     end;

  if z=2 then                                      //2er Schiff
   if a=1 then
    begin
     if col<9 then
      begin
       arr2[col,row]:= not arr2[col,row];
       arr2[col+a,row+e]:= not arr2[col+a,row+e];
       image1.visible:=false;
       z:=z+1;
      end;
    end
   else
    if row<9 then
     begin
      arr2[col,row]:= not arr2[col,row];
      arr2[col+a,row+e]:= not arr2[col+a,row+e];
      image1.visible:=false;
      z:=z+1;
     end;


DrawGrid1.Repaint;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  z:=2;
  a:=1; b:=2; c:=3; d:=4;
  e:=0; f:=0; g:=0; h:=0;
end;

procedure TForm1.BHoriClick(Sender: TObject);
begin
  IVerti.visible:=false;                     //Horizontale Ausrichtung
  IHori.visible:=true;

  a:=0; b:=0; c:=0; d:=0;
  e:=1; f:=2; g:=3; h:=4;
end;

procedure TForm1.BVertiClick(Sender: TObject);
begin
  IVerti.visible:=true;                     //Vertikale Ausrichtung
  IHori.visible:=false;

  a:=1; b:=2; c:=3; d:=4;
  e:=0; f:=0; g:=0; h:=0;
end;

end.

patti 24. Mai 2010 11:46

Re: Schiffe versenken, Platzierung
 
Liste der Anhänge anzeigen (Anzahl: 2)
Vom Ansatz her schaut das, was du bisher hast, schon mal gar nicht so schlecht aus.

In deiner Schiff-Setzen-Routine (die ich etwas ändern würde, so ist es ziemlich umständlich und fehleranfällig) würde ich folgendes machen: Zuerst mal musst du dir überlegen, wann die Positionierung gültig ist, d.h. wann ein Setzen des Schiffs nach den Regeln erlaubt sein soll. Ein Schiff darf kein anderes Schiff irgendwo berühren, d.h. es muss um das neu zu setzende Schiff ein "Rand" von einem Feld frei sein (siehe auch Bilder im Anhang). In der Routine würde ich mir dieses Rechteck bestimmen, und zwar mit Hilfe einer Variable vom Typ TRect:

Delphi-Quellcode:
var r : TRect;
var gueltig : boolean;
var iX, iY : integer;
//
//...
// Ueberpruefung, ob innerhalb des Felds (das hast du ja schon)...
//
// Du weisst ja, wo das Schiff gesetzt werden soll und du weisst die Länge und die Orientierung des Schiffs. Damit kannst du schonmal die Position des Schiffs im Rect speichern:
r.Left := x;
r.Top := y;
//
if Orientierung = horizontal (* oder wie du es halt speicherst *) then
begin
  r.Right := r.Left + Laenge -1;
  r.Bottom := r.Top;
end
else
begin
  r.Right := r.Left;
  r.Bottom := r.Top + Laenge -1;
end;
//
// Jetzt musst du das Rect auf jeder Seite noch um "1" vergoessern, dabei musst du bedenken, dass das Schiff auch an einem Rand des Felds liegen kann:
//
if r.Left > 0 then r.Left := r.Left -1;
if r.Top > 0 then r.Top := r.Top -1;
if r.Right < 9 then r.Right := r.Right +1;
if r.Bottom < 9 then r.Bottom := r.Bottom +1;
//
// Jetzt kannst du das gesamte Rect in einer Schleife durchgehen und die Felder ueberpruefen:
//
gueltig := true;
//
for iX := r.Left to r.Right do
  for iY := r.Top to r.Bottom do
    if not(arr2[iX,iY]) then gueltig := false;
// (Schleife kann man noch einbisschen optimieren)
//
if gueltig then
begin
  // SETZEN
end;
(ungetestet, nur hier schnell im Beitrags-Editor getippt, können Tippfehler drin sein :-) )

Hoffe, das hilft dir schonmal einbisschen weiter ;-)

mfg
Patti

m2zer0 24. Mai 2010 12:50

Re: Schiffe versenken, Platzierung
 
Vielen dank, ich werd mir nachher wenn ich Zeit hab darüber gedanken machen :)
Aber den Grundgedanken versteh ich schon :)

Falls ich das nächste mal irgendwo hängen bleibe, oder was an deinem Tipp nicht verstehe Frage ich nochmal :)

Danke. M2zer0

m2zer0 26. Mai 2010 23:13

Re: Schiffe versenken, Platzierung
 
mhh.. Ich hab reichlich rumprobiert und es klappt auch das ich auf manchen Feldern nichts mehr setzten kann, nur das schon von Anfang an. Durch das setzen von Schiffen ändert sich auch nichts an den Feldern.. ich kann sie trotzdem noch ineinander setzen. Könntest du mir deinen Quelltext noch einmal näher erklären?

m2zer0 27. Mai 2010 17:16

Re: Schiffe versenken, Platzierung
 
soooo :)
Mit dem Platzieren der eigenen Schiffe bin ich endlich fertig :)
Der Quelltext sieht nun so aus:

Delphi-Quellcode:
procedure TForm1.DrawGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var row,col:integer;
begin

  DrawGrid1.MouseToCell(X, Y,Col, Row); //Mausposition auslesen

r.Left :=Col-1;
r.Top :=Row-1;

  if Horizontal=0 then
   begin
    r.Right:=col+z;
    r.Bottom:=Row+1;
   end
  else
   begin
    r.Right:=col+1;
    R.Bottom:=row+z;
   end;


  if r.Left = -1
    then r.Left := 0;
  if r.Top = -1
    then r.Top := 0;
  if r.Right =10 then
    r.Right := r.Right -1;
  if r.Bottom = 10 then
    r.Bottom := r.Bottom -1;

  LX.caption:=IntToStr(R.right);
  LY.caption:=IntToStr(R.left);

  gueltig:=true;

  for iX := r.Left to r.Right do
    for iY := r.Top to r.Bottom do
           if (arr2[iX,iY]) then gueltig := false;

if gueltig then
begin
//schiffe setzen
end;
Wie könnte ich recht simpel einen "Neues Spiel" button machen, ohne das ich manuell alle variablen auf anfangsstatus setzen muss?

shmia 27. Mai 2010 17:30

Re: Schiffe versenken, Platzierung
 
Das grundsätzliche Problem steckt hier:
Delphi-Quellcode:
arr2:array[0..9,0..9] of boolean;
Damit lässt sich nur erkennen ob an einer bestimmten Stelle Schiff oder Wasser ist.
Man kann aber nicht herausfinden, zu welchem Schiff ein Punkt gehört.
Damit ist die Aussage "Schiff versenkt" nicht möglich.
Jedes Schiff sollte eine andere Kennung haben.
Delphi-Quellcode:
arr2:array[0..9,0..9] of char;
Hier eine Spielkarte mit drei Schiffen aaa (3-er Schiff), bBbbb (5-er Schiff mit einem Treffer), cccc (4-er Schiff)
*-chen bedeutet Wasser
Bei einem Treffer wird ein Kleinbuchstabe zu einem Grossbuchstaben.
Code:
**********
*aaa******
*b********
*B********
*b********
*b********
*bcccc****
**********
**********
**********

m2zer0 27. Mai 2010 18:39

Re: Schiffe versenken, Platzierung
 
Danke für die Antwort :)
Nur ich bin noch ein Anfänger was Delphi angeht, könntest du das "Array of Char" ein wenig erklären? Das war mir bisher noch nicht bekannt.

Vielen dank :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:12 Uhr.
Seite 1 von 4  1 23     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz