【问题标题】:In a game programming project, how do I handle multiple items with multiple instances?在游戏编程项目中,如何处理具有多个实例的多个项目?
【发布时间】:2017-02-19 07:02:47
【问题描述】:

假设我有一个包含多种武器的 2 人游戏。在游戏开始时,玩家可以选择自己的武器并将其装备给自己的角色。所以如果现在,我有以下代码来实现上述场景:

public class Weapon {
    private String name;
    private int attackPoints;
    private int effectivity = 100;

    public Weapon(String name, int attackPoints) {
        this.name = name;
        this.attackPoints = attackPoints;
    }
    // ...
}

public class Character {
    private String name;
    private Weapon weapon;

    public Character(String name, Weapon weapon) {
        this.name = name;
        this.weapon = weapon;
    }
    // ...
}

public class Game {
    Scanner scanner = new Scanner(System.in);
    public void createCharacter() {
        String namePlayer = "Knight";
        String nameOpponent = "Thief";

        //Weapon Menu
        System.out.println("Select weapon");
        System.out.println("1. Dagger - Attack: 10");
        System.out.println("2. Sword - Attack 20");

        Character player;
        Character opponent;
        int choice = scanner.nextInt();

        //Weapon assignment
        switch (choice) {
        case 1:
            player = new Character(name, new Weapon("Dagger", 10));
            break;
        case 2:
            player = new Character(name, new Weapon("Sword", 20));
            break;
        }
    }
}

改写问题

我担心的是,如果我必须添加一个额外的武器,例如“15 伤害的斧头”,那么我必须修改武器菜单,同时在我的开关中添加一个额外的箱子陈述。是否有可能我只需要修改某种列表,它会处理可供玩家选择的武器列表,同时使武器的实例对玩家和对手角色?

老问题

我担心的是,每次我有了新武器,我都必须修改武器菜单,同时修改武器分配部分。有没有更好的方法来实现它?

