2012-04-14 57 views
2

我正在製作農業/塔防遊戲,我在編程方面很新穎。我似乎在使用列表<>或XNA中的數組時遇到了一個主要問題。我無法讓它從列表中返回我想要的索引。C#列表和ArgumentOutOfRangeException的問題

主要問題是在我的種植引擎。我已經成功實施了一個種植系統,可以生成具有不同屬性的植物列表(spriteobjects),並將它們放置在地圖上。現在,我需要一種基於鼠標點擊該工廠的方式訪問工廠列表中的特定工廠。我覺得我非常接近,但是我最終得到了一個我無法解決的ArgumentOutOfRangeException。下面是代碼的演練:

初始化

public void Addplants() 
     { 
      switch (Mode) 
      { 
      case "Wotalemon": 
      NewPlant = new Plant(Texture, msRect); 
      NewPlant.AddAnimation("seed", 0, 16, 64, 64, 1, 0.1f); 
      NewPlant.AddAnimation("sprout", 64, 16, 64, 64, 1, 0.1f); 
      NewPlant.AddAnimation("wota", 128, 16, 64, 64, 1, 1.0f); 
      NewPlant.CurrentAnimation = "seed"; 
      NewPlant.DrawOffset = new Vector2(32, 48); 
      NewPlant.Position = Position; 
      NewPlant.Type = "wotalemon"; 
      NewPlant.Birthday = Days; 
      NewPlant.IsSelected = false; 
      plants.Add(NewPlant); 
      thisPlant = NewPlant; 
      //various plants after this 

更新/繪製

我使用一些簡單的foreach循環在這裏更新並繪製植物,沒有任何問題。

的GetInfo(此方法使用spriteobject的擊中格屬性和mouseRectangle)

public void GetInfo(Rectangle ms) 
     { 
      msRect = ms; 
      for (int i = 0; i < plants.Count; i++) 
      { 
       foreach (Plant NewPlant in plants) 
       { 
        if (NewPlant.BoundingBox.Intersects(msRect)) 
        { 
         SelectedIndex = i; 
         NewPlant.Tint = Color.Black; 
        } 
        else 
         NewPlant.Tint = Color.White; 
       } 

      } 
     } 

最後,現在的問題是:

public void SelectPlant() 
     { 
      //if (SelectedIndex != null) 
      if (SelectedIndex > plants.Count | SelectedIndex < 0) 
       SelectedIndex = plants.Count; 
      SelectedPlant = plants[SelectedIndex]; 

     } 

唯一的例外是在這條線拋出:

​​

調試器顯示值爲0.我嘗試過各種方法來嘗試預先發布索引從null。我覺得Getinfo()方法中的某些東西是關鍵。我相信我非常接近成功,因爲我在那裏插入的顏色測試非常完美。當我將鼠標懸停在植物上時,它會變黑,當我移除鼠標時,它會恢復正常。

這完全是我想要的行爲類型,除非我想將selectedIndex設置爲我在上進行移植的工廠的索引。任何建議將不勝感激。

+0

if語句,'的SelectedIndex = plants.Count;'應該是'的SelectedIndex = plants.Count-1;' – asawyer 2012-04-14 03:10:31

回答

2

我將添加此作爲一個新的答案,因爲這是解決一個完全不同的問題。看看這個代碼:

msRect = ms; 
for (int i = 0; i < plants.Count; i++) 
{ 
    foreach (Plant NewPlant in plants) // <-- this is redundant 
    { 
     if (NewPlant.BoundingBox.Intersects(msRect)) 
     { 
      SelectedIndex = i; 
      NewPlant.Tint = Color.Black; 
     } 
     else 
      NewPlant.Tint = Color.White; 
    } 

} 

你正在兩個內部循環'植物'!一旦使用索引(for (int i = 0 ...),然後再次使用迭代器(foreach (Plant NewPlant ...)。

你的選擇是要麼改變GetInfo通過使用一個循環來設置正確的索引:

msRect = ms; 
for (int i = 0; i < plants.Count; i++) 
{ 
    Plant NewPlant = plants[i]; 
    if (NewPlant.BoundingBox.Intersects(msRect)) 
    { 
     SelectedIndex = i; 
     NewPlant.Tint = Color.Black; 
    } 
    else 
     NewPlant.Tint = Color.White; 
} 

還是做同樣的事情,短路首先需要SelectPlant()和SelectedIndex的:

msRect = ms; 
foreach (Plant NewPlant in plants) // no need for indexes 
{ 
    if (NewPlant.BoundingBox.Intersects(msRect)) 
    { 
     SelectedPlant = NewPlant; // this is everything you need 
     NewPlant.Tint = Color.Black; 
    } 
    else 
     NewPlant.Tint = Color.White; 
} 

但是,您需要小心使用'全局'變量,例如SelectedPlant來捕獲此邏輯。您最好將整個GetInfo方法更改爲返回選定的工廠,而不是直接修改SelectedPlant。也就是說,更改方法簽名以返回Plant而不是void,並將上面代碼中的SelectPlant = NewPlant更改爲return NewPlant。或者更有趣的一行:

return plants.Where(p => p.BoundingBox.Intersects(ms)) 
+0

酷,感謝您的深入解答,兄弟。我沒有意識到我的代碼是多麼的低效,但我猜想當你是新手時,這是可以預料的。 – user1332755 2012-04-15 02:07:19

+0

沒問題。也許upvote或接受它? – yamen 2012-04-15 06:25:28

6

首先將其設置爲合適的或||並檢查>= plants.Count - 請記住,該列表的索引編號爲0。然後按照建議將其設置爲1:

if (SelectedIndex >= plants.Count || SelectedIndex < 0) 
    SelectedIndex = plants.Count - 1 
+1

@OP:確保你想將SelectedIndex設置爲plans.Count - 1 _even when_原始SelectedIndex <0(替代方案將設置爲0) – 2012-04-14 12:43:08

+0

感謝您的修復。但是這仍然不能解決我的主要問題。 GetInfo()方法仍然不會返回動態植物索引。它只返回我種植的最後一個工廠的索引。任何人都知道通過鼠標移動或點擊列表中的對象來獲取列表索引的好方法? – user1332755 2012-04-14 17:49:55