【问题标题】:Best way to choose two random ints to assign values to选择两个随机整数分配值的最佳方法
【发布时间】:2019-11-21 06:56:11
【问题描述】:

我正在创建一个龙与地下城角色创建器。有一个随机化功能将创建一个完整的字符表。我已经完成了一部分,但我不太确定最好的方法。

我设置种族修饰符的方式是使用 if 语句。这是一个例子。

if (raceInt == 0 || raceInt == 2 || raceInt == 10)
{
    raceStrMod = 2;
}

if (raceInt == 3 || raceInt == 4 || raceInt == 5 || raceInt == 11 || raceInt == 12)
{
    raceDexMod = 2;
}

但是,有些种族具有修饰符,可让您选择两个属性来添加修饰符,例如力量或敏捷。为这些比赛选择两个随机整数的最佳方法是什么?

例如,半精灵种族将获得 +2 敏捷,然后 +1 其他两个随机属性。所以我需要找到一种方法来随机选择剩余的两个整数来使 value = 1。

我的种族模组初始化为

int raceStrMod = 0;
int raceDexMod = 0;
int raceConMod = 0;
int raceIntMod = 0;
int raceWisMod = 0;
int raceChaMod = 0;

然后 if 语句根据随机选择的种族分配一个值。

感谢大家的投入!这就是我最终编码的方式

        if (raceInt == 9)
        {
            int randomX = rnd.Next(1, 5);
            int randomY = rnd.Next(1, 5);

            int attempts = 0;
            while (randomX == randomY && attempts < 10)
            {
                randomY = rnd.Next(1, 5);
                attempts++;
            }

            //if they are still not unique after 10 attempts
            if (randomX == randomY)
            {
                if (randomX == 5)
                    randomY = 1;
                else
                    randomY = randomX + 1;
            }

            int[] randomNumbers = { randomX, randomY };

            foreach (int i in randomNumbers)
            {
                switch (i)
                {
                    case 1:
                        raceStrMod = 1;
                        break;
                    case 2:
                        raceDexMod = 1;
                        break;
                    case 3:
                        raceConMod = 1;
                        break;
                    case 4:
                        raceIntMod = 1;
                        break;
                    case 5:
                        raceWisMod = 1;
                        break;
                }
            }
        }

【问题讨论】:

  • 你问的是如何生成随机数?
  • 最好将它们视为具有“可选属性奖励 +2”。或者,将它们视为几个物种 - 每个属性组合一个 |像这样的案例正是为什么制作角色创建者几乎不可能做到,即使对于有经验的程序员也是如此。所以你最好不要把这些边缘案例放在外面。

标签: c#


【解决方案1】:

您的班级有没有向您介绍enum 类型?如果没有,您的期末项目在使用课堂上未教授的语言功能方面是否有任何限制?

您的问题可以说过于宽泛,因为即使在现实世界的代码中也有许多不同的方法可以解决此类问题,而且课堂环境引入了潜在的障碍,虽然可能会限制问题,但由于未知,因此不可能知道什么答案实际上对你有用。

也就是说……

忽略课堂方面,只关注问题本身,我会使用enum 类型和字典来处理这类事情。例如:

enum Attribute
{
    Strength,
    Dexterity,
    Constitution,
    Charisma,
    Intelligence,
    Wisdom,
    Count, // must always be last
}

Dictionary<Attribute, int> modifiers = new Dictionary<Attribute, int>();

然后您可以选择一个随机属性,例如(假设您有一个引用 Random 对象的 random 变量……不要犯经典的新手错误,即每次您想选择一个新的 Random 对象时新随机数):

Attribute attributeToModify = (Attribute)random.Next((int)Attribute.Count);

您可以像这样存储该选择:

modifiers[attributeToModify] = 1;

这可以用来存储任何你喜欢的修饰符。您可以将其封装在代表角色本身的对象中,或者您可以将其放入单独的AttributeModifiers 类中。做后者的一个好处是,如果您有来自不同来源的修饰符,您可以在角色对象中将其作为AttributeModifier 实例的列表进行跟踪,每个实例依次跟踪这些修饰符的实际来源是什么.

