Java. Помогите связать три класса между собой с помощью переменных

Делаю проект, состоящий из пяти игр. На логику каждой игры - один класс. Есть класс App, есть Engine. По заданию в классе App - тупо список игр и вызов другого класса с логикой. В классе Engine должна быть общая логика игр.

В каждой игре 3 раунда. Последовательность происходящего:

  • приветствие(общее)
  • объяснение сути игры(разное для каждой игры)
  • вопрос(математическое выражение/число - всегда разное)
  • два варианта исхода (положительный, если ответ пользователя совпал с заранее вычисленным результатом / отрицательный, если пользователь ввел неверный ответ)

Пока код Engine выглядит так и не работает:

public class Engine {
    public static String question;
    public static String result;
    public static String greeting;

    public static int index = 0; //нужны для вычислений в классах
    public static int sum = 0; //нужны для вычислений в классах

    public static Random random = new Random();
    public static Scanner scanner = new Scanner(System.in);
    public static String userName;
    public static String wrong = " is wrong answer ;(. Correct answer was ";
    public static String wrong2 = "Let's try again, ";
    public static int raunds = 0; //нужны для вычислений в классах

    public static void comunication() {

        System.out.println("");
        System.out.println("Welcome to the Brain Games!");
        System.out.print("May I have your name? ");
        Scanner scanner = new Scanner(System.in);
        String userName = scanner.next();
        System.out.println("Hello, " + userName + "!");

        if (App.choise().equals("2")) {  //пытаюсь сослаться на метод, где я сначала задавал переменную
            greeting = ParityCheck.greeting; //ссылка на отдельные значения в нужные классы, которые выведены в отдельные методы и посчитаны
            question = Integer.toString(ParityCheck.question());
            result = ParityCheck.result();
        }
        if (App.choise().equals("3")) {
            Calculator.calculate(); //здесь и ниже в усл. конструкциях - старый синтаксис, еще не переделанный
        }
        if (App.choise().equals("4")) {
            GCD.divide();
        }
        if (App.choise().equals("5")) {
            Progression.progression();
        }
        if (App.choise().equals("6")) {
            Prime.prime();
        }

        System.out.println(greeting);

        for (var i = 0; i < 3; i++) {
            System.out.println("Question: " + question);

            System.out.print("Your answer: ");
            String answer = scanner.next();

            if (answer.equals(result)) {
                System.out.println("Correct!");
            } else {
                System.out.println("'" + answer + "'" + wrong + "'" + result + "'");
                System.out.println(wrong2 + userName);
                break;
            }
            raunds++;
        }
        if (Engine.raunds == 3) {
            System.out.println("Congratulations, " + userName + "!");
        }
    }
}

Ниже код класса App:

public class App {
    static Scanner scan = new Scanner(System.in);

    public static String choise() {
        String userChoice = scan.next();
        return userChoice;
    }
    public static void main(String[] args) {

        System.out.println("Please enter the game number and press Enter.");
        System.out.println("1 - Greet");
        System.out.println("2 - Even");
        System.out.println("3 - Calc");
        System.out.println("4 - GCD");
        System.out.println("5 - Progression");
        System.out.println("6 - Prime");
        System.out.println("0 - Exit");
        System.out.print("Your choice: ");

        choise();


        Engine.comunication();
    }
}

Код работает корректно до момента с выводом System.out.println(greeting). Это программа уже не делает. Понимаю, что видимо в переменной userChoice в методе choise() не остается значений пользователя, что он ввел и поэтому программа не может двигаться дальше, но как сделать так, чтоб оставались значения? Так как мне очень нужны эти значения для работы условных конструкций и правильного вызова нужных значений из разных классов

Важно! Мне необходимо реализовать эту логику "в лоб", используя только статические методы (без абстракций, интерфейсой, ООП и пр.) Если не запрещено правилами, я приложу ссылку на свой гитхаб, там старая версия игры, когда класс App ссылается на каждую игру и в каждом игре прописана вся логика. Сейчас я хочу общую логику вынести в класс Engine, оставив в классах игр только вычисления. https://github.com/DEGTEVUWU/java-project-61


