在C#中使用GetType/instanceof与其他选项
我在C#游戏中遇到了一个问题。这是一个简单的基于瓷砖的匹配游戏,我正在尝试制作的一个加电游戏出现了问题: 假设我们有基本的瓷砖类型,圆形,正方形和菱形,它们都是瓷砖的子类。我尝试将“匹配”行为提取到一个抽象的Tile方法:canMatchWith(Tile t),而不是让圆只与圆匹配。 瓷砖还有两种方法可以添加/删除它们可以匹配的瓷砖 所以我们在游戏的中间有一个圆形的瓦片,我们有一个强大的力量,说“圆形的瓦片可以与这一回合的方形瓦片相匹配”。我会浏览所有的圆形瓷砖,然后说circleTile.addCanMatchWith(typeof(Square))。在内部,我们有一个可以匹配的列表 后来,我想说“圆不能再与正方形匹配”,简单地说是circleTile.removeCanMatchWith(typeOf(Square)) 这是我目前的解决方案,它工作得很好,没有我注意到的性能缺陷(这是一个基于分片的匹配游戏,所以这些类型在每次“移动”时只评估一次,而不是逐帧)。然而,我脑海中的声音告诉我,这是一个不好的方式来完成这种行为。所以我有一些选择:在C#中使用GetType/instanceof与其他选项,c#,oop,object,reflection,instanceof,C#,Oop,Object,Reflection,Instanceof,我在C#游戏中遇到了一个问题。这是一个简单的基于瓷砖的匹配游戏,我正在尝试制作的一个加电游戏出现了问题: 假设我们有基本的瓷砖类型,圆形,正方形和菱形,它们都是瓷砖的子类。我尝试将“匹配”行为提取到一个抽象的Tile方法:canMatchWith(Tile t),而不是让圆只与圆匹配。 瓷砖还有两种方法可以添加/删除它们可以匹配的瓷砖 所以我们在游戏的中间有一个圆形的瓦片,我们有一个强大的力量,说“圆形的瓦片可以与这一回合的方形瓦片相匹配”。我会浏览所有的圆形瓷砖,然后说circleTile.a
我觉得我必须使用类型/枚举,因为我不想说thisTile.addCanMatch(Tile someOtherObject)。这太具体了,我希望此互动程序能够与作为特定类实例的所有互动程序匹配 如果相似类型的所有形状都将始终共享一个行为,那么不将该行为存储在“每个实例”级别是有意义的。相反,您可以使用“CanMatchManager”,它存储列表字典,并按形状类型索引。然后,当圆尝试比较匹配时,它会从MatchManager请求可以匹配的类型。或者,MatchManager可以采用这两种形状,并确定它们是否匹配。这是我知道这个问题已经得到了回答和接受,但我曾经做过类似的事情,我想我应该把代码贴在这里
public class TypeMatchManager
{
private Dictionary<Type, List<Type>> savedMatches = new Dictionary<Type, List<Type>>();
public TypeMatchManager() { }
public void AddMatch(Type firstType, Type secondType)
{
this.addToList(firstType, secondType);
this.addToList(secondType, firstType);
}
public void DeleteMatch(Type firstType, Type secondType)
{
this.deleteFromList(firstType, secondType);
this.deleteFromList(secondType, firstType);
}
public bool CanMatch(Type firstType, Type secondType)
{
List<Type> firstTypeList = this.findListForType(firstType);
List<Type> secondTypeList = this.findListForType(secondType);
return (firstTypeList.Contains(secondType) || secondTypeList.Contains(firstType));
}
private void addToList(Type firstType, Type secondType)
{
var matchingTypes = this.findListForType(firstType);
if (!matchingTypes.Contains(secondType))
{
matchingTypes.Add(secondType);
}
}
private void deleteFromList(Type firstType, Type secondType)
{
var matchingTypes = this.findListForType(firstType);
if (matchingTypes.Contains(secondType))
{
matchingTypes.Remove(secondType);
}
}
private List<Type> findListForType(Type type)
{
foreach (var keyValuePair in savedMatches)
{
if (keyValuePair.Key == type)
{
return keyValuePair.Value;
}
}
savedMatches.Add(type, new List<Type>());
return findListForType(type);
}
}
恐怕我不是一个熟练的设计师,无法为您推荐一个完整的设计,但是如果圆和椭圆的操作方式没有实际的功能差异,那么最好让所有实例都是class
Tile
,然后设置某种行为
属性。棋盘上的所有圆圈可能都可以共享相同的行为
对象,然后当规则更改一圈时,您可以在该行为
对象上设置更改。如果我理解情况,这可能会减少代码重复。如果我理解正确,这有点像我的#2行为组合。我担心的是行为爆炸。例如,与圆形和方形行为匹配。明白我的意思了吗?如果有5种类型的瓷砖,那么我们有5种选择1+5选择2+5选择3+5选择4+5选择5种行为组合。这似乎比GetType更糟糕。然而,我可能误解了你建议中的某些内容。瓷砖本身可以做任何他们想做的事情,一个可以做爆炸动画,等等。这只适用于瓷砖可以与另一个匹配的情况。我不是建议行为是枚举或不可修改的类。您可以用不同的方式对它进行子类化,但主要是我希望它有一个内部集合,表示它的类型(圆形)和它可以匹配的类型(方形)。然后,您可以以某种面向数据的方式来更改它。我完全同意为了良好的对象设置应该避免任何会导致大量if/else/switch块的事情,但是我们也希望避免编写新的类来解释行为上的一些不太新的变化。有趣的是,比如:CanMatchManager::canMatch(Tile one,Tile two){return dictionary[one]。contains(two)}其中dictionary将平铺类型映射到可匹配类型的列表。然后,如果我想添加一个交互,我可以说tileManager.addInteraction(Tile one,Tile two),它会更新为{dict[one].add(two),dict[two].add(one)}。这似乎比wha更有效
typeManager.AddMatch(a, b);
Console.WriteLine(typeManager.CanMatch(a, b)); // True
typeManager.DeleteMatch(b, a);
Console.WriteLine(typeManager.CanMatch(a, b)); // False
Console.WriteLine(typeManager.CanMatch(a, c)); // False
typeManager.AddMatch(a, c);
Console.WriteLine(typeManager.CanMatch(a, c)); // True
Console.WriteLine(typeManager.CanMatch(a, d)); // False
typeManager.AddMatch(b, d);
Console.WriteLine(typeManager.CanMatch(a, d)); // False
Console.WriteLine(typeManager.CanMatch(d, b)); // True
typeManager.DeleteMatch(d, b);
Console.WriteLine(typeManager.CanMatch(d, b)); // False
Console.WriteLine(typeManager.CanMatch(b, d)); // False