2015-11-13 5 views
0

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

У меня есть это конструктор:

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; }, а затем добавить каждый, но это избыточно.

Любые идеи или предложения по улучшению?

+1

Я бы использовал библиотеку 'System.Reflection' с пользовательскими атрибутами. пометьте свои конечности некоторым атрибутом, затем используйте библиотеку отражения, чтобы получить свойства Humanoid, а затем отфильтруйте этот список на основе пользовательских атрибутов. то у вас есть список всех ваших '' ILimb'', которые вы можете перебирать через https://msdn.microsoft.com/en-us/library/a4a92379(v=vs.110).aspx –

+0

Конкат «Ноги» и 'Arms' вместе и прокрутите их. –

+0

@MattBurland: Как вы относитесь к concat? – Spikee

ответ

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>() .... , ... }); 
} 

вы можете привести в порядок код вверх, но в основном он должен иметь набор конечностей и конечности должны иметь наборы конечностей, так что вы можете иметь Голова> Уши> Ухо или любая иерархия, которую вы желаете.

Затем в интерфейсе ILimb, дайте ему свойство через экраны

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);

, например.

+0

Торс и головы не являются конечностями. Но в остальном, общий принцип, что они должны изменить свою структуру, не является плохим –

+0

В реальной жизни нет, но для целей игры они могут быть. Или вы можете изменить его на «BodyPart» или что-то подобное. Понятие «голова» тоже не является реальностью, это просто объект, который автор использовал для группировки нескольких головок. Я не думаю, что это действительно необходимо, головы могут быть добавлены к корневому объекту, и вы можете легко получить все головы. – NibblyPig

+0

@SLC: Правильно, задача с несколькими головками состоит в том, чтобы покрывать такие вещи, как двуглавые огры или что-то подобное. Или гидры, хотя это, конечно, не гуманоидная реализация. – Spikee

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()) 
{ 

} 
+0

Я рассмотрю его, спасибо! – Spikee

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) 

По существу точка здесь заключается в том, что набор объектов сам по себе является объектом, остроумием h пользовательская логика, как и любой другой объект. Поместите объектную логику в объекты, поместите логику сбора в коллекции. Там нет правила, которое говорит, что вы должны только использовать встроенные коллекции в рамках.

+0

Интересное предложение, я рассмотрю его. – Spikee

Смежные вопросы