Autor |
Beitrag |
Shanks
Hält's aus hier
Beiträge: 4
Win XP
|
Verfasst: Di 11.04.06 16:11
Hi,
ich bin neu hier und auch recht neu in Sachen programmierung. Ich hoffe, dass mir hier jemand weiter helfen kann.
Ich arbeite derzeit an dem Spiel Minesweeper, welches ich mit Delphi programmieren möchte. Ich habe für die erste Stufe 81 kleine Panels erstellt ( weis nicht, ob man das einfacher machen kann). Mittels eines 2D Arrays habe ich 10 Minen verteilt. Jedes Panel hat den Namen PanelA(x)(y). Also z.B: PanelA32. Wobei die erste Ziffer für den x Wert und die zweite für den y Wert stehen soll. Wie kann ich es schaffen, dass ich die Zahlen im Panelnamen als Variablen verwenden kann?
Schonmal danke im Vorraus.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 11.04.06 16:22
Moin und  im Forum!
Schau dich mal nach dem Stichwort FINDCOMPONENT um, damit solltest du weiterkommen.
Vielleicht kannst du dir aus diesem Tut auch noch ein paar Anregungen holen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Stoney
      
Beiträge: 122
Mac OS X 10.6 "Snow Leopard", Ubuntu Linux 9.04, Mandriva 2010, Win 7, Win Vista, Win XP
Object Pascal (Turbo Delphi, FPC 2.2.4, Lazarus), C++ (Code::Blocks, XCode), Java (Eclipse)
|
Verfasst: Di 11.04.06 16:24
81 Panels zu erstellen muss doch eine Mordsarbeit gewesen, zumal ich nicht aus deinem Post herauslese, dass die dynamisch erzeugt wurden. Wenn du dir wirklich so viel Arbeit aufsatteln willst, solltest du am besten mit dem Befehl FindComponent arbeiten:
Delphi-Quelltext 1:
| (FindComponent('PanelA'+IntToStr(x)+IntToStr(y)) as TPanel).Caption := 'Mine'; |
Panels sind übrigens auch sehr speicherlastig, damit könntest du einige Computer in die Knie zwingen.
Der einfachere Lösungsweg ist das du nur ne Paintbox schnappst, und mit Hilfe von Canvas darauf malst. Oder du nimmst eine Grafikbibliothek wie DirectX, SDL oder OpenGL und bekommst noch gute Performance zusätzlich dazu.
|
|
Martin1966
      
Beiträge: 1068
Win 2000, Win XP
Delphi 7, Delphi 2005
|
Verfasst: Di 11.04.06 16:29
Hallo Shanks!
Willkommen in der Entwickler-Ecke!
Du kannst auch das Draw-Grid. Das wird denke ich noch einfacher sein.
Lg Martin
_________________ Ein Nutzer der Ecke
|
|
Shanks 
Hält's aus hier
Beiträge: 4
Win XP
|
Verfasst: Di 11.04.06 16:46
Erstmal danke für eure schnellen Antworten. Vielleicht wäre es für euch hilfreich, wenn ich mein Problem besser erkläre. Bei dem FindComponent schein ich irgendwas falsch zu machen, denn es klappt nicht. Also hier ne bessere erklärung. entweder habt ihr mich missverstanden oder ich bin zu dumm. ( ich tippe auf letzteres  )
Also ich habe einen Globale 2D Array "FeldA[1..9,1..9] of boolean" erstellt. 2D, weil das Feld ja 81 Felder (Panels) hat. Je nach rechts und unten 9 Stück. Jede Reihe nach rechts hat einen X Wert von 1 bis 9 und auch jede Reihe nach Unten. (Y Wert, 1 bis 9).
Also habe ich vorhin etwas falsch erklärt. z.B. haben die Panels in der obersten Reihe die Zahlen : 11,12,13.... 19. ab dann beginnt die zweite Reihe, nur das sich der Y Wert um eine Zahl erhöht hat, also : 21,22,23.... 29.
Nun habe ich (oder hatte es vor, weil das klappt auch noch nicht so recht) 10 Minen in diesem Array mit dem boolean Wert "True" gesetzt. (bei mir setzt der immer nur eine, trotz "For Schleife")
Nun möchte ich, dass man, wenn man auf ein Panel klickt, ich die Zahlen im Namen als Variable x und y nutzen kann um im Array abzufragen, ob das besagte Feld "True" ist oder nicht.
Eine andere Frage wäre auch noch. Muss ich dafür jedes einzelne Panel mit
"procedure TForm1.PanelA......;
programmieren, oder gibt es eine alles umfassende procedure, mit der ich nicht jedes einzelne Panel neu programmieren müsste?
So ich hoffe ich konnte es etwas besser erklären, falls immer noch unklarheiten sein sollten, kopier ich meine bisherige Codierung ins Forum (ist eh nicht viel)
|
|
Martin1966
      
