Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - 8-Damen-Problem
klabri - Mo 05.01.09 19:34
Titel: 8-Damen-Problem
Hallo, ich weiss....
warum funktioniert das so nicht ?
Was funktioniert nicht... das Zurücknehmen der Dame
in Zeile x-1 ,wenn 'Sackgasse=True'....
Delphi-Quelltext
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: 50: 51:
| procedure Suche(x,y:integer); begin if (Sackgasse=True) and (Feld[x][y]=True)then begin dauf[x+y]:=false; dab[y-x]:=false; Feld[x][y]:=False; end; erfolg:=false; if (erfolg=false) and (y<8) then begin y:=y+1; d[x]:=y;
erfolg:=True ; if (dauf[x+y]=True)or (dab[y-x]=True) then
erfolg:=false;
if (erfolg=false) and(y<8)Then begin Suche (x,y); end; if (erfolg=False) and(y=8) AND (x>1) then begin Sackgasse:=True; Damen(x-1,d[x-1]); end; end; ; If erfolg=true then begin dauf[x+y]:=True; dab[y-x]:=True;
Feld[x][y]:=True; ListBox1.Items.Add('Dame:'+IntToStr(x)+'**'+IntToStr(d[x])); y:=0; end; if x<8 then Suche (x+1,y); end; |
Moderiert von
Narses: Topic aus Sonstiges (Delphi) verschoben am Mo 05.01.2009 um 20:09
jaenicke - Mo 05.01.09 20:06
Durch die globalen Variablen und die fehlenden Einrückungen ist der Code so gut wie unlesbar. :roll:
Was mir auffällt:
Delphi-Quelltext
1: 2: 3:
| if (Sackgasse=True) and (Feld[x][y]=True)then begin |
Das ist falsch. Es muss heißen:
Delphi-Quelltext
1: 2:
| if Sackgasse and Feld[x][y] then begin |
Erklärung:
http://www.delphi-treff.de/tutorials/objectpascal/programmierung-mit-boolean-werten/page/4/
Und dann noch etwas, was vielleicht der Fehler ist:
Du setzt Sackgasse auf True, aber nie wieder auf False.
Und was ist hier Damen? Mit Suche rufst du die eigene Prozedur rekursiv selbst auf. Aber wo ist Damen definiert?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure Suche(x,y:integer); ... if (erfolg=false) and(y<8)Then begin Suche (x,y); end; if (erfolg=False) and(y=8) AND (x>1) then begin Sackgasse:=True; Damen(x-1,d[x-1]); |
Jakob_Ullmann - Mo 05.01.09 21:21
Also ich hab irgendwie gar nichts verstanden. Bitte formuliere deine Frage noch mal. :roll:
Was weißt du? Was soll das Programm machen? Was ist Zeile x-1?
klabri - Di 06.01.09 00:54
Hallo, das war sehr unverständlich gefragt;
Danke für's Ansehen,da steckten noch eine Menge Fehler
drin...
also,dass Programm findet Lösungen für das
8-Dame-Problem.
Inzwischen hab ich alles noch mal neu gemacht und
,welche Freude,scheinbar funktioniert das Backtracking,
darum ging's mir eigentlich.
Also so funktioniert's; zumindest lässt sich das Back-
tracking gut verfolgen;
Die Ausgabe erfolgt in einer Listbox;
Delphi-Quelltext
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: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93:
| unit Unitrec59;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; ListBox1: TListBox; procedure Button1Click(Sender: TObject); private public procedure Suche(x:integer); end;
var Form1: TForm1; erfolg:boolean; d:array[1..8]of integer; dauf:array[2..16]of boolean; dab:array[-7..7]of boolean; vertikal:array[1..8]of boolean; y:integer; sackgasse:boolean; implementation
{$R *.dfm}
procedure TForm1.Suche(x:integer);
begin if sackgasse=True then begin dauf[x+d[x]]:=false; dab[d[x]-x]:=false; vertikal[d[x]]:=false; d[x]:=0; end; erfolg:=false; if (erfolg=false)and (y<8) then begin y:=y+1; erfolg:=True; if dauf[x+y]=true then Erfolg:=false; if dab[y-x]=true then Erfolg:=false; if vertikal[y]=True then Erfolg:=false; if erfolg=false then begin Suche(x); end; end;
if erfolg=True then d[x]:=y; dauf[x+y]:=True; dab[y-x] :=true; vertikal[y]:=True;
ListBox1.Items.Add(IntToStr(x)+'*'+IntToStr(d[x]));y:=0; end; if (x<8) and (erfolg=True) Then begin
Suche(x+1); end;
if (y=8)and (erfolg=false) then begin Sackgasse:=True; y:=d[x-1]; Suche(x-1); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin Suche(1); end;
end. |
F34r0fTh3D4rk - Di 06.01.09 10:29
jaenickes Beitrag hast du aber nicht zur Kenntnis genommen, oder? Auch wenn es in deinem Fall höchstwahrscheinlich nicht zu Problemen führt, sind Konstrukte wie
(erfolg=True) auch meiner Ansicht nach unsinnig.
Delphi-Quelltext
1:
| if (erfolg = true) then |
wird zu:
Delphi-Quelltext
1:
| if (erfolg = false) then |
wird zu
Man kann nämlich nicht immer davon ausgehen, dass
trueauch wirklich
trueist. Klingt komisch, ist aber so. Das liegt daran, dass man keine einzelnen Bits speichern kann und ein
booleandeshalb immer als ein Byte abgelegt wird. Wobei man sich selbst da nicht sicher sein kann. Es gibt also 256 Zustände (statt 2) die rein theoretisch von boolean angenommen werden können. Ob das jetzt immer die Werte 1 (
true) oder 0 (
false) sind, kann man nicht mit Bestimmtheit sagen.
mfg
WInfo - Di 06.01.09 10:48
klabri hat folgendes geschrieben : |
Hallo, das war sehr unverständlich gefragt; |
Moin Moin klabri,
wenn dein Codebeispiel verständlich formatiert und dokumentiert wäre, werden sich sicher auch andere den Code mal ansehen. Aktuell finde ich das nur für Grauenhaft und ist mir keines Blickes wert.
klabri - Di 06.01.09 12:34
Hallo,
erstmal danke an alle,die hier geantwortet haben.
Ich hab jänickes beitrag gelesen und war auch auf dem
Delphi-Link;
Ich schreib das noch mal richtig und erklär das auch aus-
führlich und stell's hier dann noch mal als PDF-Datei rein.
klabri - Di 06.01.09 13:37
Hallo
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure Suche(x:integer); begin .... ..... erfolg:=false; if (erfolg=false)and (y<8) then begin y:=y+1;
erfolg:=True; |
ich bemüh mich mal, dieses erfolg:=false am Anfang
der Procedur Suche(x) zu erklären:
-Die Procedure wird mit Suche(1) aufgerufen
-auf einem Schachbrett wäre wir jetzt in der ersten Zeile
-y:=y+1, die erste Spalte in der Zeile oder das erste Feld
-erfolg:=True :wir haben ein nicht besetztes Feld gefunden
-in der Procedure geht es mit erfolg:=True weiter
-die Diagonalen und Vertikal werden als besetzt
-dauf[x+y]:=True etc. markiert
-die Procedure wird wieder aufgerufen :Suche(2)
-wenn dieses erfolg=false fehlt
-wird alles ,was in "If erfolg=false...."steht
übersprungen
-das Programm prüft dann nicht,ob die Dame in der zweiten
Zeile bedroht wird und sucht auch in dieser Zeile keine
neue Lösung
Ich weiss,es ist nicht verständlich so,aber dieses
erfolg:=false am Anfang der Procedure hat so seinen Sinn.
Dunkel - Di 06.01.09 18:10
klabri hat folgendes geschrieben : |
Ich weiss,es ist nicht verständlich so,aber dieses
erfolg:=false am Anfang der Procedure hat so seinen Sinn. |
Darum geht es ja auch garnicht.
Es geht um Deine if-Konstrukte, in denen Du explizit auf True oder False prüfst. Dass das zu Problemen führen
kann (nicht muss!), steht recht gut erklärt in dem Link, welchen Du Dir offensichtlich nicht genau genug durchgelesen hast.
klabri - Di 06.01.09 20:39
Hallo,
stimmt,ich hab mal so schnell drüber gelesen; aber es
leuchtet mir ein und ich werd's mal ändern;
Danke noch einmal für den Hinweis
--
Moderiert von
Kha: Beiträge zusammengefügt - ab hier 10.03.10 --
Hallo,
ich beschäftige mich gerade mal wieder mit diesem 8-Damen-Problem.
Mein Programm findet mit 8 Damen, mit Back-Tracking 1 Lösung,
dabei steht die erste Dame in der ersten Zeile,in der ersten Spalte.
Während der Lösungssuche läuft das Backtracking von der achten Zeile bis zur
zweiten Zeile,dann findet es eine Lösung.
Die erste Dame müsste sich dann auf das nächste Feld bewegen,aber wie stelle ich das an ?
--
Moderiert von
Kha: Beiträge zusammengefügt --
Hallo,
das Programm läuft nach folgendem Schema ab:
-Suche Position ,in der Dame(x) nicht geschlagen wird
-wenn Position gefunden,dann setze Dame(x)
-wenn in Zeile x keine Lösung ,
,mache in Zeile(x-1)weiter
-Suche Position....setze Dame.....
usw.
es gibt eine Funktion Setze_Dame(x:integer):integer;
,die,wenn eine Position gefunden ist mit Setze_Dame(x+1) wieder aufgerufen wird.
In dem Programm lässt sich das Backtracking gut verfolgen,aber
es findet eben nur eine Lösung..
Setze_Dame(x) wird so aufgerufen
if x<8 and gefunden:=True then
Setze_dame(x+1);
Kha - Do 11.03.10 01:23
Da war ich mit dem Zusammenfassen wohl etwas übereifrig, also zum Pushen gleich eine Antwort hinterher ;) .
Im Prinzip darfst du nach dem Fund einer gültigen Position nicht aufhören, sondern musst für
jede gültige Position in der Reihe die Funktion rekursiv aufrufen. Wenn dein Algorithmus die Menge aller Lösungen zurückgeben soll, bräuchtest du noch eine verschachtelte Liste wie im
Wikipedia-Beispiel [
http://de.wikipedia.org/wiki/Damenproblem#Rekursives_Backtracking], für die bloße Anzahl oder weiterhin die direkte Ausgabe in einer Listbox solltest du nicht viel ändern müssen.
klabri - Do 11.03.10 11:09
Hallo,
ich guck mir das Wikedepia mal ;
irgendwo fehlt ein rekursiver Aufruf.
Die Funktion Setze_dame(x+1) ruft sich auf bis
diese Abbruchbedingung
x<8 and gefunden =True erfüllt ist, beim Setzen der achten Dame.
dame(1): Pos 1
dame(2): Pos 5
dame(3): Pos 8
..
dame(8): Pos 4
Ende, weil Lösung gefunden...
weitergehn müsste die Suche mit dame(2),indem Pos 6,7,8 geprüft wird..
Hier fehlt mir also ein entsprechender Aufruf.
Wenn diese Positionen geprüft sind und die Lösungen gefunden sind,müsste die
1.Dame auf Pos 2 vorrücken usw.... ,dieser neue Aufruf fehlt mir aucn noch...
Aber ich bin schon mal zufrieden,dass das Backtracking so funktioniert
Ich häng die Unit mal als Datei dran,vielleicht hat jemand eine gute Idee,was
da noch fehlt..
klabri - So 14.03.10 17:58
So, inzwischen ist das Problem gelost;
nachdem das Programm eine Lösung gefunden hat, also die achte Dame in gesetzt ist
ruft es eine zweite Funktion auf, die weiter Positionen absucht
-zuerst in der Zeile, in der die letzte Dame gesetzt worden ist
-dann kommt das Backtracking in Zeile -1 ,wenn keine Lösung gefunden usw,
alle Fragen sind beantwortet,dass Rad wurde zum x-ten Mal erfunden.
Jetzt verpacke ich das ganze noch ein wenig.
Vielen Dank für das Beantworten meiner Fragen.Ich habe als verstanden,
wie "Backtracking" funktioniert.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!