Bitte beachten Sie: Ich möchte hier keine Hilfe beim Codieren, ich bin Programmers
aus einem bestimmten Grund dabei. Ich möchte meine Programmplanungs- / Schreibfähigkeiten verbessern, nicht (nur) mein Verständnis von Java .
Ich versuche herauszufinden, wie man einen Baum mit einem beliebigen Kategoriesystem erstellt, basierend auf den Fähigkeiten, die hier für dieses LARP-Spiel aufgeführt sind . Mein früherer Versuch hatte ein Problem damit, ob eine Fertigkeit auch eine Kategorie war. Der Versuch, das zu umgehen, war chaotisch. Als ich meinen Baum herausholte, bemerkte ich, dass nur meine 'Blätter' Fähigkeiten waren und ich hatte die anderen als Kategorien bezeichnet.
Was ich will, ist eine Möglichkeit, einen Baum zu erstellen, der versucht, Modell und Ansicht zu trennen, und einem beliebigen übergeordneten Knoten einen beliebigen Typ eines untergeordneten Knotens hinzuzufügen (mit einer separaten Möglichkeit, bearbeitet / gerendert zu werden).
NB Alles hier wird als Fähigkeit gekauft, auch wenn es wie eine Eigenschaft scheint. Die Endbenutzer werden dies als das Kaufen von Fähigkeiten ansehen (was sie auf Papier tun) und sollten dies als solche darstellen, alle auf derselben Seite.
Erklärung des Baumes: Der Baum wird mit einer Reihe von hartcodierten Kategorien auf höchster Ebene ( Waffen, physische und mentale, medizinische und mehr usw.) "geboren". Daraus muss der Benutzer eine Fähigkeit hinzufügen können. Letztendlich möchten sie zum Beispiel die Fertigkeit 'Einhandschwert-Spezialisierung' ( nicht Gegenstand) hinzufügen . Klicken Sie dazu im Idealfall bei Weapons
Auswahl auf "Hinzufügen" und wählen Sie dann One-handed
einen Kombinationsfeldknoten aus, der für das untergeordnete Element angezeigt wird. Klicken Sie dann erneut auf "Hinzufügen" und geben Sie einen Namen in ein Textfeld für das untergeordnete Element ein, das angezeigt wird. Klicken Sie dann erneut auf "Hinzufügen", um ein "Level" oder "Tier" für dieses Blatt hinzuzufügen / festzulegen. Erst Kompetenz, dann Spezialisierung (zum Beispiel).
Wenn Sie eine andere Fertigkeit kaufen möchten, ist dies natürlich ein völlig anderer Weg zum Blatt. Möglicherweise benötigen Sie kein Kombinationsfeld auf der gleichen Ebene im Baum wie im Waffenbeispiel und benötigen auch eine andere Logik dahinter. Dies ist, was ich Probleme habe, meinen Kopf herumzukriegen, geschweige denn einzulernen; Wie erstelle ich eine Gruppe von Klassen und gebe nicht an , in welcher Reihenfolge sie zusammengefügt werden sollen?
Was ist ein gutes System, um diese Art von Baum im Code zu beschreiben? Alle anderen JTree-Beispiele, die ich gesehen habe, weisen vorhersehbare Muster auf, meine jedoch nicht . Ich möchte nicht alles in 'Literalen' codieren müssen, mit langen Listen, welcher Typ (Kombinationsfeld, Textfeld usw.) des Kinderknotens auf welchem Elternteil zulässig sein soll. Soll ich abstrakte Klassen verwenden? Schnittstellen?
Wie kann ich diese Art von Objektclustern erweiterbar machen, wenn ich andere Fähigkeiten hinzufüge, die nicht oben aufgeführt sind und sich anders verhalten?
Wenn es kein gutes System gibt, gibt es einen guten Prozess, um herauszufinden, wie man so etwas macht?
Die Zahnräder in meinem Kopf drehen sich:
Ich muss immer:
- Überprüfen Sie die Eltern
- Geben Sie Optionen basierend auf dem übergeordneten Element an
Ich beginne zu denken, weil ich aufgrund dieser Gemeinsamkeit eine Art abstrakte / Interface- skill
Klasse brauche , die gängige Methoden für Fähigkeiten und Kategorien definiert / umreißt. Ich kann (hoffentlich) Regeln und Optionen in eine Datenbank einfügen und von dort nachlesen. Die Frage ist nun, ob es sich um eine abstrakte oder eine Schnittstellenmethode handelt und wie man das umsetzt.
quelle
Antworten:
Einfaches veränderbares JTree-Beispiel
Code (kompatibel und getestet mit Java 7, um das obige Bild zu erstellen):
Besonderer Dank geht an dieses JTree-Tutorial
Update: Diskussion möglicher Lösungen
Es gibt ein Tutorial zum Erstellen eines dynamischen Baums mit Schaltflächen am unteren Rand des Rahmens zum Hinzufügen / Entfernen / Löschen von Knoten.
Für Comboboxen und dergleichen möchten Sie Objekte der entsprechenden Swing-Klasse nehmen und sie so etwas wie eine JComboBox haben, die java.swing.tree.MutableTreeNode implementiert. Das Java Swing Tutorial enthält eine Liste von Steuerelementen .
Sie müssen noch ein Benutzeroberflächenelement erstellen, damit Benutzer auswählen können, welche Art von Knoten sie hinzufügen möchten, und den Knoten bearbeiten können. Wenn sie ein Kombinationsfeld hinzufügen, müssen sie definieren können, welche Auswahlmöglichkeiten das Feld bietet.
Sie benötigen ein zugrunde liegendes Datenmodell, um Ihre Daten zu speichern. Sie können das Standard-Serialisierungsschema verwenden, das in alle Java-Objekte integriert ist, es dient jedoch nur dem Prototyping - es wird beschädigt, wenn Sie jemals Ihren Programmcode ändern. Sie müssen entweder eine Datenbank mit JDBC oder JPA verwenden, oder Sie müssen Ihre eigenen Serialisierungsroutinen schreiben (oder eine Bibliothek verwenden, die die Serialisierung für Sie übernimmt), wobei Sie etwas wie JSON oder XML als Speicherformat verwenden.
Update: Lösungsvorschlag mit Projektübersicht
Die einfachste Lösung könnte darin bestehen, Datenbanken zu vergessen und zuerst den XML-Ausdruck der Daten zu erstellen, dann die XML-Datei zu bearbeiten und die Ergebnisse einfach als JTree ohne spezielle Kombinationsfelder oder ähnliches anzuzeigen. Ich denke, das hat Chibueze Opata mit seiner Antwort vorgeschlagen. Eine teilweise XML-Darstellung dieses Baums könnte folgendermaßen aussehen:
Hier sind einige mögliche Meilensteine für Sie:
Stellen Sie sicher, dass Sie jedes Mal eine Sicherungskopie Ihres Programms sichern, wenn es am Ende jedes Meilensteins funktioniert. Ein Versionsverwaltungssystem, das auf einem anderen Computer installiert ist, ist hierfür ideal. Sie können Github, SourceForge oder eine andere öffentliche Quellcodeverwaltung verwenden, wenn Sie nichts dagegen haben, Ihren Code freizugeben und keinen Server mit darauf befindlicher Quellcodeverwaltung einrichten möchten.
Jede dieser Lösungen ist viel Arbeit und definitiv größer als ein Anfängerprojekt. Das bedeutet, dass Sie viel mehr Zeit mit dem Erlernen von Java Swing und XML oder JSON verbringen als mit dem Spielen von LARP. Aus diesem Grund habe ich zuerst die Möglichkeiten untersucht, mit vorhandenen Tools auszukommen. Aber der beste Weg, etwas zu lernen, ist der, zu dem Sie am meisten motiviert sind. Das könnte ein perfektes Projekt für Sie sein.
Ich hoffe das hilft.
quelle
Ich denke nicht, dass JTree die richtige Darstellung für das Problem ist, das Sie zu lösen versuchen. Ich habe mir Ihre Website angesehen und sehe Listen mit Dingen. Dies ist ein guter Anfang, aber ich denke, es gibt ein zugrunde liegendes Datendesign, das Sie möglicherweise haben, aber ich sehe es nicht.
Leben und Stärke sehen für mich wie Charakterattribute aus. Double, Triple und Quadruple sehen aus wie Werte für das Strength-Attribut. Dann sehe ich Fähigkeiten, die in Waffen und Medizin unterteilt sind. Ich stelle mir Waffen als Besitztümer vor (die man kaufen, finden oder fallen lassen kann), und ich gehe davon aus, dass es die Fähigkeit ist, mit der man mit einer bestimmten Waffe effektiv ist. Aber so wie ich das sehe, haben Waffen und Medizin keine Fähigkeiten, der Charakter schon. Tatsächlich vermute ich stark, dass der Charakter die zentrale Figur in Ihrem Datenentwurf ist.
Hier sind drei Datenobjekte, die sich für mich bisher von Ihrem Design abheben:
Jetzt kann ein Charakter Waffen und Fähigkeiten haben, aber für einen wirklich guten Angriff benötigen sie eine Fähigkeit, die für die von ihnen verwendete Waffe spezifisch ist. In jedem Fall gibt es hier eine Eins-zu-viele-Beziehung (ein Charakter kann viele Fähigkeiten haben). Aber ich sehe noch keine Bäume.
Nimm einen Block Papier und lege auf der ersten Seite den Charakter in die Mitte der Seite und liste die 5-10 wichtigsten Objekte der Spielwelt auf. Finden Sie heraus, welche Daten lediglich ein Attribut eines anderen Objekts sind (z. B. Leben und Stärke sind untrennbare Bestandteile des Charakters) und welche Beziehungen zwischen den Objekten am wichtigsten sind, ohne an Bäume, Textfelder oder Kombinationsfelder zu denken. Zeichnen Sie Linien zwischen Objekten, um Beziehungen darzustellen. Ermitteln Sie dann, welche Beziehungen 1: 1, welche 1: viele und welche viele: viele sind, und bezeichnen Sie sie. Es kann auch "has-a" und "is-a" und andere Arten von Beziehungen geben.
Sie können entscheiden, ob Sie separate Darstellungen für eine Waffenfertigkeit oder eine Heilfertigkeit oder eine Manufakturfertigkeit benötigen. Oder Sie entscheiden, dass sie sich so ähnlich sind, dass sie zu einer Fähigkeitentabelle (in meinem obigen Beispiel) gehören und in einem Feld festgelegt sind, um welche Art von Fähigkeit es sich handelt.
Es ist ein gutes Zeichen dafür, dass Sie mit Ihren bisherigen Versuchen nicht zufrieden sind - es bedeutet, dass Sie bereit sind, viele Möglichkeiten in Betracht zu ziehen, bevor Sie eine auswählen. Je mehr Skizzen Sie berücksichtigen, desto besser wird Ihr endgültiges Design. Schließlich wird das beste Ihr Datendiagramm. Wenn das ziemlich gut geklärt ist, können Sie wieder über "Kombinationsfelder" oder "Textfelder" nachdenken, aber ich würde die Entscheidungen über die Benutzeroberfläche bis zum Ende überlassen.
Anstatt sich JTrees anzuschauen, würde ich vorschlagen, dass Sie sich mit den Themen Datenstrukturen, Datenbankdesign und möglicherweise Datenmodellierung befassen. EDIT-> Oder besser Entity-Relationship-Mapping- Diagramme, wie David Kaczynski vorgeschlagen hat! <-EDIT Wenn Sie das Daten-Design richtig gestalten, werden Java und die Benutzeroberfläche offensichtlich und natürlich davon abgeleitet. Aber wenn Sie etwas falsch machen, wird es durch keine Menge Java-Kung-Fu oder UI-Beauty behoben.
Viel Glück!
quelle
Ich werde mich auf das Objektmodell konzentrieren.
Ich denke, für die Flexibilität, die Sie möchten, möchten Sie Ihre Klassen wahrscheinlich in eine Wissens- (in diesem Fall ist "Definition" ein besseres Wort) und eine Transaktionsschicht aufteilen. Mit "Ebene" meine ich wirklich nur, sie logisch in deinem Kopf zu trennen. Die Wissensschicht enthält Ihre Definition, wie der Baum angeordnet werden soll, und die darin enthaltenen Daten stammen von einem Spieledesigner, und die Datenschicht speichert bestimmte Auswahlmöglichkeiten für einen bestimmten Charakter.
Ihr Wissensstand wird zumindest ein wenig chaotisch sein, weil Sie versuchen, ein cooles Spiel zu machen, anstatt ein mathematisch sauberes Modell.
Ich denke, Sie haben eine SkillDefinition-Klasse mit einer Parent-Eigenschaft vom Typ SkillDefinition, um zu organisieren, was Sie bisher haben. Sie haben auch Unterklassen von SkillDefinition (die zu Einträgen in einer DEF_SkillType-Tabelle in der Datenbank werden können), um einige Fälle abzudecken.
"Waffen", "Körperlich und Geistig" und "Medizinisch" scheinen nur einen Titel (und kindliche Fähigkeiten) zu haben.
"One Handed", "Strength" und "Bind Wounds" scheinen ein zugehöriges Kombinationsfeld zu haben (was so etwas wie eine DEF_SkillChoice-Tabelle in der Datenbank mit einem Fremdschlüssel für DEF_Skill bedeutet). Schwert und Bogen scheinen eine benutzerdefinierte Zeichenfolge zu sein (daher keine zugeordnete Tabelle auf Wissensebene, aber die Daten werden auf der Transaktionsschicht gespeichert).
"Leben" scheint eine ganze Zahl zu haben. Es ist möglicherweise nicht möglich, diese Klasse mit zukünftigen Merkmalen zu teilen, die eine Ganzzahl verwenden, da implizites Verhalten beim Inkrementieren der Ganzzahl vorliegt. In jedem Fall benötigt es derzeit eine eigene Klasse.
"Schwert", "Bogen", "Stärke" und "Wunden binden" scheinen alle eine Stufe progressiver Fertigkeiten im Baum zu haben. Im Fall von "Schwert" und "Bogen" sind diese Stufen wirklich mit der übergeordneten Fertigkeit verknüpft. Ich denke, Sie benötigen eine ProgressiveSkillDefinition-Klasse mit einer geordneten Auflistung zulässiger Werte (Tabelle DEF_SkillLevel mit Fremdschlüssel für DEF_Skill. Auf der Wissensstufe ist nicht vollständig klar, welche Regeln Sie modellieren. Wenn "Kompetenz" und "Spezialisierung" immer verfügbar sind Möglicherweise verfügen Sie für alle Waffen über eine DEF_SkillLevel-Tabelle mit den Datensätzen "proficiency" und "specialization", die Fremdschlüssel für den Datensatz "Weapons" enthalten.
Dies deckt das ab, was Sie auf Wissensebene wissen. Die Transaktionsstufe (vielleicht "Zeichenstufe" wäre ein besserer Name?) Verweist nur auf die entsprechende Wissensstufe. In Ihrem Beispiel hätten Sie also ein Character-Objekt mit einem Skills-Objekt, das eine Sammlung von Skills enthält - nur die, die er tatsächlich hat.
Der Charakter hätte also eine Fertigkeit "Fertigkeit", deren Elternteil die Fertigkeit "Schwert" ist und deren Typ Skill_Level ist. In der Datenbank enthält der TRANS_SkillDefinition-Datensatz einen Fremdschlüssel für den Transaktions-Skill-Datensatz "Schwert" und den Wissensstand-DEF_SkillLevel-Datensatz mit dem Namen "Proficiency".
Die Fähigkeit skill hätte ein übergeordnetes Objekt der Fähigkeit "sword" vom Typ Skill_UserNamed. In der Datenbank hätte dies keinen Fremdschlüssel für den Wissensstand, da für "Schwert" (es ist der Name des Benutzers) nichts Besonderes definiert ist. Es hat jedoch auch einen Fremdschlüssel für den übergeordneten Transaktionsdatensatz, sodass über diesen weitere Informationen verfügbar sind.
Das Fertigkeitsobjekt "Schwert" hat ein übergeordnetes Objekt "Einhand", da der Benutzer "Schwert" in die Kategorie "Einhand" gestellt hat. Dies ist ein Objekt vom Typ SkillCategory. In der Datenbank hat es einen Fremdschlüssel für die Tabelle DEF_SkillChoice für den Datensatz "einhändig" und kein übergeordnetes Transaktionselement, da alle zusätzlichen Daten für diese Fähigkeit auf der Wissensstufe gespeichert sind.
Bei der Erstellung des Anfangsbaums für einen neuen Charakter muss nur der Wissensstand abgefragt werden. Zum Auffüllen der für einen Charakter getroffenen Auswahl ist die Transaktionsebene erforderlich.
Sie benötigen Code, um das Objektmodell in einen Baum und zurück zu übersetzen. Ich hoffe, es sollte klar sein, was Sie tun müssen - jeder Typ in der Wissensschicht verfügt über eine Reihe von Steuerelementen in der Struktur, die für diesen Typ geeignete Daten abrufen.
Später möchten Sie vielleicht Klassen für jede Auswahl in den SkillCategory-Datensätzen (wenn mit "Spezialisierung" Verhalten verbunden ist, muss der Code irgendwo hin), aber das brauchen Sie noch nicht für diesen Baum, und dieser Entwurf wird kompatibel sein damit. Sie benötigen lediglich eine Fabrik, die die Informationen des Wissensstands verwendet, um das richtige Objekt zu erstellen.
quelle
Schließlich müssen wir immer hierarchische Strukturen verwalten - sei es eine Klassenhierarchie eines Programms oder das Programm selbst, das aus verschiedenen Modulen besteht, die Sie mit einer "internen Welt" verbinden (GUI, DB-Verbindung, datengebundene Geschäftslogik usw.). . Aber das ist Philosophie, wie soll es in Ihrem Fall funktionieren?
Sie haben Knoten in diesem Baum. Jedes Element ist eine "Objektinstanz". während ihr Verhalten (wo Sie sie ablegen können, die Liste der zulässigen untergeordneten Knoten usw.) für einige Mengen wie "Klassen" üblich ist. Ja, das ist wie ein Programmcode. Wenn Sie mit der Java-Reflektion ausreichend vertraut sind, können Sie diese Komponente mithilfe von POJO-Klassen und Vererbungshierarchien zusammen mit einem IoC-Container oder einem Factory-Mechanismus erstellen, um die tatsächlichen Instanzen zu erstellen. Aber ich denke du willst das nicht, denn das ist ein harter Sprachhacking, also ...
Erstellen Sie zunächst ein "Klassen" -Objekt, das das Verhalten der Elemente beschreibt. Dies beinhaltet Klassenkennungen, "Feld" -Namen und die zulässigen Arten und die Anzahl der Gegenstände usw. Beispiel: Die "Stamm" -Klasse ist "Spielereigenschaften", hat das Feld "Physisch / Geistig", "Medizinisch", "Waffen". Dieser Typ ist "final": Im Moment möchten Sie keine unterschiedlichen Spielertypen haben. Tipp: später kannst du es mit den gleichen Werkzeugen machen, um mit "nichtmenschlichen Monstern" umzugehen ... :-)
Das "medizinische" Feld ist
Gegenteil: Ein Waffenmitglied ist nicht erforderlich. Es sollte erstellt werden, wenn die erste Waffe zu Ihrem Spieler hinzugefügt wird. Das bedeutet: Wenn Sie Ihr "Objekt" (jetzt den Spieler) "bearbeiten" und ihm das Hinzufügen eines neuen Gegenstands erlauben möchten, sollten Sie die Auswahl nicht durch die tatsächlichen Eigenschaften der Instanz (die jetzt keine "Waffen" enthält) einschränken "), aber zeigen Sie alle Felder der Klassendefinition an und erstellen Sie das neue Feld (untergeordneter Knoten) bei der ersten Verwendung. Dadurch wird eine erweiterbare Umgebung erstellt. Später können Sie das Feld "Freunde" mit Referenzen für mehrere Spieler hinzufügen (siehe später).
Folgen Sie dem Prozess mit den tatsächlichen "Klassen". Es wird Ihnen helfen, Ihre Ideen zu verfeinern, wie zum Beispiel: Es scheint besser, Waffentypen (Schwerter, Dolche, Bögen, ...) zu trennen, mit Munition umzugehen (wohl wissend, dass der Spieler keinen Bogen hat, aber Pfeile sammeln kann, aber verwendet Bestimmte Waffen erfordern und verringern Munition, einige können gefunden werden, andere gehen verloren ...) in der Klasse "Waffen": Es ist einfacher zu überblicken und es kann auch angezeigt werden, ob Ihr Spieler nur diesen Gegenstand trägt oder auch verwenden kann ( hat die Fähigkeiten). Auf der anderen Seite: Sie werden diese Struktur sicherlich später ändern, wenn Sie Ihr Spiel entwickeln.
Erstellen Sie einen global verfügbaren "Klassenladen", den Sie zu Beginn Ihres Spiels initialisieren, und bedienen Sie die Klassendefinitionen, wenn sich jemand auf ihren Namen bezieht. Die class def Objekte müssen in diesem Fall unveränderlich sein.
"Objekte" sind einfacher: Sie können von derselben Stammklasse abgeleitet werden, die einen Verweis auf die Klassendefinition sowie einen generischen Zugriff auf die Felder enthält. Verwenden Sie möglicherweise eine HashMap, um diese untergeordneten Elemente zu enthalten, die durch den Feldnamen gekennzeichnet sind. Denken Sie daran: Einige dieser Felder enthalten ein einzelnes Objekt, andere eine Reihe von Objekten. Diese Instanzen sind natürlich veränderlich.
Nun zur Schnittstelle. Zuerst sollten Sie das JTree-Tutorial überprüfen ... und es sollte jetzt offensichtlich sein. Jedes "Objekt" kann durch einen DefaultMutableTreeNode dargestellt werden. Das "userObject" des Knotens sollte Ihr Objekt sein. Wenn Sie einen Knoten öffnen, durchsuchen Sie die Felder des Objekts und erstellen untergeordnete Knoten unter dem übergeordneten Knoten (wenn Sie dies dynamisch tun möchten). Sie können auch den gesamten Baum durchsuchen und die TreeNode-Struktur erstellen, wenn Sie den JTree anzeigen (Hinweis: dort) ist ein JTree-Konstruktor mit einem TreeNode-Parameter.
Wenn Sie einen Knoten in der Baumstruktur auswählen, haben Sie die Objektinstanz. Anhand der Klasse können Sie ein geeignetes Editorfenster oder ein durch die Klassendefinition generiertes generisches Fenster anzeigen (z. B .: Registerkarten mit den Feldern, Editoren für das tatsächliche Feld durch die Felddeklaration: eine Schaltfläche, die ein untergeordnetes Element des geeigneten Typs erstellt Mit of können Sie eine der verfügbaren Klassen und Editorfelder für diese Instanz auswählen (z. B. Waffeneigenschaften). Nachdem Sie die Struktur geändert haben, müssen Sie den Baum selbst aktualisieren - das TreeModel und seine Änderungsfunktionen sind Ihre Freunde.
Sieht gut aus? Oder zu komplex? Nun, das ist ein kleiner Teil der Geschichte. Ich habe nicht darüber gesprochen
Wie auch immer, ich hoffe, Sie können etwas von dieser Aufwärmsitzung verwenden.
quelle
Ich werde Ihnen keine lange Antwort geben, aber ich habe diese Art von Situation schon einmal erlebt und ehrlich gesagt aufgegeben, die vorhandenen Datenstrukturen zu verwenden. Ich habe einfach mein eigenes Objekt erstellt, das neue Eltern und Kinder aufnehmen kann, ähnlich einem XML-Knoten.
In Ihrem Fall kann die Verwendung einer Xml-Klasse jedoch hilfreich sein. Sie können dann Eigenschaften für jeden Knoten festlegen, anhand derer Sie erkennen können, ob es sich bei einer Klasse um eine Fertigkeit handelt, und auf einfache Weise Eltern und Kinder eines beliebigen Knotens abrufen, der in einem Kombinationsfeld oder auf andere Weise verwendet werden soll.
Außerdem möchte ich hinzufügen, dass Sie nicht davor zurückschrecken sollten, viele Texte / Zeichenfolgen zu haben. Spiele beinhalten normalerweise KI und KI beinhaltet normalerweise viele Texte.
quelle