【问题标题】:Random value from Enum doesn't work as I would like it to来自 Enum 的随机值不能像我希望的那样工作
【发布时间】:2021-07-25 20:49:20
【问题描述】:

我正在使用此代码从我的枚举中查找随机值:

public cards chooseFromDeck()
{
    var random = new Random();
    return (cards)random.Next(cards.GetNames(typeof(cards)).Length);
}

这是我的枚举:

public enum cards
{Ace=1,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack=10,Queen=10,King=10}

我有两个问题。

  1. 它以某种方式将“0”作为一个值,我不明白,因为我将我的 Ace 标记为“1”。
  2. 问题是它根本不选择 Jack、Queen 和 King,如果我从它们中删除“=10”就可以了,但是值是 11、12、13。我应该用什么方法给 Jack、Queen 和 King 加值“10”?

【问题讨论】:

  • 简短的回答 - enum 是错误的数据结构。您将无法使用您的代码区分 Jack 和 King。您应该做的是创建一个带有NameScoreCard 类。将其中多个添加到List<Card>,然后从该列表中随机选择。

标签: c# random enums


【解决方案1】:
  1. 随机下一个函数的最小值为0,因此需要将随机的minValue改为1:

     return (cards)random.Next(1, cards.GetNames(typeof(cards)).Length);
    
  2. 这是不可能用枚举做到的。我建议您改用数组,选择 10 的 4 倍。将数字 10 写入 4 倍的想法是为了在随机函数中获得 10 的机会更大(因为 10 代表 4 张不同的卡片)。

    readonly int[] cardNumbers = 
        new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };
    
    public int chooseFromDeck()
    {
        var random = new Random();
        return random.Next(1, cardNumbers.Length);
    }
    

附带说明,您没有正确使用 Random 功能,这也不是安全功能。你可以阅读更多关于它的信息here

【讨论】:

  • 适用于“0”,但不适用于 J、Q、K。我想我发现了我只是不知道如何解决它的问题。当我返回随机值时,它选择从 1 到 13 的随机数,但在我的枚举中有 13 个值,但最后 4 个值是 10,所以我认为这就是它不会注册 J、Q、K 的原因(当随机选择 11 到 13 时)
  • @Damianhar 您是否尝试过使用 int 数组而不是枚举?看看我在项目符号 2 中写的示例。它对我来说非常有效。
【解决方案2】:

我认为,关键是为不同的枚举成员分配相同的值(在您的情况下为:10)在您的情况下不起作用。因此,对于您的枚举(Jack、Queen、King 的值为 10),如果您通过执行以下行进行简单测试,您将得到错误的值。

cards c2 = cards.Queen;
Console.WriteLine(c2); // outputs Ten

因此,您可以做的最好的事情是,删除将值 10 分配给多个枚举成员(如果您保留,它肯定会在将来绊倒您)并编写一个方法,当您使用枚举时将值更改为 10 .例如:

public enum cards {
    Ace = 1,
    Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen , King
}

private cards chooseFromDeck() {
    Random random = new Random();
    int rNum = random.Next(1, 13);
    return (cards)rNum;
}

private int GetCardsValue(cards c) {
        int value;
        switch (c) {
            case cards.Jack:
            case cards.King:
            case cards.Queen:
                value = 10;
                break;
            default:
                value = (int)c;
                break;
        }
        return value;
}

或者创建一个扩展方法:

public static class Extensions 
{
    public static int GetValue(this cards c) {
        int value;
        switch (c) {
            case cards.Jack:
            case cards.King:
            case cards.Queen:
                value = 10;
                break;
            default:
                value = (int)c;
                break;
        }
        return value;
    }
}

并将其用作:

private void SomeMethod() {
    cards c = chooseFromDeck();
    int cval = c.GetValue();
}

【讨论】:

    【解决方案3】:
    public static class Enum
    {
        private static int Random(int start, int end) =>
            new Random().Next(start, end);
    
        private static System.Array GetArray<T>() where T : struct, IConvertible =>
            System.Enum.GetValues(typeof(T));
    
        public static int GetSize<T>() where T : struct, IConvertible =>
            GetArray<T>().Length;
    
        public static int GetValue<T>(this T @enum) where T : struct, IConvertible
        {
            if (!typeof(T).IsEnum) throw new ArgumentException($"{typeof(T)} is not enum");
            return (int)(object)@enum;
        }
    
        public static int GetIndex<T>(this T @enum) where T : struct, IConvertible
        {
            if (!typeof(T).IsEnum) throw new ArgumentException($"{typeof(T)} is not enum");
            return System.Array.IndexOf(GetArray<T>(), @enum);
        }
    
        /// index to enum
        public static T GetEnum<T>(this int index) where T : struct, IConvertible
        {
            var array = System.Enum.GetValues(typeof(T));
            return (T)array.GetValue(index);
        }
    
        /// [0,Length)
        public static T Random<T>() where T : struct, IConvertible =>
            Random(0, GetSize<T>()).GetEnum<T>();
    
        /// [start,end]
        public static T Random<T>(T start, T end) where T : struct, IConvertible =>
            Random<T>(start.GetIndex(), end.GetIndex() + 1);
    
        /// [start,end)
        public static T Random<T>(int start, int end) where T : struct, IConvertible
        {
            var size = GetSize<T>();
            if (start < 0) start = 0;
            if (end > size) end = size;
            return Random(start, end).GetEnum<T>();
        }
    }
    

    枚举

    // value
    public enum EnumShape // length = 8
    {
        None,     // 0
        Direct,   // 1
        Square,   // 2
        Cross,    // 3
        Circle,   // 4
        BigSquare,// 5
        BigCross, // 6
        BigCircle,// 7
    }
    
    public enum EnumInNeedShape // length = 5
    {
        None,                      // 0
        Square = EnumShape.Square, // 2
        Cross = EnumShape.Cross,   // 3
        Circle = EnumShape.Circle, // 4
        Triangle = 10,             // 10
    }
    

    测试GetEnum

    class Test{
        pubilc void Test(){
            0.GetEnum<EnumShape>();// None
            1.GetEnum<EnumShape>();// Square
            2.GetEnum<EnumShape>();// Cross
            3.GetEnum<EnumShape>();// Circle
            4.GetEnum<EnumShape>();// Triangle
    
    
            10.GetEnum<EnumShape>();// throw IndexOutOfRangeException
        }
    }
    

    测试GetValue,GetRandom

    public class Test
    {
        pubilc void Test()
        {
            $"Square {(int)EnumInNeedShape.Square}".LogLine(); // 2
            $"Square {(int)EnumInNeedShape.Circle}".LogLine(); // 4
    
            EnumInNeedShape.Triangle.GetValue().LogLine(); // 10
            EnumInNeedShape.Triangle.GetIndex().LogLine(); // 4
            Enum.Random(EnumInNeedShape.None, EnumInNeedShape.Triangle).LogLine(); // [None, Triangle]
            Enum.Random(EnumShape.None, EnumShape.AltCircle).LogLine(); // [None, AltCircle]
            Enum.Random<EnumShape>(0, 9).LogLine(); // [None, AltCircle]
            Enum.Random(EnumInNeedShape.Square, EnumInNeedShape.Circle).LogLine(); // [Square, Circle]
            Enum.Random(EnumInNeedShape.Cross, EnumInNeedShape.Triangle).LogLine(); // [Cross, Triangle]
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-12
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      • 2017-07-05
      • 1970-01-01
      相关资源
      最近更新 更多