3

ゲームの経路探索アルゴリズムを作成していますが、将来のアプリケーションで使用できるように汎用性を維持しようとしています。

X、Y、および「PassableType」を保持する Node クラスがあります。

NodeGrid クラスは、接続方法のグラフ情報を含むノードの配列を格納し、FindAStarPath() 関数を持ちます。この関数は、パラメータとして StartNode、EndNode、および「PassableTypes」の params を取ります。

私の問題は、「PassableType」が持つべき型を決定することです。

理想的には、一般的な列挙型 (つまり、各ゲームが定義する制限付きリスト) を使用できるようにすることです。ノードは、そのリストの単一の要素を保持し、パスの種類を示します (現在のゲームでは、パス、草、壁などを使用できます)。

したがって、エンティティがパスしようとすると、「パス可能」として処理するタイプのパスファインディング関数が提供されます。だから男は使える

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

しかし、車はただ使うかもしれません

FindAStarPath(StartNode, EndNode, "Road");

私の問題は、NodeGrid にジェネリック列挙型または同等のロジックを取得させる方法がわからないことです。

現時点では文字列を取得していますが、これは、
使用するたびに MyEnum.Road.ToString() を記述する必要があることを意味します。

理想的には、次のようなことをしたいと思います

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

次に、パスファインディング関数と同様に、ノードは passableType に MyEnum を使用します。これにより、各ゲームがパス用に異なるタイル タイプのセットを持つことができます。

しかし、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;
    }

ありがとうハイストロム

4

1 に答える 1

5

列挙型の特定の機能 ( などEnum.Parse) を使用していない限り、それらに制約する理由はありません。制約を解放することにより、呼び出し元は、適切と思われる型、 beit enumstring値のセット (現在持っているもの)、またはチェックするカスタム クラス インスタンスのセットを使用できます。

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)は、null チェックを実行し、該当する場合はジェネリックを適切に活用し、型が を実装している場合は、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
于 2013-07-11T12:46:46.610 に答える