Delphi-PRAXiS
Seite 7 von 14   « Erste     567 89     Letzte »    

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)

saii 25. Mär 2015 18:26

AW: Minesweeper
 
Wie Popov schon gesagt hat, bin ich Anfänger und folglich sagen mir die meisten Methoden und Befehle, die ihr hier auflistet garnichts.
Im Moment bin ich auch nicht bedacht, das Programm so perfekt wie möglich zu machen, sondern bis Freitag das ganze zum Laufen zu bringen.

Vielleicht perfektionier ich das danach.
Aber jetzt fehlt mir erstmal noch, dass das Anklicken eines Panels ohne benachbarte Minen, alle benachbarten Panels aufdeckt.
Dazu reicht mir auch, wenn alle Panels ohne benachbarte Minen aufgedeckt werden, nicht niur die benachbarten Panels (Stichwort Floodfill. Mal sehen ob ich das noch mache)

Und dann fehlt nur noch die Nachricht "Du hast gewonnen", für die ich mir auch noch etwas ausdenken muss.

Womit ich Hilfe brauche:
Zunächst funktioniert das Aufdecken ALLER Panels, die den Wert m=0 (=keine benachbarten Minen) haben nicht.
Könnte da jemand bitte mal reingucken?

Relevanter Teil: (gesamtes Programm auf Seite 4)
Delphi-Quellcode:
procedure TForm1.CannonFire(var A,B,m:integer; Sender: TObject);
var h,j:integer;
begin
        Panel:=TPanel(Sender);
        A:=StrToInt(Copy(Panel.Name, 3,2));
        B:=StrToInt(Copy(Panel.Name, 6,2));

        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].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;

DeddyH 25. Mär 2015 18:41

AW: Minesweeper
 
Wenn Deine beiden Schleifen von 0 bis 14 laufen, dann nenne mir doch mal einen Fall, in dem
Delphi-Quellcode:
h+1>=0 
j>=0
j<=14
nicht zutreffen.

saii 25. Mär 2015 18:44

AW: Minesweeper
 
:? Stimmt allerdings. Ich wollte halt sichergehen. Aber du hast natürlich Recht :)

*Edit:
Aber wenn h=14 dann wird h+1>14
-> Dann brauch ich das, oder?

BUG 25. Mär 2015 18:59

AW: Minesweeper
 
Zitat:

Zitat von saii (Beitrag 1294833)
Ich wollte halt sichergehen.

Das ist im Allgemeinen keine schlechte Idee.
Für solche Aussagen (sollte immer wahr sein, wenn das Programm korrekt ist) bieten sich Assertions an.
Aber bitte nur einmal in der Schleife :mrgreen:

Popov 25. Mär 2015 19:48

AW: Minesweeper
 
Zitat:

Zitat von saii (Beitrag 1294829)
WDazu reicht mir auch, wenn alle Panels ohne benachbarte Minen aufgedeckt werden, nicht niur die benachbarten Panels (Stichwort Floodfill. Mal sehen ob ich das noch mache)

Die Floodfill Methode ist geeignet Flächen zu füllen, für das Aufdecken einer Fläche wie es in MineSweeper gemacht wird, ist es der falsch Algorithmus. Oder man nimmt es nicht so genau und macht es zu 95%.

Man kann es vielleicht als Grundlage nehmen, mehr aber auch nicht.

saii 25. Mär 2015 19:54

AW: Minesweeper
 
Alles klar.
Und weiß jemand wie ich bei meinem Problem weiterkomme?

Bjoerk 25. Mär 2015 21:21

AW: Minesweeper
 
Muß man die IntA[h + 1, j + 1] ect. evtl. auf Null prüfen (keine Ahnung?) bevor Caption auf '_' gesetzt wird?

BadenPower 25. Mär 2015 21:36

AW: Minesweeper
 
Zitat:

Zitat von Popov (Beitrag 1294840)
Die Floodfill Methode ist geeignet Flächen zu füllen, für das Aufdecken einer Fläche wie es in MineSweeper gemacht wird, ist es der falsch Algorithmus.

Der FloodFill-Algorithmus in der 4-Neighbour-Variante ist doch genau der Ansatz den er braucht.

