建议用关系枚举复杂结构

时间:2012-12-14 15:46:30

标签: c# arrays

我想知道处理具有关系的复杂结构的最佳方法是什么?

我正在为我的项目实现一个星系生成算法,基本上我有简单的

枚举
GalaxySize { Small, Medium, Large };
GalaxyAge { Young, Mature, Ancient}; 
StarTypes { Black = 1, White = 3, Yellow = 1, Red = 3 };

到目前为止,我生成的星星限制了GalaxySize的价值。 然后我随机从StarTypes中获取一个类型并从此类型创建一个星。 我想要做的是在StarTypes和GalaxyAge之间建立关系。

意味着在一个年轻的星系中(例如)黄色和白色恒星的机会会更高,而在古老的星系中,黑色和红色恒星的可能性会更高。

我所想的是有一个基本机会让StarType得到“滚动”,然后根据GalaxyAge添加修饰符,这将导致特定星系时代中更多常见的恒星。

Example: weight (chance) of a white star in young galaxy is 3 base + 3 
from the "young" galaxy age modifier 
against the weight of a red star which has 3 base + 1 from the "young" modifier.


Resulting in:
White star type weight = (3 + 3 ) * rand.nextDouble() 
Red star type weight = (3 + 1) * rand.nextDouble()

关于如何实现/代表此功能的任何建议,因为显然单独的枚举是不够的? :)

3 个答案:

答案 0 :(得分:0)

为什么不为星系创建一个类层次结构?

using System.Collections.Generic;

enum StarTypes { Black, White, Yellow, Red };

abstract class Galaxy {
    Dictionary<StarTypes, float> _baseProbabilities;
    protected Galaxy() {
        _baseProbabilities = new Dictionary<StarTypes, float>();
        _baseProbabilities[StarTypes.Black] = 1.0f;
        _baseProbabilities[StarTypes.White] = 3.0f;
    }
    public float GetStarProbability(StarTypes starType) {
        return _baseProbabilities[starType] + GetStarProbabilityModifier(starType);
    }
    protected abstract float GetStarProbabilityModifier(StarTypes starType);
}

class YoungGalaxy : Galaxy {
    protected override float GetStarProbabilityModifier(StarTypes starType) {
        switch (starType) {
        case StarTypes.White:
            return 3.0f;
        default:
            return 0;
        }
    }
}

答案 1 :(得分:0)

是的,所以你想生成随机恒星但是根据星系的年龄加权吗?我假设你已将这些权重存储在某处。

所以:

年轻的星系。让我们假设:

  1. 白星:40%的几率
  2. 黄星:40%的几率
  3. 红星:10%的几率
  4. 黑星:10%的几率
  5. 如果是这种情况,那么让我们建立一个List,包括4颗白色和黄色的星星以及1颗红色和黑色的星星。

    现在,对于每个星形插槽,我们可以执行以下操作:

        var start=GetListOfStarsBasedOnGalaxyAge(galaxyAge);
        var starList=new List<StarTypes>();
        for(int starCount=0;starCount<starsInGalaxy,starCount++)
    {
        var star=var stars.OrderBy(a => Guid.NewGuid()).First();
     starList.Add(star);
    }
    

    基本上我们使用随机Guids进行排序,这是一种廉价但有效的shuffling方式。这将确保您的星级选择是随机的,但也使用您想要的适当权重。你可能仍然会得到一个完全被黑色星星填满的星系,但这种可能性很小。

答案 2 :(得分:0)

我真的不了解算法,但你可以从这开始:

sealed class Age
{
    public static readonly Young = new Size(3.0);
    public static readonly Mature = new Size(2.0);
    public static readonly Ancient = new Size(1.0);

    public double Weight
    {
        get;
        private set;
    }

    private Age(float weight)
    {
        Weight = weight;
    }
}

sealed class Size
{
    public static readonly Small = new Size(3.0);
    public static readonly Medium = new Size(2.0);
    public static readonly Large = new Size(1.0);

    public double Weight
    {
        get;
        private set;
    }

    private Size(float weight)
    {
        Weight = weight;
    }
}

现在让我们为Galaxy定义一个类:

sealed class Galaxy
{
    public Age Age
    {
        get;
        set;
    }

    public Size Size
    {
        get;
        set;
    }
}

现在你必须定义一个类来定义星形:

abstract class Star
{
    protected Star(string color, Galaxy galaxy)
    {
        Color = color;
        Galaxy = galaxy;
    }

    public string Color
    {
        get;
        private set;
    }

    public Galaxy Galaxy
    {
        get;
        private set;
    }

    public abstract float Chances(Random rnd);
}

现在让我们为每颗星定义一个新类(不要忘记根据每种类型的实际情况更改算法,公式和权重):

sealed class WhiteStar : Star
{
    public WhiteStar(Galaxy galaxy) : base("White", galaxy)
    {
    }

    public override float Chances(Random rnd)
    {
        return (3 + Galaxy.Age + Galaxy.Size) * rnd.NextDouble();
    }
}

当然这不是最终的代码,但您可以将其用作组织代码的提示。

最大的好处是Galaxy不知道获得特定类型的星的规则,每个星型都知道自己的规则(这意味着如果你添加一个你不需要的新星型)搜索许多类中遍布的规则)。当然这也适用于其他类(例如,如果你添加MiddleAge galaxy的年龄,你将不需要更新任何其他类。)

最后,不要忘记将Weight属性的名称更改为对您的域名更有意义的内容。