AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Minesweeper

Ein Thema von saii · begonnen am 21. Mär 2015 · letzter Beitrag vom 29. Mär 2015
Antwort Antwort
Seite 8 von 14   « Erste     678 910     Letzte »    
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.143 Beiträge
 
Delphi 10.3 Rio
 
#71

AW: Minesweeper

  Alt 25. Mär 2015, 23:05
Das bekommt man nicht ohne Hilfe eines Stapelspeichers (Stack) hin. Das ist nicht leicht, aber auch nicht schwer.
Ok Sagen wir es einfachen rekursives aufrufen einer Procedure

Simpler Maussucht Käse:

Delphi-Quellcode:
Procedure FindeLeer(X,Y);
begin
  if (X = 0) or (Y=0) or (X > Max) or (Y > Max) then
    Exit;
 
  if (Feld[X,Y] <> Mine) and (Feld[X,Y] <> Zahl) then
    begin
      Aufdecken(X,Y);
      FindeLeer(X+1,Y);
      FindeLeer(X-1,Y);
      FindeLeer(X,Y+1);
      FindeLeer(X,Y-1);
    end;
end;
Fertig

Mavarik
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#72

AW: Minesweeper

  Alt 25. Mär 2015, 23:30
Ob man es Stapel oder rekursiven Prozeduraufruf (was im Hintergrund das Gleiche ist), leere Felder aufdecken nur ein kleiner Teil des Ganzen. Aber schon mal der Anfang.

Geändert von Popov (25. Mär 2015 um 23:32 Uhr)
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#73

AW: Minesweeper

  Alt 26. Mär 2015, 03:37
Simpler Maussucht Käse:
Weil das ja so simple ist würde ich ggf. vorschlagen, daß du das kurz in der Play ergänzt.

Delphi-Quellcode:
unit MinesweeperUnit;

interface

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

const
  cGridCount = 9;
  cMinesCount = 10;
  cFlagSign = '?';
  cMineSign = 'X';