Ответы (1 шт):

Автор решения: Швеев Алексей

Если я правильно понял, то вам надо прописать разную логику для разных игр. Почему бы не использовать для этого ООП?

Предлагаю следующую архитектуру:

  • Класс App управляет общим интерфейсом, выбором игры и т. п.
  • Класс Engine имеет общие методы для каждой игры, которые переопределяются в дочерних классах (которые являются классами самих игр)

Поскольку все игры состоят из определённого числа шагов, то логику игры можно оставить внутри класса App, а в Engine хранить только информацию об игре и метод для проверки правильности ответа.

Реализуем класс Engine на основе указанных этапов:

// Так как Engine является лишь базовым классом
// сделаем его абстрактным, что бы его нельзя было создавать
abstract class Engine {
    // Имя игры (по умолчанию - имя класса)
    public String GetName() {return this.getClass().getSimpleName();}
    
    // Описание игры
    public abstract String GetDescription();
    
    // Генерация и сохранение вопроса и ответа
    public abstract void GenerateQuestion();
    public abstract String GetQuestion();
    public abstract boolean IsAnswerCorrect(String answer);
    
    // Рандом (на всякий случай)
    final Random random = new Random();
}

Для примера реализуем одну игру - калькулятор:

class Calculator extends Engine {
    @Override
    public String GetDescription() {
        return "This is a calculator game. I'm write mathematical example and you provide answer.";
    }
    
    int num1 = 0;
    int num2 = 0;
    
    @Override
    public void GenerateQuestion(){
        num1 = random.nextInt(10);
        num2 = random.nextInt(10);
    }
    
    @Override 
    public String GetQuestion(){
        return num1 + " + " + num2 + " = ";
    }
    
    @Override
    public boolean IsAnswerCorrect(String answer){
        return answer.equals(Integer.toString(num1 + num2));
    }
}

Теперь создадим класс App который будет хранить список игр

class App {
    // Инициализируем App и запускаем Start()
    public static void main(String[] args){
        App app = new App();
        app.Start();
    }
    

    public ArrayList<Engine> games = new ArrayList<Engine>();

    public void Start(){
        games.add(new Calculator());
    }
}

Ну и реализовываем логику этапов игры:

class App {
    // Инициализируем App и запускаем Start()
    public static void main(String[] args){
        App app = new App();
        app.Start();
    }
    
    // Некоторые константы:
    final String sucAns = "Good job!";
    final String wrongAns = "Wrong... Try again next time!";
    
    
    public ArrayList<Engine> games = new ArrayList<Engine>();
    
    public void Start(){
        Scanner in = new Scanner(System.in);
        
        games.add(new Calculator());
        
        // Выводим список игр и их индекс+1 (что бы отсчёт начинался с 1)
        System.out.println("Please select game: ");
        for (int i = 0; i < games.size(); i++){
            System.out.println((i+1) + " - " + games.get(i).GetName());
        }
        System.out.println("0 - Exit");
        
        int gameIndex = in.nextInt();
        if (gameIndex == 0) {return;}
        
        // Так как отсчёт игр начинался с одного
        // Вычитаем единицу
        Engine game = games.get(gameIndex-1);
        
        // Выводим название и описание игры
        System.out.println(game.GetName());
        System.out.println(game.GetDescription());
        
        // Генерируем вопрос
        game.GenerateQuestion();
        
        // Выводим вопрос
        System.out.println("Question: " + game.GetQuestion());
        
        // Запрашиваем ответ от пользователя
        String ans = in.next();
        
        // Проверяем, правильный ли ответ
        boolean isCorrect = game.IsAnswerCorrect(ans);
        
        if (isCorrect) { System.out.println(sucAns); }
        else { System.out.println(wrongAns); }
    }
}

Полный код можно запустить тут. Все комментарии там есть.

Надеюсь на этой основе вы сможете решить данную задачу более элегантным способом)

→ Ссылка