Minesweeper programmieren

Für Fragen von Einsteigern und Programmieranfängern...
raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Soweit läuft jetzt alles, wir verzeweifeln ein wenig an der Rekursion zum Aufdecken mehrerer Felder, wenn man auf ein leeres Feld klickt. Any ideas?
Hier mal die erstern erbärmlichen Versuche:

Code: Alles auswählen

procedure Tform1.umkreisaufdecken;
var q,r,x,y:integer;
begin
  x:=CellPos.X;
  y:=CellPos.Y;
 
   for q:=x-1 to x+1 do
     for r:=y-1 to y+1 do
       begin
         stringgrid1.cells[q,r]:=minenfeld[q+1,r+1];
       end;
Zuletzt geändert von Lori am Di 13. Mär 2012, 16:42, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Minesweeper programmieren

Beitrag von carli »

Code: Alles auswählen

procedure TForm1.deckeauf(x, y: integer);
begin
 if ___ Test, ob aufgedeckt wird ___ then begin
  // aufdecken
  CODE CODE CODE
  deckeauf(x-1, y);
  deckeauf(x+1, y);
  deckeauf(x, y-1);
  deckeauf(x, y+1);
 end
end

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Irgendwie klappts nicht so recht, die Ausgabe will nicht.

Code: Alles auswählen

procedure Tform1.umkreisaufdecken(x, y:integer);
begin
stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
if minenfeld[x+1,y+1]<>'' then stringgrid1.cells[x,y]:=minenfeld[x+1,y+1]
                            else
                                begin
                                umkreisaufdecken(x+1,y);
                                umkreisaufdecken(x-1,y);
                                umkreisaufdecken(x,y+1);
                                umkreisaufdecken(x,y-1);
                                end;
Zuletzt geändert von Lori am Di 20. Mär 2012, 19:11, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Minesweeper programmieren

Beitrag von carli »

raetzer hat geschrieben:Irgendwie klappts nicht so recht, die Ausgabe will nicht.

Code: Alles auswählen

procedure Tform1.umkreisaufdecken(x, y:integer);
begin
stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
if minenfeld[x+1,y+1]<>'' then stringgrid1.cells[x,y]:=minenfeld[x+1,y+1]
                            else
                                begin
                                umkreisaufdecken(x+1,y);
                                umkreisaufdecken(x-1,y);
                                umkreisaufdecken(x,y+1);
                                umkreisaufdecken(x,y-1);
                                end;
Kann gar nicht funktionieren, da das Ding sich rekursiv aufrufen wird bis zur unendlichsten Stelle. Du musst den Spezialfall Spielfeldrand auch noch einbeziehen und eine Abbruchbedingung für die Rekursion haben.

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

So weit waren wir mittlerweile auch schon. Das ganze sieht nun so aus:

Code: Alles auswählen

procedure Tform1.umkreisaufdecken(x, y:integer);
begin
  stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
  if minenfeld[x+1,y+1]<>' ' then stringgrid1.cells[x,y]:=minenfeld[x+1,y+1]
                            else
                                begin
                                  if x<8 then umkreisaufdecken(x+1,y);
                                  if y<8 then umkreisaufdecken(x,y+1);
                                  {if x>0 then umkreisaufdecken(x-1,y);
                                   umkreisaufdecken(x,y-1); }
                                end;
 