type
  TMinesweeperPanel = class(TPanel)
  private
    function GetMine: boolean;
  public
    X, Y: integer;
    FlankingMinesCount: integer;
    property Mine: boolean read GetMine;
  end;

  TMinesweeperForm = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure PanelsMouseUp(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  private
    FPanels: array[0..cGridCount - 1, 0..cGridCount - 1] of TMinesweeperPanel;
    function InPanelGrid(X, Y: integer): boolean;
    function GetFlankingMinesCount(X, Y: integer): integer;
    procedure NewGame;
    procedure ShowMines;
    procedure CreatePanels;
    procedure Play(X, Y: integer);
  end;

var
  MinesweeperForm: TMinesweeperForm;

implementation

{$R *.dfm}

{ TMinesweeperPanel }

function TMinesweeperPanel.GetMine: boolean;
begin
  Result := FlankingMinesCount < 0; // *** -1 als Kennzeichnung für Mine ***
end;

{ TMinesweeperForm }

procedure TMinesweeperForm.CreatePanels;
var
  I, X, Y: integer;
begin
  I := 0;
  for X := 0 to cGridCount - 1 do
    for Y := 0 to cGridCount - 1 do
    begin
      Inc(I);
      FPanels[X, Y] := TMinesweeperPanel.Create(Self);
      FPanels[X, Y].Parent := Self;
      FPanels[X, Y].Name := 'Panel' + IntToStr(I);
      FPanels[X, Y].Width := 30;
      FPanels[X, Y].Height := 30;
      FPanels[X, Y].Caption := '';
      FPanels[X, Y].Left := 20 + (X * 30);
      FPanels[X, Y].Top := 20 + (Y * 30);
      FPanels[X, Y].BorderStyle := bsSingle;
      FPanels[X, Y].OnMouseUp := PanelsMouseUp;
      FPanels[X, Y].X := X;
      FPanels[X, Y].Y := Y;
    end;
end;

function TMinesweeperForm.InPanelGrid(X, Y: integer): boolean;
begin
  Result := (X >= 0) and (X <= cGridCount - 1) and (Y >= 0) and (Y <= cGridCount - 1);
end;

function TMinesweeperForm.GetFlankingMinesCount(X, Y: integer): integer;
begin
  Result := 0;
  if InPanelGrid(X + 1, Y) and FPanels[X + 1, Y].Mine then
    Inc(Result);
  if InPanelGrid(X + 1, Y + 1) and FPanels[X + 1, Y + 1].Mine then
    Inc(Result);
  if InPanelGrid(X, Y + 1) and FPanels[X, Y + 1].Mine then
    Inc(Result);
  if InPanelGrid(X - 1, Y + 1) and FPanels[X - 1, Y + 1].Mine then
    Inc(Result);
  if InPanelGrid(X - 1, Y) and FPanels[X - 1, Y].Mine then
    Inc(Result);
  if InPanelGrid(X - 1, Y - 1) and FPanels[X - 1, Y - 1].Mine then
    Inc(Result);
  if InPanelGrid(X, Y - 1) and FPanels[X, Y - 1].Mine then
    Inc(Result);
  if InPanelGrid(X + 1, Y - 1) and FPanels[X + 1, Y - 1].Mine then
    Inc(Result);
end;

procedure TMinesweeperForm.NewGame;
var
  I, X, Y: integer;
begin
  ClientWidth := cGridCount * 30 + 40;
  ClientHeight := ClientWidth;
  for X := 0 to cGridCount - 1 do
    for Y := 0 to cGridCount - 1 do
    begin
      FPanels[X, Y].Caption := '';
      FPanels[X, Y].Color := clBtnFace;
      FPanels[X, Y].Enabled := true;
      FPanels[X, Y].FlankingMinesCount := 0;
    end;
  for I := 1 to cMinesCount do
  begin
    X := Random(cGridCount);
    Y := Random(cGridCount);
    // FPanels[X, Y].Caption := cMineSign;
    FPanels[X, Y].FlankingMinesCount := -1;
  end;
  for X := 0 to cGridCount - 1 do
    for Y := 0 to cGridCount - 1 do
      if not FPanels[X, Y].Mine then
        FPanels[X, Y].FlankingMinesCount := GetFlankingMinesCount(X, Y);
end;

procedure TMinesweeperForm.FormCreate(Sender: TObject);
begin
  Randomize;
  CreatePanels;
  NewGame;
end;

procedure TMinesweeperForm.Play(X, Y: integer);
var
  I, J: integer;
begin
  if InPanelGrid(X, Y) and FPanels[X, Y].Enabled then
  begin
    if FPanels[X, Y].FlankingMinesCount > 0 then
      FPanels[X, Y].Caption := IntToStr(FPanels[X, Y].FlankingMinesCount)
    else
      FPanels[X, Y].Caption := '';
    FPanels[X, Y].Color := clWindow;
    FPanels[X, Y].Enabled := false;
(*
Mit der linken Maustaste freigelegte Felder, die keine Mine enthalten, enthüllen die Anzahl der Minen,
die sich in den benachbarten acht Feldern befinden.
Ein aufgedecktes Feld, das an allen Seiten von Minen umgeben ist, wird eine 8 zeigen.
Durch die Zahlen der aufgedeckten Felder ist es meist möglich, den Aufenthaltsort der Minen herauszufinden.

Wenn man einen Doppelklick mit der linken Maustaste auf ein aufgedecktes Feld macht,
in dessen Nachbarschaft bereits alle Minen markiert sind oder darauf mit der linken
und der rechten Maustaste gleichzeitig klickt, werden die restlichen Felder mit einem Mal aufgedeckt.
Eine Sonderrolle spielen Felder, die keine Minen in ihrer Nachbarschaft aufweisen:
Solche zeigen zum einen nicht etwa eine 0, sondern sie werden farblich anders dargestellt.
Zum anderen werden alle noch verdeckten Felder in ihrer Nachbarschaft automatisch aufgedeckt.
Ist ein so neu aufdecktes Feld ebenfalls ein Null-Feld, so wird dieser Prozess rekursiv weitergeführt.
*)

      for I := -1 to 1 do
        for J := -1 to 1 do
          if ((I <> 0) or (J <> 0)) and InPanelGrid(X + I, Y + J) then
            if .. and .. and .. and .. and .. then Play(X + I, Y + J);
  end;
end;

procedure TMinesweeperForm.ShowMines; // GameOver;
var
  X, Y: integer;
begin
  for X := 0 to cGridCount - 1 do
    for Y := 0 to cGridCount - 1 do
      if FPanels[X, Y].Mine then
        FPanels[X, Y].Caption := cMineSign;
  Application.ProcessMessages;
end;

procedure TMinesweeperForm.PanelsMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Panel: TMinesweeperPanel;
begin
  Panel := TMinesweeperPanel(Sender);
  if Panel.Mine then
  begin
    Panel.Color := clHighlight;
    ShowMines;
    Showmessage('Du hast leider verloren.');
    NewGame;
  end
  else
    if Button = mbLeft then
      Play(Panel.X, Panel.Y)
    else
      if Button = mbRight then
      begin
        if Panel.Caption = cFlagSign then
          Panel.Caption := ''
        else
          Panel.Caption := cFlagSign;
      end;
end;

end.
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#74

AW: Minesweeper

  Alt 26. Mär 2015, 09:28
Denn nehmen wir das Beispiel oben und machen das Feld mit der 3 leer
Code:
2|1|_
-+-+-
1|x|1
-+-+-
1|1|1
darf das nicht aufgedeckt werden.
Das 3er Feld wird auch aufgedeckt, da es auf keinen Fall eine Bombe sein kann. Und auch die dann weiter angrenzenden Felder werden wiederum geprüft.

Die Diagonale ist keine Sperre.

Und so macht es der MS-Minesweeper auch.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#75

AW: Minesweeper

  Alt 26. Mär 2015, 10:15
Weil das ja so simple ist würde ich ggf. vorschlagen, daß du das kurz in der Play ergänzt.
So könnte dann die Play aussehen:

Delphi-Quellcode:
procedure TMinesweeperForm.Play(X, Y: Integer);
begin
  if ((InPanelGrid(X, Y)) and (FPanels[X, Y].Enabled)) then
   begin
    FPanels[X, Y].Color := clWindow;
    FPanels[X, Y].Enabled := false;
    if (FPanels[X, Y].FlankingMinesCount > 0) then
     begin
      FPanels[X, Y].Caption := IntToStr(FPanels[X, Y].FlankingMinesCount)
     end
    else
     begin
      FPanels[X, Y].Caption := '_';
      Play(X, Y + 1); //unten
      Play(X, Y - 1); //oben
      Play(X + 1, Y); //rechts
      Play(X - 1, Y); //links
      Play(X + 1, Y + 1); //unten-rechts
      Play(X + 1, Y - 1); //oben-rechts
      Play(X - 1, Y + 1); //unten-links
      Play(X - 1, Y - 1); //oben-links
     end;
  end;
end;

EDIT:

Du musst aber noch "TMinesweeperForm.PanelsMouseUp" ändern, da dort ein Fehler ist.

Du solltest zuerst abfragen, ob die rechte Maustaste betätigt wurde und in der ELSE überprüfen ob eine Mine unter dem Feld liegt und nicht umgekehrt, denn sonst hast Du immer verloren, auch wenn Du nur ein Marker setzen möchtest.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.

Geändert von BadenPower (26. Mär 2015 um 10:24 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.143 Beiträge
 
Delphi 10.3 Rio
 
#76

AW: Minesweeper

  Alt 26. Mär 2015, 11:40
[QUOTE=BadenPower;1294864]
Die Diagonale ist keine Sperre.

Und so macht es der MS-Minesweeper auch.
Ahh ok wusste ich nicht... Konnte das Ding noch NIE leiden...
Aber Du hast es ja schon richtig ergänzt...

Mavarik
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#77

AW: Minesweeper

  Alt 26. Mär 2015, 11:42
Das 3er Feld wird auch aufgedeckt, da es auf keinen Fall eine Bombe sein kann. Und auch die dann weiter angrenzenden Felder werden wiederum geprüft.
Wie ich schon sagte, die Drei darf nicht aufgedeckt werden wenn das Feld leer ist. Das sind die Regeln.
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#78

AW: Minesweeper

  Alt 26. Mär 2015, 12:21
Das 3er Feld wird auch aufgedeckt, da es auf keinen Fall eine Bombe sein kann. Und auch die dann weiter angrenzenden Felder werden wiederum geprüft.
Wie ich schon sagte, die Drei darf nicht aufgedeckt werden wenn das Feld leer ist. Das sind die Regeln.
DOCH, auch dieses Feld wird aufgedeckt.

So ist es beim MS-MineSweeper auf alle Fälle. Habe diese Konstellation mehrfach überprüft und immer wenn das Diagonalfeld auch leer war hat die MS-Version auch alles weitere aufgedeckt, was an das Diagonalfeld angrenzte.

NOCHMALS:
Die Diagonale ist KEINE Sperre im MS-MineSweeper.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.143 Beiträge
 
Delphi 10.3 Rio
 
#79

AW: Minesweeper

  Alt 26. Mär 2015, 12:27
NOCHMALS:
Die Diagonale ist KEINE Sperre im MS-MineSweeper.
Sicher? Hab das noch nicht gesehen...
Online zu testen wer Minesweeper nicht hat.

Oder meinst Du das? (Anhang)
Miniaturansicht angehängter Grafiken
mine.png  

Geändert von Mavarik (26. Mär 2015 um 12:30 Uhr)
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#80

AW: Minesweeper

  Alt 26. Mär 2015, 12:28
So könnte dann die Play aussehen: [..]
Du musst aber noch "TMinesweeperForm.PanelsMouseUp" ändern, da dort ein Fehler ist. [..]
Stimmt. Badenser vor. Ich kannte das Spiel nur vom Namen her und muß sagen ich finds ganz nett (Jedenfalls besser als das langweilige Fußballspiel gestern abend).
Delphi-Quellcode:
procedure TMinesweeperForm.Play(X, Y: integer); // PanelsMouseUp, Button mbLeft;
var
  I, J: integer;
begin
  if FPanels[X, Y].FlankingMinesCount > 0 then
    FPanels[X, Y].Caption := IntToStr(FPanels[X, Y].FlankingMinesCount)
  else
    FPanels[X, Y].Caption := '';
  FPanels[X, Y].Color := clWindow;
  FPanels[X, Y].Enabled := false;
  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)
          and FPanels[X + I, Y + J].Enabled
            and (FPanels[X + I, Y + J].FlankingMinesCount = 0)
              and (FPanels[X + I, Y + J].Caption <> cFlagSign) then Play(X + I, Y + J);
end;

procedure TMinesweeperForm.PanelsMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Panel: TMinesweeperPanel;
begin
  Panel := TMinesweeperPanel(Sender);
  if Button = mbLeft then
  begin
    if Panel.Mine then
    begin
      Panel.Color := clHighlight;
      ShowMines;
      Showmessage('Du hast leider verloren.');
      NewGame;
    end
    else
      Play(Panel.X, Panel.Y)
  end
  else
    if Button = mbRight then
    begin
      if Panel.Caption = cFlagSign then
        Panel.Caption := ''
      else
        Panel.Caption := cFlagSign;
    end;
end;
Damit "er" bei Themes auch die Color annimmt muß man in der CreatePanels noch ergänzen:
FPanels[X, Y].ParentBackground := false; Bleibt abzuwarten ob TE den Code versteht. Ich denke aber mal ja, hat ja schon viel Vorarbeit geleistet und ich hab ja versucht mich so eng an seinen Code anzulehnen wie möglich.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 8 von 14   « Erste     678 910     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:01 Uhr.
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