2013-07-11 31 views
3

我正在爲遊戲編寫路徑查找算法,但試圖保持它的通用性,以便可以在將來的應用程序中使用它。C# - 使用泛型枚舉(或用於控制列表的替代方法)

我有一個節點類,其中包含X,Y和「PassableType」。

NodeGrid類存儲一個節點數組,其中包含它們如何連接的圖形信息,然後有一個FindAStarPath()函數,該函數以「PassableTypes」的參數StartNode,EndNode和params爲參數。

我的問題是確定什麼類型的「PassableType」應該有。

理想情況下,我希望能夠使用泛型枚舉 - 即每個遊戲定義的限制列表。節點將保存該列表的單個元素,說明它是什麼路徑類型(當前遊戲可以使用路徑,草地,牆等)

因此,當一個實體試圖路徑時,它提供路徑查找功能哪些類型被視爲「可通過」。所以,一個人可以使用

FindAStarPath(CurrentNode, DestinationNode, "Path", "Floor", "Door"); 

,但汽車可能只是使用

FindAStarPath(StartNode, EndNode, "Road"); 

我的問題是我不知道如何獲得NodeGrid採取通用枚舉或等效邏輯。

目前,我把它取字符串,但這意味着我不得不寫
MyEnum.Road.ToString() 我每次使用它的時間。

理想我想這樣做

NodeGrid<MyEnum> CurrentNodeGrid = new NodeGrid<MyEnum>() 

然後節點將採取MyEnum他們passableType,如將尋路功能,從而使每場比賽有一組不同的瓷磚類型尋路。

但我不能定義NodeGrid爲:

public class NodeGrid<T> where T:enum 

爲了清楚起見,其使用該枚舉尋路功能的唯一部分是(包含在節點):

public bool IsPassable(string[] passableTypes) 
    { 
     for (var i = 0; i < passableTypes.Count(); i++) 
     { 
      if (this.PassableType == passableTypes[i]) return true; 
     } 
     return false; 
    } 

由於 Haighstrom

+0

做什麼用'NodeGrid CurrentNodeGrid =新NodeGrid ()'問題了嗎? –

+0

我無法通過「Where MyEnum:enum」來限制MyEnum。更新了主要問題。 – Haighstrom

+0

請參閱:http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-an-enum –

回答

5

除非你使用枚舉的某些特定功能(如Enum.Parse),否則我沒有看到任何理由將它約束到它們。通過釋放約束,呼叫者可以使用他們認爲合適的任何類型,例如enum或一組string值(與您目前擁有的一樣)或一組自定義類實例進行檢查。

public class NodeGrid<T> 
{ 
    public T PassableType { get; private set; } 

    public bool IsPassable(params T[] passableTypes) 
    { 
     return IsPassable((IEnumerable<T>)passableTypes); 
    } 

    public bool IsPassable(IEnumerable<T> passableTypes) 
    { 
     foreach(T passType in passableTypes) 
     { 
      if (EqualityComparer<T>.Default.Equals(this.PassableType, passType)) 
       return true; 
     } 

     return false; 
    } 
} 

但由於現在我們正在使用泛型,你不能再使用==比較。最簡單的是利用EqualityComparer.Default實用程序。直接調用this.PassableType.Equals(passType)的主要原因是它會執行空檢查並在適用的情況下正確使用泛型,如果類型實現IEquatable<T>,則使用這些泛型版本。可能還有其他一些小事情。它通常最終會調用Object.Equals過載。


根據你的問題的一些例子:

//using a custom enum, calls the params T[] overload 
NodeGrid<MyCarEnum> carNode = ... 
carNode.IsPassable(MyCarEnum.Road, MyCarEnum.Tunnel); 

//demonstrates receiving a set of pass types strings from an external source 
List<string> passTypes = new List<string>("Path", "Floor", "Door"); 
NodeGrid<string> personNode = ... 
personNode.IsPassable(passTypes) //calls the IEnumerable<T> overload 

//feel free to declare enums wherever you want, 
//it can avoid potential mixups like this: 
NodeGrid<string> airplaneNode = ... 
NodeGrid<string> personNode = ... 
NodeGrid<MyCarEnum> carNode = ... 
airplaneNode.IsPassable("Floor"); //makes no sense, but will compile 
personNode.IsPassable("Clouds"); //makes no sense, but will compile 
carNode.IsPassable("Sky"); //compile error: was expected a MyCarEnum value 
+0

+1,優秀的答案。 –

+0

完美,這正是我所追求的。 – Haighstrom