3

我有一个类的已声明实体,并且想为其分配不同的预制模板,而模板却永远不会改变。使用 const 似乎并不能解决问题。

例子:

Weapon w1;
w1 = Sword; // premade weapon.
w1.reducedamage(1); // for example a debuff

在这种情况下,预制武器的伤害会降低,并且不再可用作模板。这个问题在敌人身上变得更加深刻。

例子:

Enemy enemy;
enemy = enemies[r] // r being a randomly generated integer and enemies a list of enemy templates
Fight(player,enemy); // this method would resolve a fight between the two entities of the type Character.

这个问题在玩家类中是不可见的,因为玩家是通过所有游戏方法传递的单个引用——因为只有一个玩家。每次玩家战斗时,敌人的模板都会被“损坏”。

通常,我将如何创建始终按值传递的模板或类/结构,这意味着第一个类的属性将具有与第二个相同的值,而两个类之间没有任何关系?

我获得的唯一成功是创建了一个方法,该方法手动将每个具有模板的类的每个属性复制到同一类的另一个实体上;但这非常不切实际,因为每当添加新类或更改旧类时,它都需要不断升级。

4

6 回答 6

2

我肯定错过了什么。这似乎是一个相当简单的问题,可以通过继承轻松解决,也许与某种工厂结合使用。首先,您不想使用对单个实例的引用,您希望每次都创建一个新实例,因此它是一个唯一的对象。我更喜欢类而不是结构,但您也可以轻松创建一个新结构。您可以使用工厂创建具有预定义值的对象的各种预配置实例。例如,达摩克利斯之剑或命运之剑。

public static class WeaponFactory
{
       public static Weapon CreateSword(SwordType type)
       {
            var sword = new Sword(); // plain, old default sword

            // override properties based on type
            switch (type)
            {
                case SwordType.SwordOfDamocles:
                    sword.FallTime = GetRandomFutureTime();
                    break;
                case SwordType.SwordOfDestiny:
                    sword.Invincible = true;
                    break;
                ...
            }

            return sword;
        }

        ...
}

替代使用操作

public static class WeaponFactory
{
      public static Weapon Create<T>(Action<T> decorator) where T : IWeapon, new()
      {
           var weapon = new T();
           decorator(weapon);
           return weapon;
      }

      public static void SwordOfDamocles(Sword sword)
      {
           sword.FallTime = GetRandomFallTime();
      }

      public static void SwordOfDestiny(Sword sword)
      {
           sword.Invincible = true;
      }
}

var weapon = WeaponFactory.Create(WeaponFactory.SwordOfDamocles);
于 2012-12-24T17:25:56.090 回答
1

你想要的是对象克隆。您可以通过ICloneable接口[1]实现它。这需要您实现自己的克隆机制——您必须完成繁重的工作。

但是,您可能应该做的只是让构造函数接受一个表示您想要的模板的参数,然后根据该模板填充相关对象的属性。当我想用一组基本值制作重复的东西时,这就是我要走的方向。

于 2012-12-24T17:16:52.833 回答
0

您可以进行实际复制(例如,在http://msdn.microsoft.com/en-us/library/ms173116(v=vs.80).aspx中提供复制构造函数),但我最常看到的是这种情况是工厂模式,例如Weapon w1 = Weapon.CreateSword();Enemy e=Enemy.CreateEnemyOfType(r);

于 2012-12-24T17:19:06.023 回答
0

您可以构建一个方法以将通用集合或数组中的多个敌人返回到您的敌人类中。就像是:

公共共享函数 getEnemies(num 为整数,类型为字符串)作为列表(来自 clsEnemy) 将敌人组作为列表(来自 clsEnemy)

for i = 0 to num - 1 dim thisEnemy as new clsEnemy(type)enemyGroup.add(thisEnemy) next

返回enemyGroup结束函数

于 2012-12-24T17:23:28.120 回答
0

与复制对象以实现某种“应用对象”模式相反,最好记住改变的不是剑“基础物品”,而是玩家携带的物品。

例如,一把给定的剑,比如“生锈的旧剑”,其基础伤害始终为 50。现在,如果有人对其应用“旧的东西变得更好的魔法”,那么受到更多伤害的并不是“生锈的旧剑”:如果其他没有这种魔法的玩家捡起该物品,它会恢复到 50 的基础伤害。

因此,如果您实现某种EquippedWeapon(甚至EquippedItem)类,您可以让您的玩家装备武器并为其赋予扩展属性。像这样声明剑:

interface IWeapon
{
    int Damage { get; }
}

class Sword : IWeapon
{
    public int Damage { get; private set; }

    public Sword()
    {
        this.Damage = 50;
    }
}

现在我们有一把基础伤害为 50 的剑。现在让玩家携带这把剑:

interface IDamageModifier
{
    int Damage { get; set; }
}

class EquippedWeapon : IWeapon
{
    public int Damage
    {
        get
        {
            return CalculateActualDamage();
        }
    }

    public List<IDamageModifier> DamageModifiers { get; set; }  
    private IWeapon _baseWeapon = null;

    public EquippedWeapon(IWeapon weapon)
    {
        _baseWeapon = weapon;       
    }

    private int CalulcateActualDamage()
    {
        int baseDamage = _baseWeapon.Damage;

        foreach (var modifier in this.DamageModifiers)
        {
            baseDamage += modifier.Damage;
        }

        return baseDamage;
    }
}

武器包含一系列活动修饰符,这些修饰符会影响携带物品的伤害,但不会影响基础物品。Sword通过这种方式,您可以与许多(非)可玩角色共享一个实例。

现在,如果玩家受到攻击并且该攻击具有伤害效果,您只需将其应用于玩家携带的物品,因此该玩家的每次连续攻击都会应用这些效果:

class Player
{
    public EquippedWeapon PrimaryWeapon { get; set; }

    public Player()
    {
        this.PrimaryWeapon = new EquippedWeapon(new Sword());
    }

    public void UnderAttack(Attack attack)
    {
        // TODO: implement

        if (attack.Buffs...)
        {
            this.EquippedWeapon.DamageModifiers.Add(attack.Buffs);
        }
    }
}
于 2012-12-24T17:28:06.247 回答
0

我写了一个答案直接回答你的问题。但是现在我看到您想要的只是创建相同但未链接的项目。

当您创建实例时,无论如何都会发生这种情况。你不必做任何事情。

如果你有:

class Class1
{
    public int i;
}

然后:

Class1 c1 = new Class1() { i = 1 };
Class1 c2 = new Class1() { i = 2 };
Text = c1.i.ToString();

打印“1”,而不是“2”。

如果你的意思是你想要一个带有子类“朋友”和“敌人”的“玩家”类 - 这就是继承的目的:

class Player
{

}

class Friend : Player
{

}
class Foe : Player
{

}

编辑:

也许这会使任务更容易:(“复制”方法)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        Class1 c1 = new Class1() { i = 1, j = 2 };
        Class1 c2 = Duplicate(c1);
        c1.i = 3;
        Text = c2.i.ToString();//Prints "1";
    }

    public Class1 Duplicate(Class1 c)//Duplicates all public properties.
    {
        Class1 result = new Class1();
        PropertyInfo[] infos = typeof(Class1).GetProperties();
        foreach (PropertyInfo info in infos)
            info.SetValue(result, info.GetValue(c, null), null);
        return result;
    }
}

public class Class1
{
    public int i { get; set; }
    public int j { get; set; }
}
于 2012-12-24T17:40:23.297 回答