这只是触及表面而已。正如我所指出的,这个问题本身相当广泛。但我强烈建议使用可用的语言特性来确保您的变量以特定于类型的方式表示事物,而不是仅仅使用int 值来表示不是真正整数的事物,并使用更正确地表示的集合类语义你的代码打算做什么。

请注意,这也意味着您可能应该为比赛设置 enum 类型。例如:

enum Race
{
    Dwarf,
    Elf,
    HalfElf,
    Halfling,
    HalfOrc,
    Human,
    // etc.
}

您的if 语句链可能更好地表示为switch

Attribute racialMod;

switch (race)
{
    case Human:
    case Halfling:
    // etc.
        racialMod = Attribute.Strength;
        break;
    case Elf:
    case HalfElf:
    // etc.
        racialMod = Attribute.Dexterity;
        break;
}

modifiers[racialMod] = 2;

类似的东西。关键是要确保代码读起来更像原始规范所说的(如果你真的写过的话)。这将使代码更容易理解,并且您不太可能在代码中添加错误(例如,您不小心输入了错误的魔法、未命名的整数)。

【讨论】:

    【解决方案2】:

    我正在创建一个龙与地下城角色创建器。

    这是一个有趣的初学者项目;我在学习编程时也是这样做的。

    我需要想办法随机选择剩下的两个……

    你需要找到两个不同的值,然后调用x和y。您得出的解决方案是:

    • 生成 x
    • 尝试生成 y 十次
    • 如果没有成功找到不同的 y,则硬编码选择。

    这很有效,您几乎不必使用硬编码选项。但我想你可能有兴趣知道有一种更简单的方法可以生成两个不同的数字。假设我们想要两个不同的数字 0、1、2、3 或 4。(显然,如果你想要一个不同的范围,比如 1 到 5,你可以通过生成两个不同的数字 0->4 然后添加一对一。)

    改进的算法是:

    • 像往常一样在 0 和 4 之间选择 x。
    • 在 1 和 4 之间选择 n。
    • y = (x + n) % 5;

    这样想。假设我们列一个这样的列表:

    0, 1, 2, 3, 4, 0, 1, 2, 3
    

    我们从列表的前五个条目中随机选择 x,然后我们通过在 1 到 4 步之间步进向前来选择 y。由于列表不会在一到四个步骤中重复,因此我们知道我们将获得两个独特的元素。数学就相当于。

    你也可以在你的程序中使用%

    if (randomX == 5)
      randomY = 1;
    else
      randomY = randomX + 1;
    

    可以写

    randomY = randomX % 5 + 1
    

    如果你不熟悉%,那就是remainder 运算符。它是/ 运算符的补充。规则是:

    int x = whatever;
    int y = whatever;
    int r = x % y;
    

    等同于:

    int r = x - (x / y) * y;
    

    即是x除以y时的余数。请记住,余数可以是负数!

    【讨论】:

    • “少选一个数字,然后避开已经选择的数字”方法的变体:在 0 和 3 之间选择 n。将 y 设置为 n==x ? 4 : nn &lt; x ? n : n+1。第一个变体与 OP 的原始解决方案非常相似。
    【解决方案3】:

    (免责声明:我不喜欢这个选项,但除了反射之外想不出其他更糟糕的方法)
    您可以定义一个类来掩盖所有模块都存储为数组的事实,因此可以使用随机数进行索引。
    类似于以下内容:

        public class StatMods
        {
            public int RaceStrMod { get { return this.mods[0]; } set { this.mods[0] = value; } }
            public int RaceDexMod { get { return this.mods[1]; } set { this.mods[1] = value; } }
            public int RaceConMod { get { return this.mods[2]; } set { this.mods[2] = value; } }
            public int RaceIntMod { get { return this.mods[3]; } set { this.mods[3] = value; } }
            public int RaceWisMod { get { return this.mods[4]; } set { this.mods[4] = value; } }
            public int RaceChaMod { get { return this.mods[5]; } set { this.mods[5] = value; } }
    
            private readonly int[] mods;
            private static readonly Random rand = new Random();
    
            public StatMods()
            {
                this.mods = new int[6];
            }
    
            public void ApplyRandomMod(int modification)
            {
                this.mods[rand.Next(0, 6)] += modification;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2012-01-30
      • 1970-01-01
      • 2012-05-19
      • 2014-10-07
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      相关资源
      最近更新 更多