Beiträge: 1068
Win 2000, Win XP
Delphi 7, Delphi 2005
|
Verfasst: Di 11.04.06 16:59
Hallo!
Ich denke, wir haben dich schon verstanden.  Nur die Info mit der Nummerierung ist neu.
Allerdings würde ich dir immer noch empfehlen das ganze nicht mit Panels zu machen. Wenn du es mit Panels machst dann schleichen sich immer wieder Probleme auf die Du zu lösen hast die Du zum Beispiel mit einem DrawGrid nicht hättest.
Lösche am besten also deine ganzen Panels von deinem Form und erstelle ein DrawGrid mit der entsprechenden Anzahl an Spalten und Reihen. Dort musst du dann das Draw-Event verwenden um die Zellen zu zeichnen.
Dein 2 dimensionales Array sollte nicht aus lauter Boolean Werten bestehen sondern am besten aus einem oder noch besser jeweils zwei Aufzählungstypen. Ein Boolean Wert der festlegt ob hnter der Zelle eine Bombe liegt und ein Aufzählungstype der festlegt ob der User die Zelle schon aufegeckt hat oder nicht oder ob der User dort eine Bombe vermutet.
Beim zeichnen der einzelnen Zellen im DrawGrid kannst du dann den Array verwenden und die entsprechenden Symbole zeichnen.
Dies nur mal so als kleine Hinweise.
Lg Martin
_________________ Ein Nutzer der Ecke
|
|
Simon Joker
      
