Wie erstelle ich einen veränderlichen, abwechslungsreichen jtree mit beliebigen / generischen Kategorieknoten?


12

Bitte beachten Sie: Ich möchte hier keine Hilfe beim Codieren, ich bin Programmersaus 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).

Ein Baum mit verschiedenen Fähigkeiten aus dem obigen Link

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 WeaponsAuswahl auf "Hinzufügen" und wählen Sie dann One-handedeinen 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- skillKlasse 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.


Ich habe begonnen (nachdem ich mit einem Freund gesprochen habe), eine abstrakte Klasse für die SkillComponents in den Daten auszuwerten und dann die einzelnen Fälle durch Erweitern der Basisklasse zu spezifizieren. Der Baum schaut sich die Daten einfach an und zeichnet sich entsprechend. Ich werde antworten, wenn es funktioniert.
Pureferret

Frage: Das Leben ist eine Fähigkeit mit einer "Level" -Eigenschaft, die inkrementiert werden kann. Ist dies einzigartig für das Leben, oder können andere Fähigkeiten auch im Level gesteigert werden? Ich kann mir eine Kombination aus einer abstrakten Klasse und mehreren Schnittstellen in Ihrer Lösung vorstellen, z. B. eine abstrakte Klasse "Skill" oder "Category" oder "SkillNode", um Ihren Baum zusammen mit einer Reihe von Schnittstellen wie "Specializable" aufzubauen "oder" Levelable ", um verschiedene Funktionen einzumischen, die für die Baumstruktur nicht erforderlich sind. Kommentieren nur zum Spaß ... hoffe du findest was du suchst!
David Kaczynski

Sie geben in der Frage jTree an. Fragen Sie sich, wie Textfelder und Kombinationsfelder als Knoten angezeigt werden sollen, oder suchen Sie nach einem Design, das nicht für Java spezifisch ist?
PSR

@DavidKaczynski du hast den Nagel auf den Kopf getroffen. Ich werde so etwas so schnell wie möglich implementieren.
Pureferret

@psr Ich versuche zu sehen, ob es ein kodifiziertes Muster (nicht unbedingt ein 'Entwurfsmuster') von Klassen gibt oder auf andere Weise, um dies zu begründen. David Kaczynski kommt dem sehr nahe.
Pureferret

Antworten:


3

Einfaches veränderbares JTree-Beispiel

Bildbeschreibung hier eingeben

Code (kompatibel und getestet mit Java 7, um das obige Bild zu erstellen):

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class SimpleTree extends JFrame {
    public static void main(String[] args) {
        new SimpleTree();
    }

    public SimpleTree() {
        super("Mutable Varied JTree");
        Container content = getContentPane();
        N root = new N("Root");

        N weapons = new N("Weapons").add(
            new N("One-handed").add(
                new N("Sword").add("Proficiency", "Specialization"), 
                new N("Mace").add("Proficiency")),
            new N("Bow").add("Proficiency"));
        root.add(weapons);

        N phys = new N("Physical & Mental").add(
            new N("Life"),
            new N("Strength").add(
                "Double", "Triple", "Quadruple"));

        root.add(phys);
        N med = new N("Medical");
        med.add(new N("Bind Wounds"));
        med.add(new N("Set Broken Bones"));
        root.add(med);

        JTree tree = new JTree(root);
        content.add(new JScrollPane(tree), BorderLayout.CENTER);
        setSize(275, 300);
        setVisible(true);
    }

    private class N extends DefaultMutableTreeNode {
        public N(String s) { super(s); }
        public N add(String... strs) {
            for (String s : strs) {
                super.add(new N(s));
            }
            return this;
        }
        public N add(N... ns) {
            for (N n : ns) {
                super.add(n);
            }
            return this;
        }
    }
}

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:

<folder name="Physical &amp; Mental">
    <int name="Life">12</int>
    <drop-down name="Strength">
        <option name="Single" />
        <option name="Double" />
        <option name="Triple" />
        <option name="Quadruple" />
    </drop-down>
</folder>
<folder name="Medical">
    <text name="Bind Wounds" />
    <text name="Set Broken Bones" />
</folder>

Hier sind einige mögliche Meilensteine ​​für Sie:

  • Erstellen Sie ein XML- oder JSON-Datenformat und schreiben Sie dann ein Programm, das eine Datei dieses Formats liest und als JTree ohne Kombinationsfelder, nur Ordner und Dateien, anzeigt.
  • Fügen Sie der JTree-Anzeige Swing-Steuerelemente hinzu
  • Erweitern Sie Ihr Programm, um dieselbe Datei zu schreiben
  • Erstellen Sie eine Benutzeroberfläche, damit der Benutzer Knoten über die GUI hinzufügen und bearbeiten kann

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.


Hallo, ich bin gerade auf meinem Handy, daher kann ich dies nicht vollständig überprüfen, aber es sieht so aus, als ob ich danach Ausschau halten würde, aber wie ich in meiner Frage darlege, muss ich in der Lage sein, verschiedene Knotentypen auszutauschen. +1 für den richtigen Weg!
Pureferret

1
"DefaultMutableTreeNode bietet Vorgänge zum Untersuchen und Ändern der übergeordneten und
untergeordneten Elemente

Mein Problem dabei, Glen, ist, dass dies zwar einen potenziellen Baum darstellt, aber möglicherweise nicht die Fähigkeiten eines Charakters darstellt. Sie müssen in der Lage sein, den Waffentyp in ein Textfeld einzugeben und beispielsweise einige Optionen aus einem Dropdown-Kombinationsfeld auszuwählen. In diesem Sinne ist es veränderlich und erlaubt beliebige Kinder. Sie haben nur eine Art von Kindknoten hier, N . Außerdem bin ich nicht wirklich nach Code (so gut das Beispiel ist), sondern eher nach einem allgemeinen Entwurfsmuster für solche Dinge / Bäume / Datenmodelle .
Pureferret