Wenn in ein Feld geklickt wird, dass keine Zahl und keine Bombe enthält, dann alles Aufdecken, was leer ist und was angrenzend eine Zahl hat.

Also, wenn leer, dann aufdecken und rekursiv oben unten links und rechts weiter prüfen. Wenn eine Zahl, dann nur aufdecken und diese Stelle nicht mehr weiter untersuchen.

Popov 25. Mär 2015 21:43

AW: Minesweeper
 
Mein Hinweis auf falschen Algorithmus in Post #65 bezog sich auf Floofill. Dein Code in Post #61 ist aber... sagen wir es mal psychologisch nett: noch weniger richtig.

Du kannst die Matrix nicht mit For-Schleifen durchgehen. Damit bekommst du irgendwas hin, vielleicht sogar freie Flächen inkl. Zahlenwerte um die Minen, aber eben alle Flächen in der Matrix. Das ist aber nicht unbedingt das wie MineSweeper funktioniert. Du musst nur die Fläche um den Klick herum frei machen.

Das bedeutet, dass du von deiner geklickten Zelle heraus arbeiten musst. Das bekommt man nicht ohne Hilfe eines Stapelspeichers (Stack) hin. Das ist nicht leicht, aber auch nicht schwer.

Ich versuche das ganz Simpel zu erklären, also nicht optimiert. Nehmen wir an du hast ein Feld von 10x10 Feldern. Feld x/y 5/6 ist frei und alle Felder um das Feld sind auch frei. Du klickst in das Feld 5/6 rein. Dein Problem ist nun, dass du mitten drin bist und nun die freie Fläche aufdecken mußt. Wie kannst du nun jedes Freie benachbarte Feld ansprechen?

Gehen wir von dem Feld 5/6 aus. Das ist ein Feld, das kannst du bei der Gelegenheit überprüfen und aufdecken. Nun hast du 8 benachbarte Felder um das Feld 5/6 (4/5, 5/5, 6/5, 4/6, 6/6, 4/7, 5/7, 6/7). Die Felder legst du auf Stapel. Mit eine While-Schleife prüfst du den Count des Stapels. Ist er größer Null, sind Koordinaten drin. Also nimmst du den obersten Wert vom Stapel, z. B. 6/7 und überprüfst das Feld und dann alle benachbarte Felder aufnehmen (bereits aufgedeckte Felder wie z. B. 5/6 nicht auf Stapel legen, denn das ist bereits abgearbeitet). Im Grunde war es das schon. Du legst neue Koordinate auf Stack und arbeitest den obersten immer ab. Auf diese Weise wird jede Feld abgearbeitet.

Hier eine kleine Demo (ohne Code) wie so ein Stack funktioniert: http://www.delphipraxis.net/1246627-post16.html. Die roten Punkte sind die Koordinate auf Stack.

Popov 25. Mär 2015 21:58

AW: Minesweeper
 
Zitat:

Zitat von BadenPower (Beitrag 1294846)
Zitat:

Zitat von Popov (Beitrag 1294840)
Die Floodfill Methode ist geeignet Flächen zu füllen, für das Aufdecken einer Fläche wie es in MineSweeper gemacht wird, ist es der falsch Algorithmus.

Der FloodFill-Algorithmus in der 4-Neighbour-Variante ist doch genau der Ansatz den er braucht.

Wenn in ein Feld geklickt wird, dass keine Zahl und keine Bombe enthält, dann alles Aufdecken, was leer ist und was angrenzend eine Zahl hat.

Also, wenn leer, dann aufdecken und rekursiv oben unten links und rechts weiter prüfen. Wenn eine Zahl, dann nur aufdecken und diese Stelle nicht mehr weiter untersuchen.

Code:
2|1|3
-+-+-
1|x|1
-+-+-
1|1|1
Das Problem ist (siehe Beispiel oben), dass wenn du auf X klickst, es nicht ausreicht nur die Felder zu den vier Seiten aufzudecken, sondern auch die in der Diagonalen (z. B. auch das Feld mit der 2). So funktioniert der MineSweeper von MS. Aber so einfach ist es dann doch nicht, denn so ohne weiteres wird keine 8-Neighbour-Variante draus. 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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:06 Uhr.
Seite 7 von 14   « Erste     567 89     Letzte »    

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-2025 by Thomas Breitkreuz