3

我正在为游戏编写寻路算法,但试图保持其通用性,以便可以在未来的应用程序中使用。

我有一个包含 X、Y 和“PassableType”的节点类。

NodeGrid 类存储一个节点数组,包含它们如何连接的图形信息,然后有一个 FindAStarPath() 函数,该函数将 StartNode、EndNode 和“PassableTypes”的参数作为其参数。

我的问题是确定“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

为清楚起见,使用此枚举的寻路函数的唯一部分是 this(包含在 Node 中):

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

谢谢 Haighstrom

4

1 回答 1

5

除非您使用枚举的某些特定功能(如Enum.Parse),否则我看不出有任何理由将其限制在它们身上。通过释放约束,调用者可以使用他们认为合适的任何类型, beitenum或一组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
于 2013-07-11T12:46:46.610 回答