1
OK, Sie möchten ein Programm, mit dem Menschen Bäume machen können - wie eine Gliederung. In Microsoft Word ist bereits eine Gliederungsansicht vorhanden. OpenOffice / LibreOffice Write verfügt über ähnliche Funktionen. Was brauchst du noch?
GlenPeterson

1
Ich weiß, dass ich mit all meinen Fragen die Leute falsch reiben kann und entschuldige mich dafür. Aber ich muss das tun, um das Problem zu verstehen. Ich habe das Ende meiner Lösung oben (unter der großen Überschrift "Aktualisieren") mit den Antworten auf Ihre Fragen aktualisiert, oder zumindest Anleitungen, wie Sie sie selbst beantworten können. Ich hoffe das hilft.
GlenPeterson

2

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:

Character:
    Life (a value: e.g. 12)
    Strength (a value: e.g. double, triple, quadruple)
    Skills (list or set of weapon-skills, healing-skills)
    Possessions (list of weapons, armor and other possessions)
    WornArmor (maybe only wear one you possess at a time?)
    WieldedWeapon (one or two of your posessions)

Skill:
    Skill-Type (healing, manufacture, or weapon)
    RelevantWeapon (for this skill)

Weapon:
    IsOneHanded (boolean)
    IsBow (boolean)

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!


2

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.


Wenn dies unklar ist oder die Frage nicht beantwortet wird, lassen Sie es mich wissen. Es ist ein großes Thema und irgendwann musste ich aufhören.
PSR

Dies ist die Antwort, die am ehesten meinen Wünschen entspricht, die sich für das System, das ich emuliere, als natürlich anfühlt und die möglicherweise funktioniert. Im Moment basieren meine Fähigkeiten alle auf einer abstrakten SkillComponent (AbSkillComponent, da ich keine gute Benennungskonvention für abstrakte Klassen finde), und ich habe eine RootSkillComponent, SkillComponent und einige Schnittstellen für die Dropdown-Box und den UserNamed-Teil. Ich muss mich bei Ihnen bedanken, dass Sie hinzugefügt haben, wie sich dies auf die Datenbank auswirkt. Das schiebe ich jetzt auf, aber es lohnt sich, darüber nachzudenken. Diese Antwort ist sehr gut und sicherlich ein Hauch frischer Luft.
Pureferret

@ Pureferret - Ich denke, ich lasse die Antwort so wie sie ist - Ich war mir nicht sicher, ob ich weiß, wonach du suchst.
PSR

1

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

  • "Singleton": Der Spieler kann nicht mehrere "Medical" -Informationen haben
  • Der untergeordnete Typ ist festgelegt, hier kann nur ein Objekt vom Typ "Medizinisch" verwendet werden
  • Erforderlich: Wenn Sie einen Spieler erstellen, muss dieses Feld "Medizinisch" enthalten

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

  • die Klassendefinitionshierarchie / oder Kategorisierung. Verwenden Sie besser einen von ihnen, wenn Sie das Hinzufügen verschiedener Klassen zum selben Feld unterstützen (wie verschiedene Arten von Schwertern). Ein Profi für die Kategorisierung: Eine Klasse kann mehrere Kategorien haben, keinen festen Vererbungsbaum. Ein gutes Zeug, wenn Sie "alle Fähigkeiten" eines Spielers sammeln möchten, wenn Sie die EP für Verbesserungen der Fähigkeiten ausgeben ... :-)
  • Persistenzunterstützung: Sie müssen eine generische Lösung erstellen, um die Objekthierarchie extern zu speichern, z. B. in einer Eigenschaften- oder JSON-Datei. Verwenden Sie ein für Menschen lesbares Format, KEINE binäre Serialisierung, wenn Sie Ihr Gehirn in guter Verfassung halten möchten.
  • Instanzspeicher: Sie werden schnell feststellen, dass die "Welt" Ihres Spiels besser an einem Ort aufbewahrt werden sollte. Ein bestimmtes Schwert ist KEIN Eigentum Ihres Spielers, aber eine Entität in der Welt in Ihrem Spiel (der Spieler kann es verlieren, jemand kann es finden usw.), so dass viele dieser "Objekte" in Ihrem Baum tatsächlich VERWEISE auf Entitäten sind (während andere, wie die Gesundheit des Spielers, eigentlich nur Attribute sind). Sie müssen die beiden Typen trennen und über einen globalen Speicher für die Instanzen verfügen, die Verweise auflösen können. Dies erspart Ihnen auch das Serialisieren des Spielstatus, und mehrere Entitäten verweisen auf dieselbe andere Entität (wie der "Standort" mehrerer Spieler im selben Tempel).
  • (und um das echte Gehirnmühlen zu erwähnen: die Ähnlichkeit des Klassenspeichers und des Instanzenspeichers; die Tatsache, dass die Typdeklaration selbst Objektinstanzen sein kann, genau wie Ihre Programmkomponenten, aktiven Fenster, Benutzersitzungen usw. Dies ist das Land von Maniacs wie mir.)

Wie auch immer, ich hoffe, Sie können etwas von dieser Aufwärmsitzung verwenden.


1

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.


Dieses Spiel wird nicht über das Programm gespielt, es werden nur persistente Daten und eine gewisse Logik dargestellt. Ich werde mir XML auf jeden Fall ansehen. Vielen Dank!
Pureferret
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.