Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Class 我应该如何设计具有大量属性的游戏角色类?_Class_Attributes - Fatal编程技术网

Class 我应该如何设计具有大量属性的游戏角色类?

Class 我应该如何设计具有大量属性的游戏角色类?,class,attributes,Class,Attributes,我是一名学生,目前正在学习Java,并试图用它编写一个基于文本的小型RPG游戏。我在游戏设计中遇到的第一个问题是“角色”类,它代表所有可玩的英雄和敌人角色,现在由我自己实现如下: class RPGActor { private String name; private int HP; // hit points private int MP; // mana private int AP; // attack private int DP; // defense ... // follow

我是一名学生,目前正在学习Java,并试图用它编写一个基于文本的小型RPG游戏。我在游戏设计中遇到的第一个问题是“角色”类,它代表所有可玩的英雄和敌人角色,现在由我自己实现如下:

class RPGActor {

private String name;
private int HP; // hit points
private int MP; // mana
private int AP; // attack
private int DP; // defense

... // followed by tens of other attributes. 

public Actor(int actorID)
{
    ... // Reads all attributes from a file based on the 'actorID'.
}
public void printStatus()
{
    System.out.println(name);
    System.out.println("HP :" + HP); 
    System.out.println("MP :" + MP); 
    ... // And print all the attributes one by one.
}
public void setHP(int newHP)
{
    HP = newHP;
}
public int getHP()
{
    return HP;
}
public void setMP(...)
{
    ...
}
// And tens of accessors and mutators for each attribute
}
我看到这个设计的问题是有太多的东西需要手工编码:类中有20-30个属性,需要为每个属性实现一个单独的访问器/变异器。用于显示英雄当前状态的函数printStatus必须单独输出每个属性,即使输出的每一行都遵循完全相同的格式。这使得类定义冗长乏味

另外,如果以后我想在游戏中再添加一个属性,那么我必须记住修改“printStatus”,并为它添加一对访问器/变异器

所以我的问题是:有没有一种方法可以设计类,这样我就可以使用一对set/get函数来设置所有属性。比如:

public void set(String attribName, int attribVal)
{
...
}
并按如下方式迭代打印属性:

public void printStatus()
{
    System.out.println(name);
    for (...)
        System.out.println(curAttribName + ": " + curAttribVal);
}
class RPGActor {
    private String name;
    private int HP; // hit points
    private int MP; // mana
    private int AP; // attack
    private int DP; // defense
    // ... followed by tens of other attributes. 

    private Map<String, Object> attributes = new HashMap<String, Object>();    

    public RPGActor(int actorID) {
        // ... Reads all attributes from a file based on the 'actorID'.
    }

    public void attacks(RPGActor defender) {
        defender.defend(this.getAttack());
    }

    public void defend(Attack attack) {
        switch (attack.getType()) {
            case PHYSICAL:
                // This actor is resistant against physical attacks.
                return;
            case MAGICAL:
                this.HP = this.HP - attack.getStrength();
                break;
        }
    }

    public void castSpell(Spell spell, Set<Target> targets) {
        // targets could be other actors, equipment or chickens dependent on the spell
        // ...
    }

}

多谢各位

我将向您展示一个解决方案,用一个方法设置所有属性,但您不应该使用它,我将在后面告诉您原因

class RPGActor {
    private static final String NAME = "Name";
    private static final String HP = "HP";
    private static final String MP = "MP";
    private static final String AP = "AP";
    private static final String DP = "DP";
    // ... followed by tens of other attributes. 

    private Map<String, Object> attributes = new HashMap<String, Object>();    

    public RPGActor(int actorID) {
        this.attributes.put(NAME, nameFromFile);
        // ... Reads all attributes from a file based on the 'actorID'.
    }

    public void setAttribute(String attributeName, Object value) {
        this.attributes.put(attributeName, value);
    }

    public int getAttribute(String attributeName) {
        return this.attributes.get(attributeName);
    }
}
类RPGActor{
私有静态最终字符串NAME=“NAME”;
私有静态最终字符串HP=“HP”;
私有静态最终字符串MP=“MP”;
私有静态最终字符串AP=“AP”;
私有静态最终字符串DP=“DP”;
//…然后是数十个其他属性。
私有映射属性=新HashMap();
公共RPGActor(int actorID){
this.attributes.put(NAME,nameFromFile);
//…基于“actorID”从文件中读取所有属性。
}
public void setAttribute(字符串attributeName,对象值){
this.attributes.put(attributeName,value);
}
public int getAttribute(字符串attributeName){
返回this.attributes.get(attributeName);
}
}
这有几个缺点:

  • 没有设置特定属性的代码完成
  • 可读性较差

更好:

尽管您使用的是类和对象,但这并不是很好。尤其是你违反了法律

您不应该从类本身之外显式设置HP。仅在少数需要的用例中。相反,你应该考虑演员真正做什么:攻击、防守、施法

因此,它应该更像这样:

public void printStatus()
{
    System.out.println(name);
    for (...)
        System.out.println(curAttribName + ": " + curAttribVal);
}
class RPGActor {
    private String name;
    private int HP; // hit points
    private int MP; // mana
    private int AP; // attack
    private int DP; // defense
    // ... followed by tens of other attributes. 

    private Map<String, Object> attributes = new HashMap<String, Object>();    

    public RPGActor(int actorID) {
        // ... Reads all attributes from a file based on the 'actorID'.
    }

    public void attacks(RPGActor defender) {
        defender.defend(this.getAttack());
    }

    public void defend(Attack attack) {
        switch (attack.getType()) {
            case PHYSICAL:
                // This actor is resistant against physical attacks.
                return;
            case MAGICAL:
                this.HP = this.HP - attack.getStrength();
                break;
        }
    }

    public void castSpell(Spell spell, Set<Target> targets) {
        // targets could be other actors, equipment or chickens dependent on the spell
        // ...
    }

}
类RPGActor{
私有字符串名称;
private int HP;//生命值
私有int MP;//法力
私有int-AP;//攻击
私有int-DP;//防御
//…然后是数十个其他属性。
私有映射属性=新HashMap();
公共RPGActor(int actorID){
//…基于“actorID”从文件中读取所有属性。
}
公共空间攻击(RPGActor defender){
defender.defect(this.getAttack());
}
公共虚空防御(攻击){
开关(attack.getType()){
个案物理:
//这个演员能抵抗物理攻击。
返回;
案例:
this.HP=this.HP-attack.getStrength();
打破
}
}
公共虚空施法(法术,设定目标){
//目标可能是其他演员、装备或依赖于咒语的小鸡
// ...
}
}

使用或更高级的设计模式,例如,您可以让每个参与者对攻击做出不同的反应。

让我想起了Zork……非常感谢您的回答!它被设计成这样的原因是,实际上还有另一个类,叫做地下城主,处理所有的攻击/防御/施法事件。例如,当攻击发生时,地下城主会决定攻击者/防御者是谁以及他应该损失多少生命(防御者不知道他为什么会损失生命)。我相信你的第二个解决方案确实是一个更优雅的设计。但是你能详细解释一下为什么原始设计违反了封装吗?我认为封装意味着属性对用户是不可见的,这是由“私有”保证的。你的地下城主人实际上是一个。它集中了太多关于攻击、防御、法术、生物等方面的知识。。。在我看来,防御者不知道他为什么会失去生命是一种误解,因为防御者可能拥有护甲或抵抗力,因此生命损失取决于个体生物,因此应由防御者处理(但也可以设计不同,这不是唯一的解决方案)封装并不像将属性私有化那么简单,但它是一种共识,如果我开始编程时也这么认为的话。封装范式是将逻辑和属性集中在一个地方,并尽可能限制外部访问。相比之下,将属性设置为HP私有,但提供getter和setter以无任何限制地对其进行操作,并不封装属性或逻辑,这只是访问属性的另一种方式。另一个重要方面是可维护性。如果你决定改变生物保护自己的方式,我认为RPGActor必须改变。但也许我得换个角色扮演者和地下城主。这在一开始并不是问题,但随着您添加更多功能,它逐渐变得更加混乱。你应该读一读这本书。有很多关于面向对象编程的好书,但大多数范例在维基百科上都有很好的描述。花点时间通读重要的部分。非常感谢你的解释。它澄清了很多事情。我在学校还没有真正学到任何关于设计模式的深刻知识,所以RPGActor/undgeonmaster设计是最好的