Pfadfinder

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    Hey Leute,

    eine kleine Aufgabe für Euch und evtl. könnt Ihr mir helfen, meine Lösung zu verbessern. Kommen wir gleich zum Thema.

    Die Aufgabe besteht darin, den kürzesten Weg zwischen zwei Orten zu finden. Konkret bezieht sich das Ganze auf das Spiel EVE-Online. EVE-Online ist mit das größte MMO, das es gibt. Es existiert seit nun fast 13 Jahren. Die Welt von EVE-Online ist die Galaxy "New Eden". Es gibt 5201 verbundene Sonnensysteme, genannt K-Space (Known-Space). 2604 nicht direkt verbundene Sonnensystem W-Space (Wormhole-Space) und 230 nicht zu erreichende Sonnensysteme, der Jove-Space.

    Sonnensysteme sind zusammegefasst in Constellations, Constellations sind zusammengefasst in Regions. Sonnensysteme haben verschiede Security-Classes => High-Sec, Low-Sec und 0-Sec. Das aber nur am Rande. Hier geht es nur um die 5201 untereinander erreichbaren Sonnensysteme.

    evemaps.dotlan.net/map

    Dies ist die Darstellung der Regionen. Mit einem Klick auf eine beliebige Region erhaltet Ihr die Übersicht der in dieser Region enthaltenen Sonnensysteme.

    evemaps.dotlan.net/map/Lonetrek#sec

    Beispielsweise die Region "Lonetrek".

    Jedes Sonnensystem enthält mindestens 1 Stargate, welches zu einem anderen Sonnensystem führt. Manche Systeme haben Verbindungen zu mehreren benachbarten Systemen.

    evemaps.dotlan.net/map/Lonetrek/Nalvula#sec

    Am Beispiel Sonnensystem "Nalvula" (hier schwarz umrahmt) in der Region "Lonetrek". "Nalvula" hat jeweils eine Verbindung zu "Jan", "Vuorrassi", "Oimmo", "Otsasai", "Taisy" und "Hakonen".

    Will ich nun vom System "Nalvula" nach "Mara" (4 Systeme, ausgehend von "Nalvula", links und eines runter) reisen, ergibt sich folgende Route:

    evemaps.dotlan.net/route/Nalvula:Mara

    Wenn Ihr nochmal eine Blick auf die Map werft, seht ihr aber, dass noch eine zweite Route, mit der gleichen Entfernung (Jumps) möglich gewesen wäre.

    Nalvula => Vuorrassi => Hageken => Uosusuokk => Piekura => Mara

    Es sind noch weit aus mehr Routen möglich, die aber aufwändiger wären.

    Jedes Sonnensystem hat eine Position in der Galaxy (X, Y, Z). Jedes im Spiel befindliche Objekt hat diese Position. Anhand dieser Koordinaten lässt sich die Entfernung in AU (Astrometic Uint) oder LY (Light Year) berechnen. Dies ist der Grund, warum diese Route evemaps.dotlan.net/route/Nalvula:Mara ausgegeben wurde und nicht die Alternative. Aber auf das lege ich keinen Wert. Wenn jemand wirklich überhaupt Lust hat, sich da hineinzudenken, einfach als Fleissaufgabe ansehen.

    Die Definition für die kürzeste Route soll die Anzahl der Gate-Jumps sein, nicht die zurückzulegende Entfernung.

    All diese Daten werden von CCP, das ist das Unternehmen, das hinter EVE-Online steht, bereitgestellt. Nein, ihr braucht Euch nicht darum kümmern. Ich habe fast das komplette EVE-Universum in Code abgebildet. Alle Daten, die zur Durchführung der Aufgabe nötig sind, erhaltet Ihr von mir.

    Im Anhang findet Ihr eine Projektmappe (DLL-Projekt). Übersetzt es und verweist in einem Projekt auf diese .dll.

    VB.NET-Quellcode

    1. Imports EveUniverse
    2. Module Module1
    3. Private _universe As Universe = Universe.BuildDefaultEveUniverse()
    4. Sub Main()
    5. End Sub
    6. End Module


    Wird Eure Anwendung dann zum 1. mal gestartet, wird es ein bisschen dauern. Die nächsten Starts laufen dann schneller. Nachdem das Universe erstellt wurde, liegt es in serialisierter Form in Eurem Debug-Ordner (eveUniverse.dat)

    Um mit der Arbeit zu beginnen, benötigt Ihr die 5201 verbundenen System (K-Space). Dazu:

    VB.NET-Quellcode

    1. Imports EveUniverse
    2. Module Module1
    3. Private _universe As Universe = Universe.BuildDefaultEveUniverse()
    4. Sub Main()
    5. Dim kSpace As IEnumerable(Of Solarsystem) = _universe.Solarsystems.Where(Function(x) x.IsKSpace)
    6. End Sub
    7. End Module


    Die Variable kSpace enthält nun eine Auflistung aller relevanten Systeme. Für die Lösung der Aufgabe wichtig ist Folgendes:

    VB.NET-Quellcode

    1. Imports EveUniverse
    2. Module Module1
    3. Private _universe As Universe = Universe.BuildDefaultEveUniverse()
    4. Sub Main()
    5. Dim kSpace As IEnumerable(Of Solarsystem) = _universe.Solarsystems.Where(Function(x) x.IsKSpace)
    6. Dim y As Solarsystem = kSpace(0)
    7. y.AdjacentSolarsystems.ForEach(Sub(z)
    8. Console.WriteLine(z.SystemName)
    9. End Sub)
    10. Console.ReadLine()
    11. End Sub
    12. End Module


    Die Klasse Solarsystem enthält eine Auflistung der benachbarten Systeme (AdjacentSystems), sowie die Koordinaten im Universum, falls Ihr auch an die Zusatzaufgabe ranwollt. Meine, zugegeben, recht dürftige Umsetzung der Aufgabe findet Ihr in der Klasse Universe => CalculateRoute. Ich bin, was Logik und Mathematik angeht, eher recht weit unten anzusetzen. Das Projekt habe ich letztes Jahr im Dezember begonnen und konnte die Aufgabe nicht zu meiner Zufriedenheit lösen.

    Ich wollte alle möglichen Routen vorberechnet haben und dachte zuerst, meine erste Umsetzung wäre gut. So sind 3 PCs über eine Woche 24/7 gelaufen und haben alle Kombinationen durchgerechnet. Danach musste ich leider feststellen, dass mein Ansatz fehlerhaft war. Danach habe ich das Projekt nicht mehr angerührt. Die in der Projektmappe enthaltene Routenberechnung funktioniert soweit und ich konnte bisher keine Fehler feststellen, jedoch lässt die Performance doch sehr zu wünschen übrig.

    Mein Ziel ist es, nochmals einen Versuch zu starten, alle Routen im Voraus zu berechnen.

    Noch gut zu wissen ist, dass jedes Solarsystem eine ID hat. Jedes Objekt im Universum hat eine ID. Es ist mit Sicherheit schneller, nur diese IDs als Grundlage für die Berechnung zu nutzen. Dies überlasse ich jedoch Euch.

    Um Eure Ansätze zu überprüfen, könnt Ihr diese Seite verwenden:

    evemaps.dotlan.net/route

    oder als direkt URL: evemaps.dotlan.net/route/nalvula:mara

    Die Werte hinter dem letzten Slash entsprechend abändern.

    Das gesamte Projekt ist, ebenfalls zugegeben, niemals sauber ausprogrammiert worden. Es ist eher aus einer Laune heraus entstanden. Darum bitte ich um Nachsicht für den schlampigen Code.

    Ich bin echt gespannt, wie Ihr das umsetzt.

    Viel Spass und Fragen jederzeit hier posten.
    Dateien
    • EveUniverseDLL.zip

      (4,22 MB, 298 mal heruntergeladen, zuletzt: )
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Ich weiss nicht, ob man das Breitensuche nennt, was ich als Ansatz habe.

    1. Schritt, checke ob das Ziel bereits in 1 oder 2 Jumps zu erreichen ist.
    2. Falls nein, bilde ich eine Liste von Routen, die Waypoints beinhalten. Jede Route bekommt als Start den Ursprung und jeweils ein benachbartes System. Dies geht solange, bis ein System das Ziel als Nachbarn hat.
    3. Jedes bereits besuchte System wird bei einer weiteren Routenbildung nicht mehr herangezogen. Ebenso werden Systeme ausgeschlossen, die nur 1 Nachbarsystem haben (Dead-End).
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Also da kann ich mir vorstellen, warum das so eine lange Laufzeit hat. ^^
    Du hast hier einen ungerichteten, ungewichteten Graphen vorliegen und in diesem Fall ist die Breitensuche die optimale Lösung (sie hat nämlich gerade mal lineare Laufzeit!). Und Breitensuche ist zudem auch kinderleicht zu implementieren. Versuch nicht das Rad neu zu erfinden. ;)
    de.wikipedia.org/wiki/Breitensuche
    Da stimme ich Artentus zu, der A*- oder Dijkstra-Algorithmus ist relativ leicht umzusetzen, für den Anfang kannst du die Kanten ja mit 1 alle gewichten, später mit der tatsächlichen Entfernung.
    Ich hab momentan nur nicht die Zeit dazu :D
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    So, im Anhang mal meine Lösung. Ohne Optimierung, ohne Berücksichtigung kurzer Strecken, und vermutlich ziemlich unelegant. Und in C#.
    Aber wie in den Bildern zu sehen ist, funktioniert es, in unter einer Sekunde, selbst für 91 Jumps; ohne Mathematik; lediglich Logik ;)

    PS: Es ist empfehlenswert, die Regions- und Konstellationsfilter in Ruhe zu lassen. Einmal aktiv, können die derzeit nicht mehr gelöscht werden :D
    Bilder
    • EVE_Route2.JPG

      67,64 kB, 719×787, 106 mal angesehen
    • Route_3.JPG

      71,34 kB, 728×454, 104 mal angesehen
    • Route_4.JPG

      130,27 kB, 728×852, 119 mal angesehen
    • EVE_Route.JPG

      68,17 kB, 722×788, 110 mal angesehen
    Dateien
    • EveUniverseDLL.zip

      (1,51 MB, 277 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    Artentus schrieb:

    Das ist alles Informatik 1. Semester.
    OT: War das bei euch auch Stoff der 11. Klasse oder ist Dir das jetzt erst im Studium begegnet? Wir hatten's auf jeden Fall im ersten Halbjahr. :P

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Doch schon aber Informatikuntericht in der Oberstufe ist ja keine Pflicht und wurde (zumindest auf meiner Schule) von nicht sonderlich vielen gewählt. Daher kann man dieses Wissen von einem Schüler nicht erwarten.
    Und den mathematischen Hintergrund gibts so oder so nur auf der Uni.