2011-03-25 41 views
0

嗨,我想知道你将如何检查列表中的特定位置的对象是否等于某件事。检查特定列表索引的子类

我订有“船舶”的子类3,他们被称为“敌人”,“Enemy2”,“玩家” 所有这些都保存在我称之为“船”

我想知道一个列表你将如何检查列表中索引项目是否为上述之一。这很难解释,我会尝试在代码中解释。

for (int i = 0; i < Game1.Ships.Count; i++) 
    { 
    if(Game1.Ships.ElementAt(i) == "Enemy") 
     Enemy e = Game1.Ships.ElementAt(i); 
     if (this.collisionBox.Intersects(e.collisionBox)) 
     { 
      e.Destroy(false); 
      //Execute Destory(bool). 
     } 
    } 
    else 
     i++; 
     //Skip to next item. 

这大致是我想要做的,显然我需要检查它不是播放器。而且我也必须为Enemy2做同样的循环。 尽管“舰船”默认没有“毁灭”(布尔),但它仅存在于“敌人”&“敌人2”上。

+0

你的问题的独立,在'要不我++;'将会造成问题,因为它会导致一些船只被跳过。这是打算? – dahlbyk 2011-03-25 12:28:15

回答

3

只需使用is

for (int i = 0; i < Game1.Ships.Count; i++) 
{ 
    if(Game1.Ships.ElementAt(i) is Enemy) 
    { 
     Enemy e = (Enemy)Game1.Ships.ElementAt(i); 
     if (this.collisionBox.Intersects(e.collisionBox)) 
     { 
      e.Destroy(false); 
      //Execute Destory(bool). 
     } 
    } 
    else 
     i++; 
     //Skip to next item. 
} 
+0

@Daniel 我在 上得到以下错误:“Enemy e = Game1.Ships。ElementAt(i);“ ”不能将类型'ProjectGame1.Ship'隐式转换为'ProjectGame1.Enemy'。有一个明确的转换存在(你是否缺少演员?)“如果我这样做 – PeppeJ 2011-03-25 12:00:25

+0

@ user669415:对不起,错过了那一行,修正了我的答案。 – 2011-03-25 12:01:40

+0

@Daniel我明白你是怎么想的,而且确实有效,在Game1.Ships.ElementAt(i)之前做的(敌人)有所作为?? – PeppeJ 2011-03-25 12:03:09

0

,并考虑

foreach (var e in Game.Ships.OfType<IDestroy>()) 
    e.Destroy() 

这似乎是一个不错的策略,鉴于

“船舶” 不 有破坏(布尔)默认情况下,它的 只存在于“敌人”& “Enemy2”

我你不能/不会添加界面,可以很容易地选择船舶类型,那么你可以诉诸

var destroyables = Game.Ships 
      .OfType<Enemy>() 
    .Concat(
      Game.Ships.OfType<Enemy2>()); 

我需要指出哪种方法有我投票?

+0

这在语义上并不相同,但是,如果添加缺少的where子句并将IDestroy改为Enemy如果你想暗示的是,Enemy应该实现IDestroy而另一个班级不应该这样在这个背后解释你的推理。 – 2011-03-25 12:05:36

+0

添加更多的细节发布。注意我在这里提供了一些想法,而不是即时解决方案:) – sehe 2011-03-25 12:07:59

+0

这就是为什么我认为你应该详细说明一下,因为OP显然还在学习。 – 2011-03-25 12:09:16

0

你绝对不想像这样使用ElementAt(),因为它每次迭代序列的开始。我会建议使用foreach环和OfType<>()来代替:

foreach (var e in Game1.Ships.OfType<Enemy>()) 
{ 
    if (this.collisionBox.Intersects(e.collisionBox)) 
     e.Destroy(false); 
} 

或者,如果Game1.Ships实现ICollection,你可以用你的for循环和更换.ElementAt(i)[i]

for (int i = 0; i < Game1.Ships.Count; i++) 
{ 
    var e = Game1.Ships[i] as Enemy; 
    if (e != null) 
     if (this.collisionBox.Intersects(e.collisionBox)) 
      e.Destroy(false); 
} 
+0

它不适用于foreach循环,因为它正在主动修改列表的大小,从而破坏它。我正在测试你的for循环atm,虽然 – PeppeJ 2011-03-25 12:14:43

+0

如果Destroy正在主动修改列表,那么你会想在列表后面枚举:'for(int i = Game1.Ship.Count - 1; i> = 0; i - )' – dahlbyk 2011-03-25 12:23:44

0

或者LINQish:

var enemiesToDestroy = from enemy in Game1.Ships.OfType<Enemy>() 
         where this.collisionBox.Intersects(enemy.collisionBox) 
         select enemy; 
enemiesToDestroy.ToList().ForEach(enemy => enemy.Destroy(false)); 

如果你想摆脱T oList()转换,定义了下面的扩展方法

public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action) 
{ 
    foreach (TSource element in source) 
     action (element); 
} 

而且使用这样的:

enemiesToDestroy.ForEach(enemy => enemy.Destroy(false)); 
+0

将你的LINQ查询放在括号中,并在末尾添加'ToList()',它甚至会编译;) – 2011-03-25 12:08:25

+0

或'enemiesToDestroy.ToList().ForEach(...)'。这将使查询可重用。当然你应该选择适合具体情况的正确方法 – sehe 2011-03-25 12:12:57

+0

那是真的,谢谢:)编辑我的答案。 – 2011-03-25 12:16:48