Большие ветвящиеся деревья в Яве?

Мой вопрос о масштабируемом логическом ветвлении.

Существует ли элегантный способ ветвления логических деревьев в Java (хотя я всегда думал, что они больше похожи на корневые системы, но это не относится к делу). Я пытаюсь разработать очень простую текстовую приключенческую игру как побочный проект для моих исследований, но я не уверен, что лучший способ ориентироваться в этих больших логических системах.

В настоящее время я пытаюсь создать массив, который содержит четыре значения: этап, местоположение, шаг, выбор.

[РЕДАКТИРОВАТЬ - добавлена ​​переменная выбора, чтобы сохранить выбор пользователя, изменено имя, чтобы отразить фактическое имя в моем коде, чтобы потом не запутаться]

int[] decisionPoint = {stage, location, step, choice};

Сцена, как предполагается, представляет единственную главную часть дерева. Местоположение должно представлять мое местоположение в дереве. Предполагается, что шаг представляет мой прогресс в данном месте. Выбор пользовательский ввод

На данный момент, так как я имею дело только с одним деревом, сцена не используется много. Расположение и шаг работают хорошо, но каждый раз, когда я принимаю решение в течение шага, система выходит из строя.

Я мог бы продолжать создавать все больше и больше переменных для представления более глубоких и глубоких слоев в дереве, но я чувствую, что Java, вероятно, где-то предлагает лучшее решение.

В настоящее время я использую операторы switch, чтобы выяснить, где в программе я базируюсь на значениях, хранящихся в nextQuestion. Есть ли что-то лучше? Или, есть ли способ расширить массив за пределы того, что я здесь использую, чтобы сделать его немного более полиморфным (в методах для отдельных вопросов / текста / что бы я мог просто сделать, чтобы он создал больший массив из меньшего? Могу ли я передать меньший массив в качестве аргумента, но определить параметр как больший массив?)

//Switch example
switch(LocationTracker.getLocation()) { //start location finding switch
    case 1 : //Location 1
        switch (LocationTracker.getStep()) {//start location1 switch
            case 1 :
                location1s1(graphicsStuff);
                break;
            case 2 :
                location1s2(graphicsStuff);
                break;
         } break; //end location1 switch
    case 2 : //Location 2
        switch (LocationTracker.getStep()) {
            //same stuff that happened above
        } break;

Все, что я нахожу в Интернете, просто приводит меня на нерелевантные страницы о разных создателях онлайн-опросов, которые я могу использовать. Если бы я мог посмотреть их исходный код, это было бы неплохо, но так как я не могу, я надеюсь, что вы, ребята, можете помочь.:)

[РЕДАКТИРОВАТЬ]

Вау, какой хороший ответ за такое короткое время в такой ранний час!

Я постараюсь подробно рассказать о том, как я решаю проблему прямо сейчас. Стоит отметить, что это технически работает, просто каждый раз, когда мне нужна ветка внутри ветви, я должен создавать другую переменную внутри массива строк, чтобы отслеживать свою позицию, и на самом деле я просто ищу решение, которое не не нужно бесконечно расширяющейся строки, так как программа становится все более и более сложной.

Прямо сейчас у меня есть программа с 5 классами: Главный класс, который запускает GUI. Класс GUI, который предоставляет три сервиса: userInput, userOptions и outputArea.

Класс DecisionTreeStage1, который обрабатывает логику моей проблемы на данный момент (используя операторы switch). Класс LocationTracker, предназначенный для отслеживания моего местоположения в классе DecisionTreeStage1. Класс DialogueToOutput, который изменяет параметры, доступные пользователям, а также обновляет поля вывода с результатами их действий.

Особый интерес: я хочу, чтобы в какой-то момент было несколько ветвей решений и одно главное дерево (возможно, назовем его Yggdrasil?:D). На данный момент DecisionTreeStage1 представляет собой очень изолированную систему, которая не собирается никуда идти. Я надеюсь использовать переменную stage, хранящуюся в моем массиве, чтобы перейти от одной основной ветви к другой (поднимаясь по дереву, если хотите). Моя текущая реализация для этого просто использует вложенные операторы switch, чтобы решить, куда я иду. Это накладывает раздражающее ограничение: каждый раз, когда мой путь становится все глубже и глубже, мне нужна другая переменная в моем массиве для хранения этих данных. Например:

//Switch example deeper
switch(LocationTracker.getLocation()) { //start location finding switch
    case 1 : //Location 1
        switch (LocationTracker.getStep()) {//start location1 switch
            case 1 :
                switch(LocationTracker.getChoice()) {//Make a decision at this step based on the user choice

Учитывая этот пример, что, если выбор пользователя не просто приводит к некоторой логике? (В этом случае просто обновление для outputArea). Что, если это приведет к ДРУГОМУ пути ветвления? И что ведет к другому пути ветвления? В конце концов, я бы хотел, чтобы все пути сходились в одном месте, чтобы я мог перейти к следующему "этапу".

Моя настоящая надежда - сделать эту проблему бесконечно масштабируемой. Я хочу иметь возможность заходить в одну ветку настолько глубоко, насколько мне нужно, без необходимости каждый раз создавать статическое и произвольное количество объявлений переменных в моем массиве решений.

Я не смог найти много информации об этом, как я уже сказал.

Позвольте мне попытаться представить этот вопрос: существуют ли другие логические операторы ветвления, кроме:

if(something)
    stuff;
else
    otherStuff;

а также

switch(something) {
    case 1:
        stuff;
        break;
    case 2:
        otherStuff;
        break;

И если да, то что они?

PS - Я знаю о троичном операторе if в Java, но это не похоже на то, что я делаю.:)

2 ответа

Решение

Вы можете построить нормальные древовидные структуры в Java, аналогично деревьям, которые могут быть построены в C. Независимо от того, являются ли ссылки на объекты теоретически указателями или нет, они прекрасно заменяют указатели в конструкциях дерева:

class Node {
  Node left;
  Node right;
  Node parent;
}

Вы также можете создавать графики (в том числе циклические) и связанные списки без проблем. Нет никаких очевидных причин, по которым у больших структур должны быть проблемы (кроме этой ссылки на объект используется некоторая память).

Вместо того, чтобы возвращать значение, вы можете вернуть Callable который просто должен быть выполнен. Затем это может быть приковано цепью (теоретически бесконечно)

Вы можете иметь LocationEvaluation например, который может вернуть SpecificLocationEvaluator который в свою очередь возвращает один из StepEvaluation или же ChoiceEvaluator или что-то подобное. Все они будут реализовывать интерфейс Callable.

В зависимости от того, как вы это делаете, вы можете иметь строгую проверку типов, чтобы LocationEvaluation всегда возвращал SpecificLocationEvaluator или он мог быть универсальным, а затем вы можете связать любой из них в любом порядке.

Как только вы построите структуру, у вас будет существовать дерево, по которому можно будет пройти, чтобы решить ее.

Я не понимаю проблему адекватно, чтобы иметь возможность предоставить более конкретные детали реализации - и извинения, если я неправильно понял некоторые из ветвления (то есть имена классов / шагов выше)

Другие вопросы по тегам