end;
Wie du siehst sind die unteren beiden ausgeklammert ({ }). Nach rechts unten funktioniert das ganze nun einwandfrei. Mach ich die Klammern weg und klammere die oberen beiden ein, gehts auch nach links oben. Ganz ohne Klammern geht aber gar nichts :(. Wenn auf ein leeres Feld geklickt wird hängt das ganze kurz und bricht dann ab (irgendwas mit SIGSEV?).
Sorry für die dummen Fragen, ist sicher ganz simpel...

DAP
Beiträge: 55
Registriert: Sa 15. Jan 2011, 00:14
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Minesweeper programmieren

Beitrag von DAP »

Hallo,

mir ist aufgefallen, dass
raetzer hat geschrieben:

Code: Alles auswählen

stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
generell am Anfang aufgerufen wird und die gleiche Zuweisung bei der
if - Struktur.
raetzer hat geschrieben:

Code: Alles auswählen

if minenfeld[x+1,y+1]<>' ' then stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
Bei dem Aufruf
raetzer hat geschrieben:

Code: Alles auswählen

umkreisaufdecken(x,y-1);
fehlt die Bedingung if y > 0

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Habs mal angepasst, bringt aber nichts :(
Langsam verzfeifel ich.

Das passiert, wenn man ein "leeres" Feld anklickt.
Bild

Und wenn man dann Ok drückt. Öffnet sich das hier:
Bild

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Minesweeper programmieren

Beitrag von MAC »

so ich hab die lösung...
Ist eigentlich ziemlich einfach:
stell dir vor du hast 2 Leere Felder neben einander...
Du klickst jetzt auf eins (sagfen wir mal das linke).
Dort wird abgefragt ob es ein rechts gibt... Ja das gibt es und die Procedure ruft sich selbst mit dem rechten feld auf....
Das rechte Feld ist leer. Also werden alle Felder in der umgebung aufgerufen, darunter auch das linke....
Das linke feld ist immer noch leer. Es ruft wieder das Rechte auf...
Das ist auch leer --> das linke kommt drann
und das nimmt wieder das recht drann .
u.s.w und so fort...

Einfach mal logisch im Gehirn schritt für schritt durchgehen hilft meistens....
Wie löst mann das ???
Eine einfache lösung wäre ein Array of boolean zu nehmen. Das Array sollte zweidimensional sein (für jedes Feld ein eintrag)... und halt so gros sein wie dein stringgrid...
Bevor du die funktion Umkreisaufdecken startest (Bevor nicht selber in der FunktioN !) wird das ganze array auf true gesetzt... in der Funktion wird dann der aktuelle eintrag auf false gesetzt und es werden andere Einträge nur noch aufgerufen wenn diese true sind...


Pro Tipp: gewöhn dir direkt an die größe eines Arrays (ein stringgrid hat intern natürlich auch ein 2 dimensionales array) dynamisch anzugeben. Also das bei dir nicht steht "If x<8 then" sondern "If x<high(mienenfeld) then" bzw "if y<high(minenfeld[x])" bei der y koordinate...

Code: Alles auswählen

Signatur := nil;

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

TAUSEND DANK! Jetzt geht es :)

Code: Alles auswählen

procedure Tform1.umkreisaufdecken(x, y:integer);
begin
  if minenfeld[x+1,y+1]<>' ' then stringgrid1.cells[x,y]:=minenfeld[x+1,y+1]
                            else if rekursion[x+1,y+1]=true then
                                begin
                                  stringgrid1.cells[x,y]:=minenfeld[x+1,y+1];
                                  rekursion[x+1,y+1]:=false;
                                  if x<8 then umkreisaufdecken(x+1,y);
                                  if y<8 then umkreisaufdecken(x,y+1);
                                  if x>0 then umkreisaufdecken(x-1,y);
                                  if y>0 then umkreisaufdecken(x,y-1);
                                end;
Damkeschön :)
Zuletzt geändert von Lori am Mo 26. Mär 2012, 18:02, insgesamt 1-mal geändert.
Grund: Bitte richtigen Highlighter nehmen

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Eine kleine Frage hab ich erstmal noch.
Ich möchte noch einen Button hinzufügen zum Neustart. Gibt es eine Anweisung die das Programm komplett in den Ausgangszustand versetzt? Also so, als ob man die .exe neu aufgerufen hat?

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Minesweeper programmieren

Beitrag von MAC »

nein :)
es gehört aber zum guten Programmierstil in einer Procedure alles wieder auf den ausgangszustand zu stellen (Objekte löschen, Arrays auf die länge 0 setzten) und diese Procedure am Anfang und am Ende eines Programms auszuführen (am anfang da evt. einige variablen initialisiert werden sollten...)

Code: Alles auswählen

Signatur := nil;

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Hab das ganze mittlerweile auch so gelöst :)
Das Programm ist nun zu 99,9% fertig, jetzt muss ich nur noch den Retlichen 0,1% machen und dann den Quelltext "schön" machen.

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Minesweeper programmieren

Beitrag von carli »

raetzer hat geschrieben:Hab das ganze mittlerweile auch so gelöst :)
Das Programm ist nun zu 99,9% fertig, jetzt muss ich nur noch den Retlichen 0,1% machen und dann den Quelltext "schön" machen.
Die letzten 0,1% der Programmierarbeit nehmen bekanntlich 99,9% der Zeit ein.

raetzer
Beiträge: 13
Registriert: Mo 23. Jan 2012, 17:47

Re: Minesweeper programmieren

Beitrag von raetzer »

Hier zum Glück nicht so sehr :D

Hab das ganze mal in den Anhang gepackt, wenn ihrs euch mal anschauen möchte. Der Quelltext ist sicher nicht optimal, wenn ihr noch ein paar Vorschläge habt könnt ihr sie mir gern nennen, morgen ist Abgabe.
Hab überall Kommentare eingefügt, hauptsächlich für unseren Informatiklehrer
Dateianhänge
MINESWEEPER.zip
(6.19 MiB) 106-mal heruntergeladen

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Minesweeper programmieren

Beitrag von MAC »

Also auch wenn du es nicht mehr stark bearbeiten wirst, hier mal mein eindruck:

1. Recht Ordentlich, macht einen guten eindruck.
2. Wieso hast du Checkboxen verwendet die du unsichtbar machst ? Und keine RadioButtons ? oder RadioGroup ?
3. Der startbildschirm sieht noch "leer" aus, also design evt anpassen damit es nicht so leer aussieht...
4. Spiel an sich übersichtlich
5. Unten an der Form sind so 30 Pixel ungebraucht, da würde ich die Form verkleinern ...
6. Absolute Highlight ist diese Notizzettel mäßige Nachricht wenn man gewonnen / verloren hat. Die ist richtig gelungen.

Code: Alles auswählen

Signatur := nil;

Antworten