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 "MineSweeper" - Probleme mit Rundtime-Buttons (https://www.delphipraxis.net/121697-minesweeper-probleme-mit-rundtime-buttons.html)

64Jabor 2. Okt 2008 17:40


"MineSweeper" - Probleme mit Rundtime-Buttons
 
Hallo DP,

ich stehe mal wieder kurz vorm Verzwefeln -.-

Ich sitze atm an einer MineSweeper-Version und habe für die Minenfelder Runtime-Buttons erstellt.
Die werden alle erstellt, sind sichtbar und funktionieren alle sehr gut.
Aber wenn ich dann anhand der Mausposition versuche herauszufinden, welcher der Buttons gedrückt worden ist, bekomme ich seltsame Ergebnisse!

Hier mal der Code:
Delphi-Quellcode:
procedure TFrmMS.MineBtnDadClick(Sender: TObject);
var x, y: integer;
    RealPosX, RealPosY: integer;
    Found: boolean;
begin
 RealPosX := Mouse.CursorPos.X - Left;
 RealPosY := Mouse.CursorPos.Y - Top ;
 ShowMessage(IntToStr(RealPosX)+', '+IntToStr(RealPosY));
 x:=0;
 repeat
  begin
   if ((MineBtn[x, 0].Left < RealPosX) and (MineBtn[x, 0].Left + MineBtn[0, 0].Width > RealPosX)) then
    begin
     y:=0;
     repeat
      begin
       if ((MineBtn[x, y].Top < RealPosY) and (MineBtn[x, y].Top + MineBtn[x, y].Height > RealPosY)) then Found := TRUE;
       y:=y+1;
      end;
     until ((y = RowsForLevel) or Found);
    end;
   x:=x+1;
  end;
 until ((x = ColsForLevel) or Found);
 Aufdecken(x, y);
end;
Das ist die Prozedur, die ausgelöst wird wenn IRGENDEINER meiner Runtime-Buttons gedrückt wird.
(MineBtn ist ein Array aus TSpeedButtons (groß genug!) und Rows/ColsForLevel sind integers, der Name erklärt den Rest)
Misteriöserweise bekomme ich immer ein "y" welches 2 zuviel ist als es eingentlich sein müsste und wenn ich das einfach korrigiere indem ich später sage y ist y-2, dann erhalte ich immer Fehler wenn ich Buttons der rechten unteren Ecke drücke.
Also iwas stimmt da nicht, aber ich kann den Fehler nicht finden...

Wer kann helfen?
Danke schonmal, greetZ DaSebi

mkinzler 2. Okt 2008 17:43

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Warum verwendest du nicht den Sender-Parameter des Click-Events?

Klaus01 2. Okt 2008 17:49

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Guten Abend,

die könntest beim Erstellen der Buttons jedem Button einen Tag-Wert mitgeben.
Anhand dieses Tag kannst Du den Button dann identifizieren.

Im Button Click Ereignis kannst Du dann so darauf zugreifen:

Delphi-Quellcode:
(sender as TButton).tag
Du kannst dann ein Click Ereignis für alle Buttons benutzen, so wie mkinzler schon geschrieben hat.

Grüße
Klaus

64Jabor 2. Okt 2008 18:33

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
@mkinzler

Meinst du damit dass jeder Button als der Sender gilt?
Das heißt ja dass ich mit Sender.XXX auf alles zugreifen könnte und anhand von Werten wie zB. dem Sender.Left ganz einfach Reihe/Spalte des Butons herausbekomme -.-

Na klasse xD :wall: :wall: :wall:
Vielen Dank! Meine Methode war wohl mit Kanonen auf Spatzen geschossen ^^

@klaus01
das mit dem tag wäre für meine Methode dank zweidimensionalen Array aber entwas aufwendiger, trotzdem danke für diesen Ansatz!

greetZ DaSebi

mkinzler 2. Okt 2008 18:43

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Der Parameter Sender ist eine Referenz auf das auslösende Objekt. Der Tag erleichtert die Identifizierung des Buttons.

64Jabor 2. Okt 2008 19:01

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Ja ich weiß was der Sender ist, aber ich dachte dass der Sender immer mein realer Button wäre, denn alle OnClick-Ereignisse hatte ich auf seines umglenkt...

Hier aber mal der funktionierende Code für alle Interessierten:
Delphi-Quellcode:
procedure TFrmMS.MineBtnDadClick(Sender: TObject);
var x, y: integer;
    i, z: integer;
    Found: boolean;
begin
 i:=0;
 Found := FALSE;
 while ((i < ColsForLevel) and not (Found)) do
  begin
   z:=0;
   while ((z < RowsForLevel) and not (Found)) do
    begin
     if(MineBtn[i, z] = Sender) then Found := TRUE else z := z+1;
    end;
   if not (Found) then i := i+1;
  end;
 x := (MineBtn[i, z].Left - MineBtn[0, 0].Left) div MineBtn[0, 0].Width;
 y := (MineBtn[i, z].Top - 50) div MineBtn[0, 0].Height;
 Aufdecken(x, y);
end;
Vielen Dank nochmal!

mkinzler 2. Okt 2008 19:03

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Was meinst du mit realer Button?

64Jabor 2. Okt 2008 19:23

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Als real meine ich einen Button den ich mir real vorstellen kann xD
Also einen den ich per Drag&Drop auf das Formular gezogen hab, der unsichtbar ist und einfach nur dazu dient, alle OnClicks auf sich zu nehmen.
Ich weiß das real ganz sicherlich nicht der richtige Begriff dafür ist, aber ich fand den iwie passend ^^

Allerdings habe ich mit meiner Variante da oben ein kleines Problem!
In einem völlig unersichtlichen Muster bekomme ich Zugriffsverletzungen im Speicher.
Das wird daher rühren, dass ich eine Prozedur hab, die die Buttons löscht wenn man auf sie klickt und es keine Mine ist.
Dazu hier mal wieder die Prozedur (die von oben ist noch aktuell):
Delphi-Quellcode:
procedure TFrmMS.SmileForUser(ACol, ARow: integer);
var TopLeft, BtmRight: TPoint;
begin
 if not (BtnDestroyed[ACol, ARow]) then
  begin
   MineBtn[ACol, ARow].Destroy;
   BtnDestroyed[ACol, ARow] := TRUE;
  end;
 TopLeft.X := MineBtn[0, 0].Left + ACol*MineBtn[0, 0].Width;
 TopLeft.Y := MineBtn[0, 0].Top + ARow*MineBtn[0, 0].Height;
 BtmRight.X := TopLeft.X + MineBtn[0, 0].Width;
 BtmRight.Y := TopLeft.Y + MineBtn[0, 0].Height;
 Canvas.TextRect(rect(TopLeft, BtmRight), TopLeft.X, TopLeft.Y, MinesArround(ACol, ARow));
 BtnFace.Caption := ':-)';
end;
Weder das Rechteck noch die Schrift erscheinen obwohl sie das meiner Meinung nach egtl müssten ^^
Und ab und zu bekomme ich diese Zugriffsverletzungen TROTZ meinem Schutz, dass ein Button nicht zweimal gelöscht werden kann...woran kann denn das jetzt liegen O.o

mkinzler 2. Okt 2008 19:24

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Und die anderen?

64Jabor 2. Okt 2008 19:29

Re: "MineSweeper" - Probleme mit Rundtime-Buttons
 
Na die anderen werden zur Laufzeit erstellt.
Dazu habe ich eine Prozedur, die je nach Schwierigkeitsgrad 17 bis max 40 Buttons (zweidimensional) erstellt.

Hier die Prozedur:
Delphi-Quellcode:
procedure TFrmMS.GenerateBtns;
var BtnIndexX, BtnIndexY: integer;
begin
 For BtnIndexX:=0 to ColsForLevel-1 do
   For BtnIndexY:=0 to RowsForLevel-1 do
    begin
     MineBtn[BtnIndexX, BtnIndexY] := TSpeedButton.Create(FrmMS);
     MineBtn[BtnIndexX, BtnIndexY].Height := 14;
     MineBtn[BtnIndexX, BtnIndexY].Width := MineBtn[BtnIndexX, BtnIndexY].Height;
     MineBtn[BtnIndexX, BtnIndexY].Top := 50 + BtnIndexY * 14;
     MineBtn[BtnIndexX, BtnIndexY].Left := (ClientWidth - (ColsForLevel-1) * MineBtn[BtnIndexX, BtnIndexY].Width) div 2 + BtnIndexX * MineBtn[BtnIndexX, BtnIndexY].Width;
     MineBtn[BtnIndexX, BtnIndexY].Parent := FrmMS;
     MineBtn[BtnIndexX, BtnIndexY].OnClick := MineBtnDad.OnClick;
    end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:15 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