Как упростить этот код или улучшить дизайн? - PullRequest
2 голосов
/ 22 мая 2010

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

Легко = 0 Нормально = 1 Сложно = 2

Итак, мой код будет выглядеть примерно так:

switch(gameMode){

case 0:
//easy
break;

case 1:
//normal
break;

case 3:
//difficult
break;

}

Но я думаю, что этоВозникают некоторые проблемы, если я добавляю новый режим, например, «Extreme», мне нужно добавить случай 4 ... ... кажется, это не дизайн GD.

Итак, я думаю сделатьОбъект gameMode, а другой gameMode - это подкласс суперкласса gameMode.Объект gameMode выглядит примерно так:

    class GameMode{
    int maxEnemyNumber;
    int maxWeaponNumber;
      public static GameMode init(){
         GameMode gm = GameMode();
         gm.maxEnemyNumber = 0;
         gm.maxWeaponNumber = 0;
         return gm;
      }    

    }

class EasyMode extends GameMode{

      public static GameMode init(){
         GameMode gm = super.init();
         gm.maxEnemyNumber = 10;
         gm.maxWeaponNumber = 100;
         return gm;
      }    
}


class NormalMode extends GameMode{

      public static GameMode init(){
         GameMode gm = super.init();
         gm.maxEnemyNumber = 20;
         gm.maxWeaponNumber = 80;
         return gm;
      }    
}

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

Ответы [ 8 ]

2 голосов
/ 22 мая 2010

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

Например, вы можете написать это в C:

typedef enum difficulties {
  DIFFICULTY_EASY,
  DIFFICULTY_MEDIUM,
  DIFFICULTY_HARD
} difficulties;

struct {
  int max_enemies;
  int max_weapons;
} difficulty_settings[] = {
  {10, 4},
  {20, 5},
  {30, 6}
};

А если вы хотите прочитать конкретную настройку, например, max_enemies для простого уровня, тогда вы можете написать difficulty_settings[DIFFICULTY_EASY].max_enemies

Легко добавить больше конфигурации (либо больше параметров, либо больше уровней сложности), расширивстол.

1 голос
/ 22 мая 2010

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

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

Например, первая реализация может быть что-то вроде

enum mode {
    MODE_EASY = 0,
    MODE_NORMAL = 1,
    MODE_DIFFICULT = 2,
};

class gameSettings {
    public gameSettings(mode GameMode) {
        m_mode = GameMode;
    }

    public int getMaxWeaponNumber() {
        int maxWeaponNumber;
        switch(m_mode) {
            case EASY_MODE:
                maxWeaponNumber = 100;
                break;

            // Other mode settings.               
         }

         return maxWeaponNumber;
    }

    // Other game settings....

    private mode m_mode;

}

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

1 голос
/ 22 мая 2010

Я не знаю java (как выглядят ваши примеры), поэтому я представляю свои идеи на простом C #.

Вот идея. Вместо этого используйте свой игровой режим в качестве флага. Если вы начинаете с:

[Flags]
enum GameModes
{
    Unknown = 0,
    ModeA = 1,
    ModeB = 2,
    ModeC = 4,
}

Теперь у вас есть уровни 1-7.

GameModes Difficulty = GameModes.ModeA | GameModes.ModeB;    // difficulty = 3
GameModes Difficulty = GameModes.ModeB;    // difficulty = 2

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

0 голосов
/ 22 мая 2010

Используйте шаблон стратегии .

В терминах Java:

public interface Strategy {
    void execute();
}

public class SomeStrategy implements Strategy {
    public void execute() {
        System.out.println("Some logic.");
    }
}

который вы используете следующим образом:

Map<String, Strategy> strategies = new HashMap<String, Strategy>();
strategies.put("strategyName1", new SomeStrategy1());
strategies.put("strategyName2", new SomeStrategy2());
strategies.put("strategyName3", new SomeStrategy3());

// ...

strategies.get(s).execute();
0 голосов
/ 22 мая 2010

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

Единственный случай, когда я могу подумать о том, что вам не нужно добавлять код, если вы добавляете другой режим, это если вы генерируете параметры игры из значения gameMode.

Например: maxenemy = 5 * gameMode;

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

0 голосов
/ 22 мая 2010

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

0 голосов
/ 22 мая 2010

Помимо некоторых проблем с синтаксисом, я думаю, что вы на правильном пути.Я не думаю, что вам нужно беспокоиться о памяти, учитывая, что, вероятно, есть только один режим одновременно.Это форма стратегии .Вы можете расширить его, чтобы режимы делали больше.Например, вместо того, чтобы просто хранить константы, возможно, мог бы быть метод generateEnemies, который фактически создает набор или список врагов.Это перемещает больше стратегии в объект режима.Разумные значения по умолчанию в суперклассе могут помочь избежать избыточного кода.

0 голосов
/ 22 мая 2010

Используйте подход переключения в конструкторе вашего класса GameMode.

...