2011-03-25 56 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