![]() |
Minesweeper
Hallo, liebe DPler,
Ich programmiere für die Schule Minesweeper in Delphi6 und bräuchte mal eure Hilfe. Ich nutze ein zweidimensionales Array, in dem ich die Minen zufällig verteile und in meiner Form1 sind 225 Panels quadratisch angeordnet. Bisher kann man mit Rechtsklick Panels markieren ("F" als Flagge und "?") und mit Linksklick wird die Zahl der umliegenden Minen kontrolliert und aufgeschrieben. Falls man auf eine Mine linksklickt, ist das Spiel verloren. Nun möchte ich, und dabei brauche ich eure Hilfe, dass wenn keine mit Minen besetzten Felder anliegen, dass passiert, was im Original auch passiert. Ihr wisst hoffentlich, was ich meine :) Mein Problem dabei ist, dass ich kein Plan hab, wie ich das umsetzen kann. Anbei mein QuellCode und ein Screenshot meiner Form1. Hinweis: Das StringGrid ist temporär. Ich nutze es um zu wissen ob sich mein Programm verzählt. Außerdem sind bisher nur 3 Panels eingebunden ([0,0], [0,1], [1,1]) Ich wäre euch echt unglaublich dankbar, wenn ihr mir da weiterhelfen würdet :-D ![]()
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Panel1: TPanel; P_0_0: TPanel; P_0_1: TPanel; P_0_2: TPanel; P_0_3: TPanel; P_0_4: TPanel; P_0_5: TPanel; P_0_6: TPanel; P_0_7: TPanel; P_0_8: TPanel; P_0_9: TPanel; P_0_10: TPanel; P_0_11: TPanel; P_0_12: TPanel; P_0_13: TPanel; P_0_14: TPanel; P_1_0: TPanel; P_1_1: TPanel; P_1_2: TPanel; P_1_3: TPanel; P_1_4: TPanel; P_1_5: TPanel; P_1_6: TPanel; P_1_7: TPanel; P_1_8: TPanel; P_1_9: TPanel; P_1_10: TPanel; P_1_11: TPanel; P_1_12: TPanel; P_1_13: TPanel; P_1_14: TPanel; P_2_0: TPanel; P_2_1: TPanel; P_2_2: TPanel; P_2_3: TPanel; P_2_4: TPanel; P_2_5: TPanel; P_2_6: TPanel; P_2_7: TPanel; P_2_8: TPanel; P_2_9: TPanel; P_2_13: TPanel; P_2_14: TPanel; P_2_10: TPanel; P_2_11: TPanel; P_3_0: TPanel; P_3_1: TPanel; P_3_2: TPanel; P_3_3: TPanel; P_2_12: TPanel; P_3_4: TPanel; P_3_5: TPanel; P_3_6: TPanel; P_3_7: TPanel; P_3_8: TPanel; P_3_9: TPanel; P_3_10: TPanel; P_3_11: TPanel; P_3_12: TPanel; P_3_13: TPanel; P_3_14: TPanel; P_4_0: TPanel; P_4_1: TPanel; P_4_2: TPanel; P_4_3: TPanel; P_4_4: TPanel; P_4_5: TPanel; P_4_6: TPanel; P_4_7: TPanel; P_4_8: TPanel; P_4_9: TPanel; P_4_10: TPanel; P_4_11: TPanel; P_4_12: TPanel; P_4_13: TPanel; P_4_14: TPanel; P_5_0: TPanel; P_5_1: TPanel; P_5_2: TPanel; P_5_3: TPanel; P_5_4: TPanel; P_5_5: TPanel; P_5_6: TPanel; P_5_7: TPanel; P_5_8: TPanel; P_5_9: TPanel; P_5_10: TPanel; P_5_11: TPanel; P_5_12: TPanel; P_5_13: TPanel; P_5_14: TPanel; P_6_0: TPanel; P_6_1: TPanel; P_6_2: TPanel; P_6_3: TPanel; P_6_4: TPanel; P_6_5: TPanel; P_6_6: TPanel; P_6_7: TPanel; P_6_8: TPanel; P_6_9: TPanel; P_6_10: TPanel; P_6_11: TPanel; P_7_0: TPanel; P_6_12: TPanel; P_6_13: TPanel; P_6_14: TPanel; P_7_1: TPanel; P_7_2: TPanel; P_7_3: TPanel; P_7_4: TPanel; P_7_5: TPanel; P_7_6: TPanel; P_7_7: TPanel; P_7_8: TPanel; P_7_9: TPanel; P_7_10: TPanel; P_7_11: TPanel; P_7_12: TPanel; P_7_13: TPanel; P_7_14: TPanel; P_8_0: TPanel; P_8_1: TPanel; P_8_2: TPanel; P_8_3: TPanel; P_8_4: TPanel; P_8_5: TPanel; P_8_6: TPanel; P_8_7: TPanel; P_8_8: TPanel; P_8_9: TPanel; P_8_10: TPanel; P_8_11: TPanel; P_8_12: TPanel; P_8_13: TPanel; P_8_14: TPanel; P_9_0: TPanel; P_9_1: TPanel; P_9_2: TPanel; P_9_3: TPanel; P_9_4: TPanel; P_9_5: TPanel; P_9_6: TPanel; P_9_7: TPanel; P_9_8: TPanel; P_9_9: TPanel; P_9_10: TPanel; P_9_11: TPanel; P_9_12: TPanel; P_9_13: TPanel; P_9_14: TPanel; P_10_0: TPanel; P_10_1: TPanel; P_10_2: TPanel; P_10_3: TPanel; P_10_4: TPanel; P_10_5: TPanel; P_10_6: TPanel; P_10_7: TPanel; P_10_8: TPanel; P_10_9: TPanel; P_10_10: TPanel; P_10_11: TPanel; P_10_12: TPanel; P_10_13: TPanel; P_10_14: TPanel; P_11_0: TPanel; P_11_1: TPanel; P_11_2: TPanel; P_11_3: TPanel; P_11_4: TPanel; P_11_5: TPanel; P_11_6: TPanel; P_11_7: TPanel; P_11_8: TPanel; P_11_9: TPanel; P_11_10: TPanel; P_11_11: TPanel; P_11_12: TPanel; P_11_13: TPanel; P_11_14: TPanel; P_12_0: TPanel; P_12_1: TPanel; P_12_2: TPanel; P_12_3: TPanel; P_12_4: TPanel; P_12_5: TPanel; P_12_6: TPanel; P_12_7: TPanel; P_12_8: TPanel; P_12_9: TPanel; P_12_10: TPanel; P_12_11: TPanel; P_12_12: TPanel; P_12_13: TPanel; P_12_14: TPanel; P_13_0: TPanel; P_13_1: TPanel; P_14_0: TPanel; P_14_1: TPanel; P_13_2: TPanel; P_14_2: TPanel; P_13_3: TPanel; P_14_3: TPanel; P_13_4: TPanel; P_14_4: TPanel; P_13_5: TPanel; P_14_5: TPanel; P_13_6: TPanel; P_14_6: TPanel; P_13_7: TPanel; P_14_7: TPanel; P_13_8: TPanel; P_14_8: TPanel; P_13_9: TPanel; P_14_9: TPanel; P_13_10: TPanel; P_14_10: TPanel; P_13_11: TPanel; P_14_11: TPanel; P_13_12: TPanel; P_14_12: TPanel; P_13_13: TPanel; P_14_13: TPanel; P_13_14: TPanel; P_14_14: TPanel; StringGrid1: TStringGrid; procedure CannonFire(var A,B,m:integer); procedure P_0_0MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure P_0_1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure P_1_1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; mf: array[0..14, 0..14] of boolean; //mf = Minenfeld A,B,m:integer; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); //Verteilung der Minen var i: integer; begin randomize; for i:=0 to 50 do begin A:=random(15); B:=random(15); mf[A,B]:=true; StringGrid1.Cells[A,B]:='M'; end; end; procedure TForm1.CannonFire(var A,B,m:integer); //Procedure für Linksklick var z:integer; begin if mf[A,B]=false then //Falls keine Mine... begin m:=0; if (A+1>=0) and (A+1<=14) and (B>=0) and (B<=14) then if mf[A+1,B]=true then m:=m+1; if (A+1>=0) and (A+1<=14) and (B+1>=0) and (B+1<=14) then if mf[A+1,B+1]=true then m:=m+1; if (A>=0) and (A<=14) and (B+1>=0) and (B+1<=14) then if mf[A,B+1]=true then m:=m+1; if (A-1>=0) and (A-1<=14) and (B+1>=0) and (B+1<=14) then if mf[A-1,B+1]=true then m:=m+1; if (A-1>=0) and (A-1<=14) and (B>=0) and (B<=14) then if mf[A-1,B]=true then m:=m+1; if (A-1>=0) and (A-1<=14) and (B-1>=0) and (B-1<=14) then if mf[A-1,B-1]=true then m:=m+1; if (A>=0) and (A<=14) and (B-1>=0) and (B-1<=14) then if mf[A,B-1]=true then m:=m+1; if (A+1>=0) and (A+1<=14) and (B-1>=0) and (B-1<=14) then if mf[A+1,B-1]=true then m:=m+1; if m=0 then begin //Hier soll der beschriebene Fall programmiert werden repeat until z=1; end; end; if mf[A,B]=true then //Falls Mine getroffen wurde.. begin ShowMessage('Du hast Verloren!'); close; end; end; //---------------------------------------------------------------Folgend: Einbindung Panels procedure TForm1.P_0_0MouseDown(Sender: TObject; Button: TMouseButton; //Panel_0_0 Shift: TShiftState; X, Y: Integer); var s:string; c:char; begin s := P_0_0.Caption; //Rechtsklick if s <> '' then c := s[1] else c := ' '; if (Button = mbRight) then case c of ' ': c := 'F'; 'F': c := '?'; else c := ' '; end; P_0_0.Caption := c; if (Button = mbLeft) then //Linksklick begin A:=0; B:=0; CannonFire(A,B,m); P_0_0.Caption:=IntToStr(m); P_0_0.Enabled:=false; end; end; procedure TForm1.P_0_1MouseDown(Sender: TObject; Button: TMouseButton; //Panel_0_1 Shift: TShiftState; X, Y: Integer); var s:string; c:char; begin s := P_0_1.Caption; if s <> '' then c := s[1] else c := ' '; if (Button = mbRight) then case c of ' ': c := 'F'; 'F': c := '?'; else c := ' '; end; P_0_1.Caption := c; if (Button = mbLeft) then begin A:=1; B:=0; CannonFire(A,B,m); P_0_1.Caption:=IntToStr(m); P_0_1.Enabled:=false; end; end; procedure TForm1.P_1_1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var s:string; c:char; begin s := P_1_1.Caption; if s <> '' then c := s[1] else c := ' '; if (Button = mbRight) then case c of ' ': c := 'F'; 'F': c := '?'; else c := ' '; end; P_1_1.Caption := c; if (Button = mbLeft) then begin A:=1; B:=1; CannonFire(A,B,m); P_1_1.Caption:=IntToStr(m); P_1_1.Enabled:=false; end; end; end. |
AW: Minesweeper
Kleine Grundregel:
Was ich nicht erklären kann, habe ich nicht verstanden, kann ich auch nicht programmieren, egal wie fit ich in der Programmiersprache bin. Also, ergründe, was da genau passieren soll. Nimm dazu ein Blatt und Stift und male die Situation auf und spiele das auf dem Blatt durch. Das machst du so lange bis du das verstanden hast. Dann leite daraus eine allgemeine Vorgehensweise ab. Wenn du uns also das erklären kannst, dann helfen wir dir gerne bei der Umsetzung in Delphi weiter :) |
AW: Minesweeper
Alles klar, Ich probiers mal aus :)
|
AW: Minesweeper
Kleine Zwischenfrage:
Kann ich irgendwie über Variablen ein Panel anwählen? Ich möchte in einer Prozedur die Caption von mehreren Panels ändern. In der Prozedur arbeite ich mit einem Array und ich möchte im Prinzip Koordinaten des Arrays mit einem Panel verknüpfen. Ansonsten komme ich vorwärts. Nur da brauch ich grad wirklich Hilfe. |
AW: Minesweeper
Jede Komponente auf der Form (die mit dem OI dort hin gekommen ist) hat eine Variable, die eine Referenz auf die Komponente beinhaltet.
Du suchst aber wohl eher ein Panel-Array. Dann erstelle dir so ein Panel-Array und trage die Panels dort ein, schon kannst du die über das Array ansprechen. So ganz nebenbei hätte ich das eher mit einem DrawGrid gemacht (oder mit einer PaintBox und alles selber gezeichnet), aber niemals mit so einem Komponenten-Haufen. Aber jeder wie er mag :) |
AW: Minesweeper
Ich hab das DrawGrid noch nie genutzt.
Das läuft auch Koordinaten und hat das OnMouseDown-Ereignis? Und dann statt Panels und dem Array einfach nur ein DrawGrid? |
AW: Minesweeper
Liste der Anhänge anzeigen (Anzahl: 1)
Nur ein kleiner Tipp: das mit den Panels ist keine tolle Idee, denn es macht dich sehr unflexibel. Sowas (das Feld) zeichnet man entweder auf der Form, PaintBox oder Image. Die Zelle ermittelt man durch die Berechnung (Breite des Feldes geteilt durch breite Zelle, gleich Zelle). Hört sich zuerst kompliziert an, ist aber hundert mal einfacher als es mit Panelen zu machen.
Ich hab im Anhang ein kleines Beispiel. Das "Spiel" habe ich mal gemacht als einer Schiffe versenken programmieren wollte und auch Panele nehmen wollte. Guck dir mal in der Funktion FeldKoordinate wie das Feld aus einer Image berechnet wird (und natürlich auch das OnMouseUp Ereignis von Image) und in DrawMatrix wie man ein Feld zeichnet. |
AW: Minesweeper
Und selbst wenn Du Panel's nehmen willst...
Aber dann bitte nicht Zusammengeklickt sondern dynamisch erzeugen...
Delphi-Quellcode:
Mavarik
Procedure TForm1.InitFeld;
var X,Y : Integer; begin for X := 0 to XMAX do for Y := 0 to YMAX do begin MeinCoolesPanelArray[X,Y] := TPanel.Create(Self); MeinCoolesPanelArray[X,Y].Parent := self; MeinCoolesPanelArray[X,Y].Left := StartX + X*XSize; MeinCoolesPanelArray[X,Y].Top := StartY + Y*YSize; MeinCoolesPanelArray[X,Y].Width := XSize-XRand; MeinCoolesPanelArray[X,Y].Height:= YSize-YRand; MeinCollesPanelArray[X,Y].OnClick := PanelClick; .... end; end; |
AW: Minesweeper
Macht es Sinn über Self.Compenents auf die Panels zuzugreifen?
(A und B sind global als integer definiert)
Delphi-Quellcode:
Leider krieg ich so in der "Panel:=TPanel.."-Zeile die Meldung "[Fehler] Unit1.pas(334): Inkompatible Typen: 'Integer' und 'String'"
var s:String;
Panel:TPanel; begin A:=0; B:=0; Panel:=TPanel(Self.Components['P_'+IntToStr(A)+'_'+IntToStr(B)]); s:=Panel.Caption; //... end; |
AW: Minesweeper
Wenn es funktioniert, dann funktioniert es eben. Du kannst dir auch FindComponent an genauer angucken.
Das einzige Problem was ich an deinem Code sehe ist, du solltest vorher prüfen ob die Komponente auch wirklich exisiert, bevor du auf sie zugreifst. Ansonsten gibt es eine böse Fehlermeldung. //Edit: Ich sehe gerade den Fehler. Components erwartet einen Index (Zahl), keinen Text. Also z. B. Self.Components[5]. Die Kunst ist nun herauszufinden welchen Index das Panel 'P_'+IntToStr(A)+'_'+IntToStr(B) hat. //Edit 2: Eine Möglichkeit der Suche, vorausgesetzt du nimmst nicht FindComponent, wäre:
Delphi-Quellcode:
var
i: Integer; Gesucht: String; begin Gesucht := 'P_'+IntToStr(1)+'_'+IntToStr(5); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = Gesucht then begin ShowMessage('Die Gesuchte Komponente hat den Index: ' + IntToStr(i)); Break; end; end; end; |
AW: Minesweeper
![]() Und nun rate mal, warum es nicht funktioniert, wobei dir der Compiler das auch schon deutlich erklärt hat, wenn du schon selber nicht auf die Idee kommst und in die Hilfe schaust. |
AW: Minesweeper
Vielen Dank Popov. Soweit funktioniert's :)
Das macht die Aktivierung von 225 Panels VIEL einfacher :-D Jetzt setz ich mich noch an daran, dass wenn das angeklickte Panel KEINE angrenzenden Minen hat, alle benachbarten Panels "aufgedeckt" werden, die eben falls keine angrenzenden Minen haben und eine Art Ring aus Panels entsteht, die anzeigen, wieviele Minen angrenzen. Ich probier das mal aus und melde mich dann nochmal :) |
AW: Minesweeper
Kleines Update:
Hab es erstmal so gemacht, dass wenn man ein Panel anklickt, dass keine angrenzenden Minen hat, alle Panels "aufgedeckt" werden, die ebenfalls keine angrenzenden Minen haben und wiederum deren bnachbarten Panels, sodass die zuvor erwähnten Ringe aus Zahlen entstehen. Im Original werden nur die aufgedeckt, die benachbart sind, aber das reicht mir so erstmal. Mein Problem ist nun, dass in 7 von 10 Versuchen, eine Zahl auf einem Panel erscheint, die unmöglich ist (zB -1, 227, 981256). Diese erscheint NICHT immer dem gleichen Panel! Ich komme nicht drauf, warum solch eine Zahl entsteht. Falls ihr möchtet könntet ihr ja mal kurz einsehen. Ich wäre euch sehr dankbar! Relevanter Quellcode + Screenshot des gemeinten Falles anbei. (das StringGrid benutze ich, um sehen zu können wo die Minen sind) *Edit: Hab das Problem gefunden (glaube Ich) Könnte sein, dass ich die Panels nicht in der Reihenfolge gesetzt habe, in der sie da sind. Funktioniert die ganze Component-Aktion dadurch nicht richtig? Krieg ich das nur durch das neu platzieren von 225 Panels wieder hin? ![]()
Delphi-Quellcode:
procedure TForm1.CannonFire(var A,B,m:integer); //Procedure für Linksklick
var h,j:integer; begin if mf[A,B]<>9 then //Falls keine Minen... begin m:=mf[A,B]; if mf[A,B]=0 then begin h:=A; j:=B; for h:= 0 to 14 do begin for j:=0 to 14 do begin if mf[h,j]=0 then begin g := 'P_'+IntToStr(j)+'_'+IntToStr(h); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:='_'; if (h+1>=0) and (h+1<=14) and (j>=0) and (j<=14) then begin g := 'P_'+IntToStr(j)+'_'+IntToStr(h+1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h+1,j]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h+1>=0) and (h+1<=14) and (j+1>=0) and (j+1<=14) then begin g := 'P_'+IntToStr(j+1)+'_'+IntToStr(h+1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h+1,j+1]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h>=0) and (h<=14) and (j+1>=0) and (j+1<=14) then begin g := 'P_'+IntToStr(j+1)+'_'+IntToStr(h); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h,j+1]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h-1>=0) and (h-1<=14) and (j+1>=0) and (j+1<=14) then begin g := 'P_'+IntToStr(j+1)+'_'+IntToStr(h-1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h-1,j+1]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h-1>=0) and (h-1<=14) and (j>=0) and (j<=14) then begin g := 'P_'+IntToStr(j)+'_'+IntToStr(h-1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h+1,j]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h-1>=0) and (h-1<=14) and (j-1>=0) and (j-1<=14) then begin g := 'P_'+IntToStr(j-1)+'_'+IntToStr(h-1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h-1,j-1]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h>=0) and (h<=14) and (j-1>=0) and (j-1<=14) then begin g := 'P_'+IntToStr(j-1)+'_'+IntToStr(h); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h,j-1]); if Panel.Caption='0' then Panel.Caption:='_'; end; if (h+1>=0) and (h+1<=14) and (j-1>=0) and (j-1<=14) then begin g := 'P_'+IntToStr(j-1)+'_'+IntToStr(h+1); for i := 0 to Self.ComponentCount - 1 do begin if Self.Components[i].Name = g then Panel:=TPanel(Self.Components[i]); end; Panel.Caption:=IntToStr(mf[h+1,j-1]); if Panel.Caption='0' then Panel.Caption:='_'; end; end; end; end; end; end; if mf[A,B]=9 then //Falls Mine getroffen wurde.. begin ShowMessage('Du hast Verloren!'); close; end; end; |
AW: Minesweeper
Zitat:
Zitat:
Warum auch immer Du unbedingt 10000 Zeilen tippen willst, wenn es auch in 25 geht... |
AW: Minesweeper
Wenn jemand nicht auf uns und auch nicht auf den Compiler hört, dann hat er halt Pech.
Zitat:
Zitat:
Delphi-Quellcode:
nichts treffen würde.
Name = g
9 Mal der selbe Code, nur durch ein +/-1 unterscheidend ... ja, das sieht nach einer zwei Schleifen aus. Aber wenn ich das genau seh, dann frag ich mich, wieso man jedem einzelnem Panel bis zu 9 Mal den selben Text zuweisen sollte, denn genau das macht der Code, durch die h+j-Schleife und die inneren IFs/Schleifen. FindCompoment wurde ja auch erwähnt, aber wenn man die Komponenten einmal einem zweidimensionalem Array zuweist, beim Programmstart, oder das Zeug garnicht erst umständlich in die Form geklickt hätte, sondern es dynamisch erzeugen und dabei gleich in dem Array speichern würde, was ja auch schon genannt wurde, dann wäre alles so viel einfacher. Und warum werden A und B als Var-Parameter eingegeben, wo sie doch nur ausgelesen, aber niemals gesetzt werden? |
AW: Minesweeper
Zitat:
|
AW: Minesweeper
@Mavarik
Für dich ist es gruselig. Ein Anfänger sieht da nur die Vorteile, der da einer wäre: da ist ein Feld, da klickt man drauf, da erhält man ein Ereignis. Man muss zwar 255 Panele plazieren und auswerten, aber der Hauptvorteil ist, man spart sich vier Zeilen Code über den man drei Minuten komplex nachdenken muss. Ich persönlich hätte noch nicht mal Panels genommen. |
AW: Minesweeper
Zitat:
Stundenlanges Panel's auf dem Form platzieren was man in 10 Sekunden und 2 for schleifen machen kann... Abgesehen davon wird das Form auch in "endlicher" Zeit in die IDE geladen... Außerdem habe ich die Pannels direct in meinem Array und muss die nicht erst wieder mühsam über die Componentenliste suchen... Abgesehen von 200 onclick Handlern |
AW: Minesweeper
100 (10*10) Panels hab ich in nichtmal 20-30 Sekunden auf der Form platziert (Copy&Paste) ... aber dann muß/sollte man den Dingern auch noch einen Namen verpassen. :stupid:
|
AW: Minesweeper
Liste der Anhänge anzeigen (Anzahl: 1)
@Mavarik
Ich hab nicht gesagt, dass man sich Code und Zeit spart, sondern, dass man sich paar Zeilen komplexen Code spart. |
AW: Minesweeper
Ich glaube Du hast da etwas falsch verstanden...
MEIN Beispiel war doch so wie Dein Source... |
AW: Minesweeper
Vielen Dank für die Kritik und Berichtigungen.
Manche Sachen die hier genannt werden probier ich halt aus, aber als quasi-Anfänger komm ich dann auch schnell nicht weiter. Ich hab mich jetzt jedenfalls entschieden ein PanelArray zu generieren. Meine Frage: Wie erstelle ich die Prozedur für das OnMouseDown-Ereignis?
Delphi-Quellcode:
begin
Panel := TPanel.Create(Self); Panel.Parent := Self; Panel.Name := 'P_' + IntToStr(x) + '_' + IntToStr(y); Panel.Width := WH; Panel.Height := WH; Panel.Caption := ''; Panel.Left := x1 + (x * WH); Panel.Top := y1 + (y * WH); Panel.OnMouseDown := PanelMatrixMouseDown( {?} ); end; |
AW: Minesweeper
Die Zuweisung der Prozedur zum Ereignis erfolgt ohne Klammern und ohne Parameter, also nur der Prozedurname.
Delphi-Quellcode:
Panel.OnMouseDown := PanelMatrixMouseDown;
|
AW: Minesweeper
Zitat:
Nimm ein Panel und mach da Click auf Mousedown oder auf OnClick geh in den Source... Kopieren die Procedure von oben in den Privat teil und drücke Speichern, damit das Form die Procedure "vergißt"... Schon hast Du die Procedure mit den richtigen Parametern. Mavarik |
AW: Minesweeper
Danke BadenPower und Mavarik.
Mal sehen wie weit ich komme :) |
AW: Minesweeper
Ich wollte mit
Delphi-Quellcode:
(falls das funktioniert hätte) A aus dem Namen des Panels bestimmen,
A:=StrToInt(Panel.Name[3]);
aber das Problem ist, dass der Name des Panels an der Stelle (zB P_4_7) auch zweistellig sein kann. (P_10_13) Wenn ihr wisst was ich meine.. wie löse ich das Problem? oder gibt es eh einen besseren Weg? |
AW: Minesweeper
Für was brauchst Du das A?
Auf das auslösende Panel kannst Du in der Event-Prozedure mit
Delphi-Quellcode:
zugreifen.
DiesesPanel := TPanel(Sender);
|
AW: Minesweeper
Und anstatt du Dinger nachträglich zu suchen, hätte man die auch automatisch erstellen können, dabei einem zweidimensionalem Array zugewiesen und hätte den ganze Quatsch mit den Namen auch lassen können.
PS: Man kann Zahlen auch immer zweistellig schreiben. 01 :stupid: |
AW: Minesweeper
Ich nutze jetzt zusätzlich zum PanelArray ein weiteres IntegerArray weil ich die einzelnen Panels einen Wert von 0 bis 9 zuweise und Ich nicht weiß wie ich das mit einem PanelArray anstellen soll.
Ich brauche A, um aus dem TPanel die Koordinaten zu entnehmen. DAs geht bestimmt einfacher, oder? |
AW: Minesweeper
Himitsu, ich erstelle die Panels automatisch und benenne sie (warum weiß ich auch nicht, wie ich gerade bemerke)
Von daher weiß ich auch nicht, wie ich die zweistellig benennen soll.
Delphi-Quellcode:
procedure TForm1.CreatePanelMatrix(x1, y1: Integer);
var x,y:integer; begin for x := 0 to 14 do for y := 0 to 14 do begin Panel := TPanel.Create(Self); Panel.Parent := Self; Panel.Name := 'P_' + IntToStr(x) + '_' + IntToStr(y); Panel.Width := 30; Panel.Height := 30; Panel.Caption := ''; Panel.Left := x1 + (x * 30); Panel.Top := y1 + (y * 30); Panel.OnMouseDown := PanelMatrixMouseDown; end; end; |
AW: Minesweeper
Du brauchst nur die Pointer abspeichern.
Delphi-Quellcode:
Und in deiner CreatePanelMatrix
var
Panels: array[0..14, 0..14] of TPanel; function IndexOfPanel(Panel: TPanel): TPoint; var X, Y: integer; begin Result.X := -1; Result.Y := -1; for X := 0 to 14 do for Y := 0 to 14 do if Panels[X, Y] = Panel then begin Result.X := X; Result.Y := Y; end; end;
Delphi-Quellcode:
Panels[I, J] := Panel;
|
AW: Minesweeper
Sorry Ich versteh nicht was du meinst :(
Und was das mir bringt erst recht nicht. Falls das hilft ist hier mal mein kompletter Code:
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Grids; type TForm1 = class(TForm) StringGrid1: TStringGrid; procedure FormCreate(Sender: TObject); procedure CannonFire(var A,B,m:integer; Sender: TObject); procedure PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private { Private-Deklarationen } public { Public-Deklarationen } procedure CreatePanelMatrix(x1, y1: Integer); end; var Form1: TForm1; implementation {$R *.dfm} var PanelA: array[0..14, 0..14] of TPanel; IntA: array[0..14, 0..14] of integer; Panel: TPanel; A,B,m:integer; procedure TForm1.CreatePanelMatrix(x1, y1: Integer); var x,y:integer; begin for x := 0 to 14 do for y := 0 to 14 do begin Panel := TPanel.Create(Self); Panel.Parent := Self; Panel.Name := 'P_' + IntToStr(x) + '_' + IntToStr(y); Panel.Width := 30; Panel.Height := 30; Panel.Caption := ''; Panel.Left := x1 + (x * 30); Panel.Top := y1 + (y * 30); Panel.OnMouseDown := PanelMatrixMouseDown; end; end; procedure TForm1.FormCreate(Sender: TObject); var k,Ai,Bi: integer; begin randomize; for k:=0 to 25 do begin A:=random(15); B:=random(15); IntA[A,B]:=9; StringGrid1.Cells[A,B]:='X'; end; for Ai:=0 to 14 do begin for Bi:=0 to 14 do begin if IntA[Ai,Bi]<>9 then begin m:=0; if (Ai+1>=0) and (Ai+1<=14) and (Bi>=0) and (Bi<=14) then if IntA[Ai+1,Bi]=9 then m:=m+1; if (Ai+1>=0) and (Ai+1<=14) and (Bi+1>=0) and (Bi+1<=14) then if IntA[Ai+1,Bi+1]=9 then m:=m+1; if (Ai>=0) and (Ai<=14) and (Bi+1>=0) and (Bi+1<=14) then if IntA[Ai,Bi+1]=9 then m:=m+1; if (Ai-1>=0) and (Ai-1<=14) and (Bi+1>=0) and (Bi+1<=14) then if IntA[Ai-1,Bi+1]=9 then m:=m+1; if (Ai-1>=0) and (Ai-1<=14) and (Bi>=0) and (Bi<=14) then if IntA[Ai-1,Bi]=9 then m:=m+1; if (Ai-1>=0) and (Ai-1<=14) and (Bi-1>=0) and (Bi-1<=14) then if IntA[Ai-1,Bi-1]=9 then m:=m+1; if (Ai>=0) and (Ai<=14) and (Bi-1>=0) and (Bi-1<=14) then if IntA[Ai,Bi-1]=9 then m:=m+1; if (Ai+1>=0) and (Ai+1<=14) and (Bi-1>=0) and (Bi-1<=14) then if IntA[Ai+1,Bi-1]=9 then m:=m+1; IntA[Ai,Bi]:=m; StringGrid1.Cells[Ai,Bi]:=IntToStr(m); if m=0 then StringGrid1.Cells[Ai,Bi]:='_'; end; end; end; CreatePanelMatrix(20,20); end; procedure TForm1.CannonFire(var A,B,m:integer; Sender: TObject); var h,j:integer; begin Panel:=TPanel(Sender); if IntA[A,B]<>9 then begin m:=IntA[A,B]; if IntA[A,B]=0 then begin for h:= 0 to 14 do begin for j:=0 to 14 do begin if IntA[h,j]=0 then PanelA[h,j].Caption:='_'; if (h+1>=0) and (h+1<=14) and (j>=0) and (j<=14) then PanelA[h+1,j].Caption:='_'; if (h+1>=0) and (h+1<=14) and (j+1>=0) and (j+1<=14) then PanelA[h+1,j+1+1].Caption:='_'; if (h>=0) and (h<=14) and (j+1>=0) and (j+1<=14) then PanelA[h,j+1].Caption:='_'; if (h-1>=0) and (h-1<=14) and (j+1>=0) and (j+1<=14) then PanelA[h-1,j+1].Caption:='_'; if (h-1>=0) and (h-1<=14) and (j>=0) and (j<=14) then PanelA[h-1,j].Caption:='_'; if (h-1>=0) and (h-1<=14) and (j-1>=0) and (j-1<=14) then PanelA[h-1,j-1].Caption:='_'; if (h>=0) and (h<=14) and (j-1>=0) and (j-1<=14) then PanelA[h,j-1].Caption:='_'; if (h+1>=0) and (h+1<=14) and (j-1>=0) and (j-1<=14) then PanelA[h+1,j-1].Caption:='_'; end; end; end; end; if IntA[A,B]=9 then begin ShowMessage('Du hast Verloren!'); close; end; end; procedure TForm1.PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var s:string; c:char; begin if not (Sender is TPanel) then Exit; Panel:=TPanel(Sender); A:=StrToInt(Panel.Name[3]); // <-- Hier ist B:=StrToInt(Panel.Name[5]); // <-- das Problem. if Button=mbRight then begin s := Panel.Caption; if s <> '' then c := s[1] else c := ' '; case c of ' ': c := 'F'; 'F': c := '?'; else c := ' '; end; Panel.Caption := c; end; if Button=mbLeft then begin CannonFire(A,B,m,Sender); Panel.Caption:=IntToStr(m); if m=0 then Panel.Caption:='_'; Panel.Enabled:=false; end; end; end. |
AW: Minesweeper
Du suchst doch Row und Col des Panels auf das geklickt wurde?
Delphi-Quellcode:
procedure TForm1.PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var S: string; C: char; Panel: TPanel; Row, Col: integer; begin if Sender is TPanel then begin Panel := TPanel(Sender); Col := IndexOfPanel(Panel).X; Row := IndexOfPanel(Panel).Y; .. |
AW: Minesweeper
Zitat:
Delphi-Quellcode:
Ändere das in:
Panel.Name := 'P_' + IntToStr(x) + '_' + IntToStr(y);
...
Delphi-Quellcode:
Das Teil
Panel.Name := Format('P_%.2d_%.2d', [x, y]);
...
Delphi-Quellcode:
formatiert die Zahl im String so, dass sie (zumindest bis 99) immer zweistellig ist. Bei Zahl 10 ist die Ausgabe 10. Bei Zahl 5 ist die Ausgabe 05. Also zweistellig.
%.2d
Der String oben wird also immer von Format P_00_00 sein. Mit
Delphi-Quellcode:
kannst du das erste Zahlenpaar ermitteln. Mit Copy
Copy('P_00_00', 3, 2)
Delphi-Quellcode:
das zweite Paar.
('P_00_00', 6, 2)
Nur wie gesagt, das klappt solange der Wert unter 100 ist. Ansonsten den Code ändern in %.3d. Dann ist die Zahl dreistellig bis 999. |
AW: Minesweeper
Zitat:
Und wie bereits mehrfach erwähnt wurde, sollte man die Panels gleich speichern (siehe, wie ebenfalls grade nochmal von Jemandem gezeigt wurde)
Delphi-Quellcode:
und schon kann man den Mist mit dm Suchen weg lassen, da man die Instanzen bereits hat.
Panels[x, y] := TPanel.Create(Self);
|
AW: Minesweeper
Vielen Dank, Leute.
Ich werde mich heute nachmittag mal dran setzen :) |
AW: Minesweeper
Zitat:
Delphi-Quellcode:
Es wäre doch viel besser den Rückgabewert von IndexOfPanel() gleich in eine Variable vom Typ TPoint zu speichern, denn dann muss die Funktion nur einmal durchlaufen werden und die Variablen Col und Row würden durch Pos.X und Pos.Y ersetzt.
procedure TForm1.PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var S: string; C: char; Panel: TPanel; Pos: TPoint; begin if Sender is TPanel then begin Panel := TPanel(Sender); Pos := IndexOfPanel(Panel); ..... IntA[Pos.X,Pos.Y] := ...... Einmal abesehen davon, dass da bestimmt nichts zurückgegeben wird, da PanelA noch gar keine Werte enthält. Zitat:
|
AW: Minesweeper
Oder man hinterlegt diese Information im Panel selbst (Ableitung, Tag-Property oder wie auch immer), dann spart man sich die Suche.
|
AW: Minesweeper
Leute Bitte... Pointer im Array suchen?
Delphi-Quellcode:
procedure TForm1.CreatePanelMatrix(x1, y1: Integer); var x,y:integer; begin for x := 0 to 14 do for y := 0 to 14 do begin Panel := TPanel.Create(Self); Panel.Parent := Self; Panel.Name := 'P_' + IntToStr(x) + '_' + IntToStr(y); Panel.Width := 30; Panel.Height := 30; Panel.Caption := ''; Panel.Left := x1 + (x * 30); Panel.Top := y1 + (y * 30); Panel.OnMouseDown := PanelMatrixMouseDown; Panel.Tag := Y*15 + X; end; end; procedure TForm1.PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var s:string; c:char; Nr,A,B : Integer; begin if not (Sender is TPanel) then Exit; // Ach wer kann den noch hier geklickt haben? Panel:=TPanel(Sender); Nr := Panel.Tag; // hmm Lass mich mal überlegen da war doch was mit teilen und Rest um X und Y zu finden... :-) ... // Andererseits habe ich ggf die X und Y schon, oder A := Panel.Left; B := Panel.Top; // Wenn ich jetzt nur wüsste was ich mit A & B machen muss end; Mavarik |
AW: Minesweeper
Es geht doch noch einfacher.
Delphi-Quellcode:
procedure TForm1.CreatePanelMatrix(InitialX, InitialY: Integer);
const PANEL_WIDTH = 30; PANEL_HEIGHT = 30; COUNT_X = 15; COUNT_Y = 15; BITS_PER_BYTE = 8; var X, Y: Integer; Panel: TPanel; begin for X := 0 to COUNT_X - 1 do for Y := 0 to COUNT_Y - 1 do begin Panel := TPanel.Create(Self); Panel.Parent := Self; Panel.Width := PANEL_WIDTH; Panel.Height := PANEL_HEIGHT; Panel.Caption := ''; Panel.Left := InitialX + X * PANEL_WIDTH; Panel.Top := InitialY + Y * PANEL_HEIGHT; Panel.OnMouseDown := PanelMatrixMouseDown; Panel.Tag := X shl (BITS_PER_BYTE * SizeOf(word)) or Y; end; end; procedure TForm1.PanelMatrixMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var Position: DWORD; begin Position := DWORD((Sender as TPanel).Tag); ShowMessage(Format('X: %d, Y: %d', [HiWord(Position), LoWord(Position)])); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:36 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 by Thomas Breitkreuz