循环通过父/子结构

时间:2015-11-13 14:20:21

标签: c# .net

我正在制作一款游戏,可以专门针对每个暴徒的肢体,所以你可以瞄准头部,腿部......

我有这个构造函数:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Legs = new List<Leg> { new Leg(), new Leg() };
    this.Torso = new Torso();
    this.Arms = new List<Arm> { new Arm(), new Arm() };
    this.Heads = new List<Head>
    {
        new Head
        {
            Ears = new List<Ear> { new Ear(), new Ear() },
            Eyes = new List<Eye> { new Eye(), new Eye() }
        }
    };
}

所有这些肢体都继承自界面ILimb

能够遍历所有肢体的最佳方法是什么,包括孩子(如果适用)?

我可以添加protected List<ILimb> { get; set; },然后添加每个,但这是多余的。

有任何改进的想法或建议吗?

3 个答案:

答案 0 :(得分:3)

最好的方法是改为使用这种结构:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs = new List<ILimb>();
    this.Limbs.Add(new Legs() { Limbs = new List<Limb>() { new Leg(), new Leg() });
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arms() { Limbs = new List<Limb>() { new Arm(), new Arm() });
    this.Limbs.Add(new Heads() { Limbs = new List<Limb>() { new Head() { Limbs = new List<Limb>() .... , ... });
}

你可以整理代码,但基本上它应该有一个肢体的集合,肢体应该有四肢的集合,以便你可以有头&gt;耳朵&gt;耳朵或你想要的任何层次结构。

然后在你的ILimb界面中,给它一个Limbs属性

public interface ILimb
{
    List<ILimb> Limbs { get; set; }
    List<ILimb> GetAllLimbs { get; }
}

使用此方法创建一个抽象基类Limb:

public virtual GetAllLimbs()
{
// pseudocode: something like this (basically recurse through the children)
return this.Limbs().foreach (c => c.GetAllLimbs()).union(this.Limbs());
}

然后它可以轻松地爬下层次结构并检索每个肢体。

所以你可以做到

myHumanoid.GetAllLimbs().Where(c => c is Arm).TakeDamage(5);

例如。

答案 1 :(得分:1)

您有所有对象的自定义模型,除了一个...模型的自定义集合List<T>是一个良好的开端,但它没有您正在寻找的功能。您尝试投入Humanoid的功能,但并不属于那里。

实施以下内容:

public class LimbList<T> : IList<T> where T : ILimb
{
    // implement IList<T> here
}

在这里,您将包括四肢集合的业务逻辑。例如:

  • 如果支持集合中已有2个Arm个对象,则在使用.Add()对象调用Arm时抛出异常。
  • 如果支持集合中已有1个Torso对象,则在使用.Add()对象调用Torso时抛出异常。

Humanoid将拥有LimbList<ILimb>属性:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Head
        {
            // as an added exercise, how would you extend this concept to the Head object?
        });
}

你可以轻松地遍历该列表:

foreach (var limb in this.Limbs)

基本上,这里的要点是对象集合本身就是一个对象,其自定义逻辑与任何其他对象一样。将对象逻辑放在对象中,将集合逻辑放入集合中。没有规则说您必须使用框架中的内置集合。

答案 2 :(得分:0)

给定legs列表和arms列表,您可以执行以下操作:

IEnumerable<ILimb> limbs = ((IEnumerable<ILimb>)arms).Concat(legs);

然后迭代它:

foreach (var limb in limbs) 
{
    // limb is an ILimb and you can access anything in that interface 
    // for each limb
}

另一种方法是你可以像Humanoid这样添加一个方法:

public IEnumerable<ILimb> GetLimbs() 
{
    foreach (var a in Arms)
    {
        yield return a;
    }
    foreach (var l in Legs)
    {
        yield return l;
    }
}

然后你可以这样做:

foreach(var limb in someHumanoid.GetLimbs()) 
{

}