我想知道处理具有关系的复杂结构的最佳方法是什么?
我正在为我的项目实现一个星系生成算法,基本上我有简单的
枚举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()
关于如何实现/代表此功能的任何建议,因为显然单独的枚举是不够的? :)
答案 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)
是的,所以你想生成随机恒星但是根据星系的年龄加权吗?我假设你已将这些权重存储在某处。
所以:
年轻的星系。让我们假设:
如果是这种情况,那么让我们建立一个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
属性的名称更改为对您的域名更有意义的内容。