Beiträge: 236
Erhaltene Danke: 1
|
Verfasst: Mi 12.04.06 10:27
Hallo Shanks
Erstmal willkommen
@Benutzung von Panels
Die Idee halte ich nicht für so schlecht.
Hinweise:
Datenspeicherung - Ich würde hier wohl kein zweidimensionales Array nehmen, sondern mit einem Eindimensionalen. Die Verwaltung wird so sehr einfach und du brauchst NICHT den Namen der Panels zu parsen um die Richtigen Daten abzufragen. (weiteres dazu weiter untern)
Datentyp - Verwende ein Record mit allen relevanten Daten für das Daten-Array, spart viel Sucherei. Außerdem würde ich ein dynamisches Array empfehlen. Das kannst du ohne Codeänderung auf andere Größen des Minenfeldes scalieren.
Beispiel:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| type TViewStats = (vsUnknown,vsFlagged,vsViewed,vsReference);
TMineFieldRec = record GridPosition : TPoint; ViewPanel : TPanel; HaveMine : boolean; NearMines : byte; ViewStat : TViewStats; end; TMineFieldArray = array of TMineFieldRec; |
Da so die größe des Spielfeldes dynamisch ist, sollten auch die Panels dynamisch sein. Dafür braucht es etwas Vorbereitung. Du brauchst dafür Event-Proceduren, die für alle Panels gelten können.
Die Erzeugung sollte in etwa so aussehen.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| var NewMinePanel : TPanel; i, PosIndexX, PosIndexY, PosPixX, PosPixY : integer; ... PanelGround.Visible := false; SetLength(MineFieldArray,CountRow*CountCol); for i := 0 to high(MineFieldArray) do begin PosIndexX := i mod CountCol; PosIndexY := i div CountCol; PosPixX := PosIndexX * 20; PosPixY := PosIndexY * 20; NewMinePanel := TPanel.Create(PanelGround); NewMinePanel.Parent := PanelGround; NewMinePanel.Tag := i+1; NewMinePanel.Name := 'MinePanel_'+IntToStr(i); NewMinePanel.Left := PosPixX; NewMinePanel.Top := PosPixY; NewMinePanel.Caption := ''; NewMinePanel.OnClick := DynPanelOnClick; NewMinePanel.Width := 20; NewMinePanel.Height := 20; MineFieldArray[i].GridPosition.X := PosIndexX; MineFieldArray[i].GridPosition.Y := PosIndexY ; MineFieldArray[i].ViewPanel := NewMinePanel; MineFieldArray[i].HaveMine := false; MineFieldArray[i].NearMines := 0; MineFieldArray[i].ViewStat := vsUnknown; end;
...
PanelGround.Visible := true; |
Beispiel für die dynamischen Proceduren.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.DynPanelOnClick(Sender: TObject); var MinePanel : TPanel; MineData : TMineFieldRec; begin if Sender is TPanel then begin MinePanel := TPanel(Sender); if (MinePanel.Tag-1 >= 0) and (MinePanel.Tag-1 <= high(MineFieldArray)) then begin MineData := MineFieldArray[MinePanel.Tag-1]; ...
end; end; end; |
So viel Spass
MfG Simon
|
|
Shanks 
Hält's aus hier
Beiträge: 4
Win XP
|
Verfasst: Do 13.04.06 12:53
Ich bin zwar dankbar für eure vielen Antworten, aber leider kann ich mit den meisten nichts anfangen, da ich kaum ahnung vom Programmieren habe.
Ich habe es mal mit findComponent probiert, aber nur merkwürdige Zahlenwerte bekommen. (über 40.000)
Wie schaffe ich es also, alle 81 Panels mit nur einer Procedure, oder Function anzusprechen?
Und wie bekomm ich das genau hin, mit dem findComponent. Mein Lehrer meinte (als kleine hilfestellung) etwas in der Art: TPanel(findComponent(PanelA'+IntToStr(x)+IntToStr(y)));
Aber damit bekam ich merkwürdige Werte ausgespuckt. Ich bräuchte derzeit wirklich nur hilfe dabei, wie ich die Zahlen aus dem Panelnamen als Variablen verwenden kann und umgekehrt, also wieder die Variablen in den Panelnamen einfügen kann.
Ich weis, dass ich mit meiner unwissenheit nerve, aber als Anfänger bleibt mir leider keine andere Wahl.
|
|
Shanks 
Hält's aus hier
Beiträge: 4
Win XP
|
Verfasst: Fr 14.04.06 10:54
Ich habe mich jetzt durchgerungen, mein Spiel anders zu gestalten. Möchte es jetzt mit einem Image anfertigen. Jedoch klappt das auch mal wieder überhaupt nicht und ich kann den dummen Fehler nicht finden. Ich schreib jetzt mal meine Codierung zum Zeichnen des Spielfeldes und hoffe, dass mir irgendwer helfen kann.
procedure MinenfeldZeichnen(pMaxX, pMaxY : integer);
var x, y, Feldx, Feldy : integer;
begin
with Form1.Image1 do
begin
Feldx := trunc(Width/AMaxX);
Feldy := trunc(Height/AMaxY);
for y := 1 to pMaxY do
for x := 1 to pMaxX do
Canvas.Brush.Color := clGray;
Canvas.Rectangle(x*Feldx-Feldx,y*Feldy-Feldy,x*Feldx,y*Feldy);
end;
end;
Wenn ich es so mache, seh ich nur unten rechts in der Ecke einen kleinen Strich.
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Sa 13.05.06 13:30
Hi
hab auch mal ein Minesweeper gemacht. Ähnlich wie du hab ich BitBtns statt Panels benutzt benutzt und ein 2D-array. jetzt hab ich bei jedem button bei onclick das dann ungefähr so gemacht (hab ich grad etwas modifiziert und weiß nicht obs so funzt.
Button363:=DOCLICK(3,19,Button363);
(ne ziemliche Arbeit bei alle Buttons  )
soll heißen: DoClick ist ne function mit Result vom Typ TButton. ich gebe der funktion X,Y-Position des Buttons zum zugehörigen Array-Feld. Zudem geb ich ihm den alten Button (wegen Name usw.). In der Funktion
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
| function DoClick(X,Y: integer; Buttoner: TButton) :TButton; var A: integer; begin
with Form1.Buttoner do begin A:=Data[X,Y]; Glyph:=ClearButton.Glyph; if Marking=true then begin Marking:=False; Glyph.LoadFromFile('LEDRedON.BMP'); Caption:=''; Font.Color:=clSilver; end else if Delete=true then begin Delete:=False; Caption:=''; Font.Color:=clSilver; end else begin if A=0 then begin Font.Color:=clWhite; Caption:='-'; end; if A=1 then begin Font.Color:=$00A4FFFF; Caption:='1'; end; ... if A=100 then begin Font.Color:=clRed; Caption:=''; Glyph.LoadfromFile('Mine.bmp'); try Form1.MediaPlayer1.Play; except end; end; end; Result:=Buttoner; end; end; |
müsste so funktionieren, hab grad noch etwas dran rumgebastelt, war schon lange her als ich das Prog gemacht hab.
Xion
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
|