我正在为游戏编写一个寻路算法,但试图保持它的通用性,以便它可以在未来的应用程序中使用.
我有一个Node类,它包含X,Y和"PassableType".
NodeGrid类存储一个节点数组,包含它们如何连接的图形信息,然后有一个FindAStarPath()函数,该函数将"PassableTypes"作为参数StartNode,EndNode和params.
我的问题是确定"PassableType"应该具有什么类型.
理想情况下我想要的是能够使用通用枚举 - 即每个游戏定义的限制列表.Node将保存该列表中的单个元素,以说明它是什么路径类型(当前游戏可能使用Path,Grass,Wall等)
因此,当实体尝试路径时,它提供路径查找功能,其类型被视为"可通过".所以男人可以使用
FindAStarPath(CurrentNode, DestinationNode, "Path", "Floor", "Door");
Run Code Online (Sandbox Code Playgroud)
但是汽车可能会使用
FindAStarPath(StartNode, EndNode, "Road");
Run Code Online (Sandbox Code Playgroud)
我的问题是我无法弄清楚如何让NodeGrid采用Generic枚举或等效逻辑.
目前我已经接受了字符串,但这意味着我
每次使用它时都必须编写MyEnum.Road.ToString().
理想情况下,我想做点什么
NodeGrid<MyEnum> CurrentNodeGrid = new NodeGrid<MyEnum>()
Run Code Online (Sandbox Code Playgroud)
然后Nodes会将MyEnum作为passableType,路径寻找函数也是如此,因此每个游戏都有一组不同的tile类型用于路径.
但我不能将NodeGrid定义为:
public class NodeGrid<T> where T:enum
Run Code Online (Sandbox Code Playgroud)
为清楚起见,使用此枚举的唯一部分路径查找功能是这个(包含在Node中):
public bool IsPassable(string[] passableTypes)
{
for (var i = 0; i < passableTypes.Count(); i++)
{
if (this.PassableType == passableTypes[i]) return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
谢谢Haighstrom
除非你使用枚举的某些特定功能(比如Enum.Parse),否则我没有任何理由将它限制在它们之内.通过释放约束,调用者可以使用他们认为合适的任何类型,beit 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;
}
}
Run Code Online (Sandbox Code Playgroud)
但由于我们现在使用泛型,你不能再使用==比较了.最简单的方法是利用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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
200 次 |
| 最近记录: |