A* Funktioniert eher suboptimal?
Übersicht

![]() |
M0rgensternBetreff: A* Funktioniert eher suboptimal? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo Leute.
Ich habe mich jetzt mal auf gegebenem Anlass mit Wegfindung auseinander gesetzt und versucht den A*-Algorithmus umzusetzen. Ich hab ihn jedoch (auch aus gegebenem Anlass) so gebaut, dass diagonale Schritte gar nicht erst möglich sind. Man kann damit also nur waagerecht und senkrecht laufen. Das funktioniert soweit auch gut. Jetzt hab ich auch eingebaut, dass man die "Map" bearbeiten kann, also verschiedene Felder teurer zu machen etc. Das klappt soweit auch ganz gut. Aber: Manchmal kommt es vor, dass er sich an einer Stelle verennt und somit keinen Weg mehr finden kann (es ist verboten auf bereits benutzte Knoten nochmal zu nutzen). Ich hab hier mal ein Bild als Beispiel: Grün ist der Startknoten, Rot das Ziel und braun die teuren Bereiche. Die Wegfindung besteht aus folgenden Methoden: BlitzMax: [AUSKLAPPEN]
In dem Spiel, in dem der Algorithmus genutzt werden soll, werden solche Extremfälle gar nicht auftreten (können), aber trotzdem möchte ich das anständig machen. Kann mir vielleicht jemand weiterhelfen um das Programm zu verbessen? Ich wäre auch schon über Anregungen sehr froh. Wenn noch Fragen zum Code bestehen, dann fragt einfach, werde es dann erklären. Danke schonmal, Lg, M0rgenstern |
||
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
BlitzMax: [AUSKLAPPEN] OpenList.Clear() 'First Clear the List
Warum löschst du andauernd alle Einträge dieser Liste? Wenn der vorerst eingeschlagene Weg in eine Sackgasse führt, sorgt diese Zeile dafür, dass die Alternativen vergessen werden. Das merkst du auch daran, dass die "offene Liste" maximal 8 Einträge besitzt. Wenn diese Zeile entfernt wurde, kann man feststellen, dass Einträge mehrfach eingefügt werden können. Da aber beim Abgleich mit der "geschlossenen Liste" immer nur ein Element auf einmal entfernt wird, kann es dann neue Probleme geben. Nun noch eine Sache: Du hast dort eine Schleife in einer Schleife in einer Schleife, wobei im Extremfall jede der Schleifen durch einen großen Anteil aller Knoten laufen kann. ->Das macht ein Laufzeitverhalten von O(n^3). (normal bei A-Star: O(log(n)*n)) Wundere dich also nicht, wenn es bei großen Karten zu lange dauert! ![]() mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey.
Die Liste lösche ich, weil er sonst Felder, die schon in der ClosedList sind als mögliche Felder genommen hatte und dann nicht vom Fleck kam. Er ist dann ein Feld weitergelaufne und dann kam nix mehr. Ich hab den Algorithmus so verstanden, dass: - In der OpenList alle Felder sind, die als nächstes betreten werden können (in meinem Fall übrigens keine 8 sondern höchstens 4 weil Diagonal laufen ausgeschlossen ist). - In der ClosedList dann das billigste Feld aus der OpenList eingefügt wird und das nächste Feld von diesem aus gesucht wird. Mein Problem seh ich ja: Wenn ich mich einmal verannt habe, dann kommt er nicht mehr raus. Aber ich weiß im Moment nicht wie ich das anders machen sollte/könnte, damit Fehlschritte bemerkt werden. Wegen der Laufzeit: Die Repeat - Until Schleife brauch ich ja aufjeden fall. Ob ich die beiden For Eachin Schleifen umgehen kann muss ich noch sehen, aber momentan eher nicht. Damit wird sicher gestellt, dass sich ein Knoten nicht in beiden Listen befindet. Im übrigen werden die Karten wahrscheinlich nicht größer als 24*24 Felder, aber die Laufzeit sollte trotzdem nicht so hoch sein, da hast du schon Recht. Lg, M0rgenstern |
||
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Jedes Feld wird aber nur einmal in der OpenList vorkommen, wenn alles richtig läuft.
Sobald es abgearbeitet wurde, wird es dort entfernt und in die ClosedList gesteckt, damit es nicht mehr in die OpenList kommen kann. Der Fehler, den die nicht korrekte Zeile verhindert, entsteht, weil ein Objekt mehrfach in der OpenList stehen kann. (->Packe das Problem an der Wurzel und versuche nicht, die Symptome bloß zu überdecken!) Sobald diese Zeile aktiv ist, werden die noch nicht besuchten Felder, an denen das Programm "vorbei gegangen" ist, nicht mehr beachtet, bis es über einen anderen Weg wieder dort ist. Mache mal einen graphischen Debug-Durchlauf ohne diese Zeile und lasse dir alle Daten zu den Feldern anzeigen. (ähnlich, wie das A-Star-Beispiel vom BlitzMax) So etwas kann beim Debuggen von Suchalgorithmen ziemlich gut helfen. mfG mpmxyz PS: Fehlschritte werden bei A-Star gar nicht bemerkt. Es geht einfach immer wieder an der günstigsten Stelle weiter. In der Sackgasse gibt es dann irgendwann keine. Daher wird sie dann nicht mehr beachtet. |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
- Zuletzt bearbeitet von mpmxyz am So, Feb 20, 2011 21:57, insgesamt 2-mal bearbeitet
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Über die Forensuche kannst Du einen von mir implementierten A* für BMax finden, der auch recht ausführlich dokumentiert ist. Vielleicht hilft der dir ein wenig weiter. | ||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey, ich lass mir den Weg Schrittweise ausgeben.
Wenn ich die Zeile "OpenList.Clear()" weglasse, dann erhalte ich folgendes Bild: Die gelben Felder sind die Felder, die sich in der OpenList befinden. Das blaue Feld ist das letzte Feld in der Closedlist. In der Openlist stehen also Knoten, die gar nicht mehr beachtet werden dürften. Hab ich schon früher was falsch implementiert oder was ist da los? Ich hab mir die Implementation nämlich mal auf Wikipedia angeguckt und glaube es danach verstanden zu haben. Vielleicht seht ihr ja meinen Denkfehler, weil richtig ist es offensichtlich nicht. Wäre super, wenn mir jemand auf die Sprünge helfen könnte. @Bladerunner: Danke, aber ich steig bei deinem Code leider nicht ganz durch. Lg, M0rgenstern |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nein, es ist ganz normal das in der Open list auch zurückliegende Felder sind.
Es wird ja nur dann eines der "alten" Felder abgearbeitet wenn das nächstgelegene keinen Erfolg bot. Abschliessen darfst Du alte Felder erst wenn sie bearbeitet wurden. Die Open List ist also deine Fahrkarte um garantiert einen gültigen Weg zu finden. |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also brauch ich im Prinzip 3 Listen:
- Eine in der alle möglichen Knoten liegen (OpenList) - Eine in der schon alle (egal wann) überprüften Knoten liegen (ClosedList) - Eine die die Knoten beinhaltet, die dann den Weg bilden Oder? Denn dann kann man x-Schritte züruckgehen wenn man sich verrannt hat. Also, ist mein Fehler eigentlich, dass alle Knoten in der ClosedList auch direkt meinen Weg bilden? Ich müsste in der ClosedList ja die Knoten so abspeichern, dass sie auch immer auf den Vorgängerknoten, von dem aus dieser Knoten gefunden wurde, zeigen und dann aus der ClosedList einen Weg in einer Liste speichern. Stimmt das so? Lg, M0rgenstern |
||
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Du brauchst zwei Listen:
-Die OpenList, die alle Knoten beinhaltet, die noch nicht erweitert wurden -Die ClosedList, in der alle schon erweiterten/besuchten Knoten drin sind Jeder Knoten verweist zusätzlich noch auf den Knoten, von dem aus er erweitert wurde (bzw. der, von dem aus er die niedrigsten F-Kosten hätte). Der Weg wird nur über diese Information rekonstruiert. |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das ist ja im Prinzip was ich sage:
In der Openlist stehen alle Knoten, die noch nicht näher betrachtet wurden. Ind der Closedlist stehen alle Knoten, die schon überprüft wurden. Wenn man dann am Endknoten angekommen ist, dann hat man einen Weg gefunden und kann ihn rückwärts, also vom Endknoten aus, laufen, jeweils über die billigsten Knoten. Mir war vorher nicht klar, dass der A*-Algorithmus eine Breitensuche betreibt. Jetzt weiß ich auch, warum ich die Open-List nicht löschen sollte. Werde das gleich entsprechend umbauen. Vielen Dank, Lg, M0rgenstern EDIT: Wollte nur kurz Bescheid geben. Es funktioniert jetzt alles wunderbar. Sobald mir klar war, dass das Teil als Breitensuche angelegt ist, wusste ich was ich falsch gemacht habe. Vielen Dank für eure Hilfe und eure Denkanstöße. Ich denke, ich werde es noch ein wenig modularer bauen und dann ins Codearchiv setzen. Lg, M0rgenstern |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group