2

我正在将游戏项目的代码从 Python 移植到 C#。现在我在翻译一段特定的代码时遇到了麻烦,游戏会在其中检查两艘太空飞船是友好还是敌对。派系通过整数标识。使用敌对或友好派系编号列表。

检查敌意或友好的功能是(Python):

def is_hostile_faction(ownF, oppF):
    hostile_factions = { 1:[5], 2:[4,5], 3:[5], 4:[2,5], 5:[1,2,3,4], 6:[5], 7:[8,9,10], 8:[5,7,9,10], 9:[7,8,10], 10:[7,8,9]}
    if oppF in hostile_factions[ownF]:
        return True
    else:
        return False

def is_allied_faction(ownF, oppF):
    allied_factions = { 1:[1,2], 2:[1,2,3], 3:[3], 4:[4], 5:[5], 6:[1,2,3,6], 7:[7], 8:[8], 9:[9], 10:[10] }    
    if oppF in allied_factions[ownF]:
        return True
    else:
        return False

分别。到目前为止,很容易。我如何在 C# 中重新创建相同的函数而不编写丑陋的代码,例如:

List<int> faction1hostiles = new List<int> {5};
List<int> faction2hostiles = new List<int> {4,5};
// etc
Dictionary<int,List<int>> hostileFactions = new Dictionary<int,List<int>();
hostileFactions.Add(faction1hostiles);
hostileFactions.Add(faction2hostiles);
// etc

public void isHostile(int ownF, int oppF) {
    if (hostileFactions[ownF].Contains(oppF)) {
        return true; }
    else { return false; }
}

// same for friendly factions

以前的代码是 Python(Panda3D 框架),目标代码是 C#(Unity3D 框架)。考虑到 Python 代码的简单性,即动态创建数据结构,C# 必须有一个同样简单的解决方案吗?

4

2 回答 2

2

我认为你可以这样做:

Dictionary<int,int[]> hostileFactions = new Dictionary<int,int[]>(){
    {1,new[]{5}}, {2,new[]{4,5}}
};

public void isHostile(int ownF, int oppF) {
    return hostileFactions[ownF].Contains(oppF)
}
于 2013-01-03T23:49:02.897 回答
1

这取决于您所说的“丑陋代码”。你可以这样写:

var allies = new Dictionary<int, List<int>>{
    {1, new List<int>{1,2}},
    {2, new List<int>{1,2,3}},
    //...
};

或者您可以像这样跟踪特定的敌对行动和联盟:

var alliances = new[]{
    new {a=1,b=1},
    new {a=1,b=2},
    new {a=2,b=1},
    new {a=2,b=2},
    new {a=2,b=3},
    //...
};

var allies = alliances.ToLookup(e => e.a, e => e.b);

或者,如果您永远不需要给定团队的实际盟友列表,而只想快速发现两个团队是否有联盟,您可以创建一组盟友团队对,如下所示:

private struct TeamPair
{
    private int _team1;
    private int _team2;
    public TeamPair(int team1, int team2)
    {
        _team1 = team1;
        _team2 = team2;
    }
}

ISet<TeamPair> alliances = new HashSet<TeamPair>(
    new[]{
        new {a=1,b=1},
        new {a=1,b=2},
        new {a=2,b=1},
        new {a=2,b=2},
        new {a=2,b=3},
        // ...
    }.Select(e => new TeamPair(e.a, e.b)));


public bool isAllied(int ownF, int oppF) {
    return alliances.Contains(new TeamPair(ownF, oppF));
}

如果你真的想的话,我相信你可以使用数组的数组来想出其他更简洁的语法。

但是您可能需要考虑将联盟映射存储在代码之外:可能是 XML 或 CSV 文件,或关系数据库,然后使用您的代码将该数据读入数据结构。在我看来,您将数据与代码过度耦合。

正如@Lattyware 所提到的,进行重写为您提供了一个独特的机会来思考为新语言编写程序的更好方法:直接翻译很少是最好的方法。如果他们今天有机会再做一次,即使是原作者也可能不会以同样的方式编写游戏。

于 2013-01-03T23:48:19.510 回答