【问题讨论】:

    标签: java oop design-patterns object-oriented-analysis


    【解决方案1】:

    你基本上需要一个WeaponFactory,它会知道所有可用的Weapons。该工厂还可以根据用户输入创建特定武器的新实例。这样,我认为,您将实现所需的一切

    • 所有武器都在一个地方创建,
    • 添加新的需要更改单个类。

    这是一个简化的例子。

    public static class WeaponFactory {
        public List<Weapon> availableWeapons() {
            return Arrays.asList(new Dagger(), new Rifle());
        }
    
        public Weapon create(int type) {
            return availableWeapons().get(type);
        }
    }
    
    public interface Weapon {
        public abstract double attack();
        public abstract String name();
    }
    
    public static abstract class WeaponAdapter implements Weapon {
        @Override public String toString() {  return name() + " - " + attack(); }
    }
    
    public static class Dagger extends WeaponAdapter {
        @Override public double attack() { return 10; }
        @Override public String name() { return "Dagger"; }
    }
    
    public static class Rifle extends WeaponAdapter {
        @Override public double attack() { return 80; }
        @Override public String name() { return "Rifle"; }
    }
    

    效率有点低,因为实际上并不需要创建Weapons 的新实例以便在Menu 中显示它们,但我认为对于这个示例来说已经足够了。

    为了缓解这种情况,您可以使用一些反射或使用枚举。你基本上需要的是一个函数,它会根据它的类型创建一个 Weapon,所以它可能有点像

    List<Class<? extends Weapon>> weapons = Arrays.asList(Dagger.class, Rifle.class);
    
    public Weapon create(Class<Weapon> weaponType) {
        try {
            return weaponType.newInstance();
        } catch (InstantiationException | IllegalAccessException ex) {
            throw new RuntimeException("Not possible");
        }
    }
    

    同样,所有这些都是WeaponFactory 的一部分,这是所有Weapons 相关的一个地方。

    【讨论】:

      【解决方案2】:

      是的,你可以..

      ..创建每个武器作为对象将它添加到一个数组(或列表等),所以你不必编码

      System.out.println("Select weapon");
      System.out.println("1. Dagger - Attack: 10");
      System.out.println("2. Sword - Attack 20");
      

      你可以去

          Weapon[] weapons = new Weapon[2];
          weapons[0] = new Weapon ("Dagger",10);
          weapons[1] = new Weapon ("Sword",20);
          for (int i = 0; i < weapons.length; i++) {
              System.out.println(i+1+". "weapons[i].getName+" - "+weapons[i].getAttackPoints);
          }
          int choice = scanner.nextInt();
          player = new Character(namePlayer, weapons[choice-1]);
      

      只是为了照顾

      • Weapon 类具有获取名称和攻击点的方法
      • 数组以索引 0 开始,如下所示

      【讨论】:

      • 感谢您的回复,但如果我这样做了,那么在玩家角色中找到的匕首实例也会在对手角色中找到。有没有办法让两种角色的武器实例不同?
      • @asker 是的,您是对的,那么实例将是相同的,但问题是为什么您需要不同的实例,因为即使玩家或对手拥有剑,剑也是剑,所以武器类本身存在,没有直接链接到角色。如果您需要不同的实例,您可以使用 clone 方法,但在我看来,这更像是一个设计主题 - 所以回来为什么认为您必须使用不同的实例?
      • 假设武器可以自定义,就像玩家使用它时会损坏一样。所以在这种情况下,实例需要不同。我也问过我的一些同事,他们也建议我实现一个克隆方法。但这是正确的方法还是有更好的方法?
      • 我同意,所以我们将深入了解面向对象设计的更多细节——当我想象应该如何完成时,会有两颗心在跳动 *1 一个说做一个好的架构 *2 另一个一个让它实用 1 我会说让它接近现实世界中的东西,这意味着创建一个管理所有可用武器的类,比如武器商店,所以你可以像你说的那样出售二手武器
      • 你可以浏览所有现有的,当你订购武器时,你会收到一个独特的武器,而不是目录中的一个 2 我会说只做你需要的事情,所以克隆它可能是最好的总是介于两者之间。但这取决于你的想法和游戏的意图:-)
      【解决方案3】:

      你的角色类可以有一个这样的武器列表:

      public class Character {
      private String name;
      private List<Weapon> weapons = new ArrayList<Weapon>();
      
       public Character(String name) { //keep this constructor. I know I have omitted weapons variable from this constructor.
          this.name = name;        
      }
      // down below you have getters and setters for name and weapons
      }
      

      然后当你初始化一个新角色时,这样做:

      Character player1;
      ...
      
      switch (choice) {
          case 1:
              Weapon w = new Weapon("Dagger", 10));
              player = new Character(name);
              player.getWeapons().add(w);
              break;
      

      【讨论】:

      • 感谢您的回复,我的问题一定是含糊其辞。我担心的是,如果我必须添加额外的武器,例如说“15 伤害的斧头”,那么我必须修改武器菜单,同时在我的 switch 语句中添加一个额外的案例。有没有可能我只需要修改某种列表,它会处理可供玩家选择的武器列表,同时使玩家的实例与对手角色不同?
      • 我明白了.. 所以我真的必须在菜单部分添加一个额外的武器。像这样://武器菜单 System.out.println("选择武器"); System.out.println("1.匕首-攻击:10"); System.out.println("2.剑-攻击20"); System.out.println("3.斧头-攻击15");
      • @asker 我仍然无法理解您的问题。你能重复一下这个问题吗?谢谢
      • 鉴于在游戏开始时,玩家会选择自己喜欢的武器。假设在游戏中期,每个角色的武器的某些属性会发生变化,那么我们需要武器具有不同的实例。在当前的实现中,如果我要在菜单中添加额外的武器,我必须修改菜单列表,同时修改玩家和对手武器分配的 switch 语句。所以我的问题是,有没有更好的方法来实现它?谢谢。
      • @asker 好的,我已经编辑了我的答案。我想我现在明白你在说什么了。如果这不是您要找的,那么我将需要查看完整的代码,并且我需要使用它直到我做对为止。然后我可以告诉你答案,你就能明白该怎么做。谢谢
      猜你喜欢
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多