Delphi-PRAXiS
Seite 12 von 14   « Erste     2101112 1314      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Minesweeper (https://www.delphipraxis.net/184385-minesweeper.html)

BadenPower 26. Mär 2015 17:50

AW: Minesweeper
 
Zitat:

Zitat von saii (Beitrag 1294972)
Sicher? Eigentlich existiert PanelA[X,Y] da doch schon. Das wird doch in FormCreate erstellt.


Wenn Du Deinen Code aus #32 benutzt

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;

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;
dann habe ich Dich bereits in #37 davon in Kenntnis gesetzt, dass die Panels dem Array gar nicht zugewiesen werden.

Wenn Du inzwischen etwas verändert hast, dann poste nochmals den entsprechenden Code.

Mavarik 26. Mär 2015 17:55

AW: Minesweeper
 
Zitat:

Zitat von BadenPower (Beitrag 1294974)
dann habe ich Dich bereits in #37 davon in Kenntnis gesetzt, dass die Panels dem Array gar nicht zugewiesen werden.

hmm oder man hätte einfach den Code aus Posting #8 übernommen...

Delphi-Quellcode:
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;

Popov 26. Mär 2015 19:05

AW: Minesweeper
 
@saii

Ich hab mir dein Beispiel angeguckt. Zuerst mal das:
Delphi-Quellcode:
  for k:=0 to 25 do
  begin
        A:=random(15);
        B:=random(15);
        IntA[A,B]:=9;
        StringGrid1.Cells[A,B]:='X';
  end;
Fangen wir damit an, dass bei dir alle Werte hardcoded sind. Das ist jetzt kein Fehler, aber wenn du Änderungen vornehmen willst, dann musst du alles in deinem Quellcode ändern. Schon was von Konstanten gehört?

Aber zurück zu dem Beispiel oben. So wie es aussieht willst du oben 26 Minen setzen. Wenn du am Ende tatsächlich 26 Minen gesetzt hast, dann eher nur zufällig, denn du prüfst nicht ob in dem Feld bereits eine Mine gesetzt ist. Theoretisch könnte es auch vorkommen, dass Random 26 Mal das gleiche Feld auswählt. Wird in der Praxis nicht vorkommen, trotzdem - ob du tatsächlich 26 Minen in 26 Felder setzt ist eher zufällig.

Sowas kann man ganz leicht mit einer Repeat Schleife prüfen.
Delphi-Quellcode:
  for k:=0 to 25 do
  begin
    repeat
        A:=random(15);
        B:=random(15);
    until IntA[A,B]<>9;

    IntA[A,B]:=9;
    StringGrid1.Cells[A,B]:='X';
  end;
Was mir auch aufgefallen ist - irgendwie kannst du dich nicht entscheiden ob du mit dem Array oder Panelen arbeitest.
Delphi-Quellcode:
    IntA[A,B]:=9;
    StringGrid1.Cells[A,B]:='X';
Kleiner Tipp - trenne beides. Arbeite nur mit dem Array, nutze das Panel nur zur Darstellung. Mal fragst du das Array ab, dann wieder mal die Captions der Panele.

Und vorerst letztens - schon mal was von Funktionen gehört? Ich weiß zwar nicht was die Zeile soll (hab sie noch nicht analysiert), aber diese Abfrage kommt 8 mal vor:
Delphi-Quellcode:
if (h+1>=0) and (h+1<=14) and (j>=0) and (j<=14) then PanelA[h+1,j].Caption:='_';
...
Wie wäre es wenn du das in eine Funktion packst? Die könnte so aussehen:
Delphi-Quellcode:
function AbfrageHJ(a, b, c, d: Integer): Boolean;
begin
  Result := (a=0) and (b<=14) and (c>=0) and (d<=14);
end;
Die Zeile in der Prozedur CannonFire würde dann so aussehen:
Delphi-Quellcode:
if AbfrageHJ(h+1, h+1, j, j) then PanelA[h+1,j].Caption:='_';
...

Bjoerk 26. Mär 2015 22:55

AW: Minesweeper
 
Zitat:

Zitat von Popov (Beitrag 1294968)
Na gut, dann ist der Algorithmus für MineSweeper nicht wirklich eine Herausforderung. [..]

Ich kenn das Spiel ja quasi erst seit gestern aber kann es sein daß wir das vergessen haben? "Wenn man auf ein leeres Feld klickt, öffnen sich alle anschliessenden leeren Felder + das erste mit einer Zahl belegten Feld" (aus einem VB Forum). Oder stimmt das nicht? :gruebel:

Also zusätzlich zur Rekursion noch den Code nach den ???

Delphi-Quellcode:
procedure TMinesweeperForm.Play(X, Y: integer); // PanelsMouseUp, Button mbLeft;
var
  I, J, K, L: integer;
begin
  // Wenn zu tun:
  // Wenn im Raster und noch nicht aufgedeckt und leeres Feld bzw. Feld mit einer pos. Zahl drin; (Mine = -1);
  if InPanelGrid(X, Y) and FPanels[X, Y].Enabled and (FPanels[X, Y].FlankingMinesCount >= 0) then
  begin
    if FPanels[X, Y].FlankingMinesCount > 0 then // Wenn Zahl > Null;
      FPanels[X, Y].Caption := IntToStr(FPanels[X, Y].FlankingMinesCount)
    else
      FPanels[X, Y].Caption := ''; // Null;
    FPanels[X, Y].Color := clWindow; // farblich kennzeichnen und
    FPanels[X, Y].Enabled := false; // -> aufdecken;
    for I := -1 to 1 do
      for J := -1 to 1 do
        if ((I <> 0) or (J <> 0)) // Alle außer 0 / 0;
          and InPanelGrid(X + I, Y + J) // Wenn im Raster;
          and FPanels[X + I, Y + J].Enabled // Wenn noch nicht aufgedeckt;
          and (FPanels[X + I, Y + J].FlankingMinesCount = 0) // Wenn leer
          and (FPanels[X + I, Y + J].Caption <> cFlagSign) then // und keine Fahne;
        begin
          Play(X + I, Y + J); // Rekursion;
          // Angrenzende Felder des leeren Feldes die eine Zahl haben ebenfalls aufdecken ???
          for K := -1 to 1 do
            for L := -1 to 1 do
              if ((K <> 0) or (L <> 0)) // Alle außer 0 / 0;
                and InPanelGrid(X + K, Y + L) // Wenn im Raster;
                and (FPanels[X + K, Y + L].FlankingMinesCount > 0) // Wenn Zahl > 0;
                and (FPanels[X + K, Y + L].Caption <> cFlagSign) then // und keine Fahne;
              begin
                FPanels[X + K, Y + L].Caption := IntToStr(FPanels[X + K, Y + L].FlankingMinesCount);
                FPanels[X + K, Y + L].Color := clWindow; // farblich kennzeichnen und
                FPanels[X + K, Y + L].Enabled := false; // -> aufdecken;
              end;
        end;
  end;
end;

Sir Rufo 26. Mär 2015 23:06

AW: Minesweeper
 
Zitat:

Zitat von Bjoerk (Beitrag 1294996)
Zitat:

Zitat von Popov (Beitrag 1294968)
Na gut, dann ist der Algorithmus für MineSweeper nicht wirklich eine Herausforderung. [..]

Ich kenn das Spiel ja quasi erst seit gestern aber kann es sein daß wir das vergessen haben? "Wenn man auf ein leeres Feld klickt, öffnen sich alle anschliessenden leeren Felder + das erste mit einer Zahl belegten Feld" (aus einem VB Forum). Oder stimmt das nicht? :gruebel:

S. Beitrag #89
Zitat:

Wenn ein Feld aufgedeckt wird, dass keine Mine im Nachbarfeld hat, dann werden auch alle Nachbarfelder aufgedeckt.

Bjoerk 26. Mär 2015 23:43

AW: Minesweeper
 
"Angrenzende Felder des leeren Feldes die eine Zahl haben ebenfalls aufdecken." Hört sich irgendwie anders an oder blick ich's jetzt auch nicht mehr?

Sir Rufo 26. Mär 2015 23:53

AW: Minesweeper
 
Zitat:

Zitat von Bjoerk (Beitrag 1295001)
"Angrenzende Felder des leeren Feldes die eine Zahl haben ebenfalls aufdecken." Hört sich irgendwie anders an oder blick ich's jetzt auch nicht mehr?

Ja hört sich anders an, ist aber auch falsch, bzw. nicht komplett.

Es ist wurst-schnuppe-pieps-egal, ob die angrenzenden Felder eine Zahl haben oder nicht, die werden aufgedeckt und für jedes dieser Felder die gleiche Regel wieder angewendet.

Bjoerk 27. Mär 2015 00:25

AW: Minesweeper
 
Ok. Thanx. Deine DeckMichAuf ist klasse. Damit sieht's in meinem Code auch gleich wesentlich entspannter aus. Stimmt das mit der Fahne?
Delphi-Quellcode:
procedure TMinesweeperForm.Play(X, Y: integer); // PanelsMouseUp, Button mbLeft;
var
  I, J: integer;
begin
  if InPanelGrid(X, Y) // Wenn im Raster;
    and FPanels[X, Y].Enabled // und noch nicht aufgedeckt;
    and (FPanels[X, Y].FlankingMinesCount >= 0) // und keine Mine; (Mine = -1)
    and (FPanels[X, Y].Caption <> cFlagSign) then // und keine Fahne;
  begin
    if FPanels[X, Y].FlankingMinesCount > 0 then // Wenn Zahl > Null;
      FPanels[X, Y].Caption := IntToStr(FPanels[X, Y].FlankingMinesCount)
    else
      FPanels[X, Y].Caption := ''; // Null;
    FPanels[X, Y].Color := clWindow; // farblich kennzeichnen und
    FPanels[X, Y].Enabled := false; // -> aufdecken;
    if GetFlankingMinesCount(X, Y) = 0 then // Wenn keine NachbarMine;
      for I := -1 to 1 do
        for J := -1 to 1 do
          if ((I <> 0) or (J <> 0)) then // Alle außer X / Y;
            Play(X + I, Y + J);
  end;
end;

Popov 27. Mär 2015 04:27

AW: Minesweeper
 
Zitat:

Zitat von Bjoerk (Beitrag 1295001)
"Angrenzende Felder des leeren Feldes die eine Zahl haben ebenfalls aufdecken." Hört sich irgendwie anders an oder blick ich's jetzt auch nicht mehr?

Die Regel ist einfach: ist das geklickte Feld leer, werden alle angrenzenden Felder geöffnet. Ist das geklickte Feld eine Zahl, wird nur das geklickte Feld geöffnet. In die Rekursion kommen alle aufgedeckten Felder, bis auf - das geklickte Feld und alle Felder die bereits offen waren. Sonderregel: das geklickte Feld ist eine Mine. In dem Fall werden alle Minen aufgedeckt und das Spiel ist zu ende.

BadenPower 27. Mär 2015 08:42

AW: Minesweeper
 
Zitat:

Zitat von Sir Rufo (Beitrag 1295002)
Zitat:

Zitat von Bjoerk (Beitrag 1295001)
"Angrenzende Felder des leeren Feldes die eine Zahl haben ebenfalls aufdecken." Hört sich irgendwie anders an oder blick ich's jetzt auch nicht mehr?

Ja hört sich anders an, ist aber auch falsch, bzw. nicht komplett.

Es ist wurst-schnuppe-pieps-egal, ob die angrenzenden Felder eine Zahl haben oder nicht, die werden aufgedeckt und für jedes dieser Felder die gleiche Regel wieder angewendet.

Ist das angrenzende Feld zu einem Leerfeld eine Zahl, dann wird das Zahlfeld aufgedeckt, aber die angrenzenden Felder des Zahlfeldes NICHT mehr überprüft.

Siehe QuellCode in #75.


Zitat:

Zitat von Bjoerk (Beitrag 1295004)
Stimmt das mit der Fahne?

Ist eine "Fahne" gesetzt, dann wird diese nicht automatisch aufgedeckt, auch nicht wenn sich darunter eine Zahl oder Leerfeld verbirgt. Ein gesetztes Fragezeichen hingegen wird automatisch behandelt, also wie wenn das Feld nicht markiert wäre.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:51 Uhr.
Seite 12 von 14   « Erste     2101112 1314      

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