【问题标题】:Problem in generating random colors - asp.net and c#生成随机颜色的问题 - asp.net 和 c#
【发布时间】:2011-05-19 13:41:49
【问题描述】:

我需要在我的 asp.net 应用程序中生成以十六进制值生成随机颜色来绘制图形。

 Random random = new Random();
 color = String.Format("#{0:X6}", random.Next(0x1000000)); 

以上代码生成随机颜色代码。但我的问题是有时它会产生与以前的颜色几乎相似的颜色。因为我将它用于图形目的,所以我需要生成完全不同的颜色。任何想法......

【问题讨论】:

    标签: c# asp.net colors


    【解决方案1】:

    试试

    Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
    

    --编辑--

    根据 mjv 的评论更新:

    public class RandomColor
    {
        Random _random;
        public RandomColor()
        {
            _random = new Random();
        }
    
        public Color GetNext()
        {
            return Color.FromArgb(_random.Next(0, 255), _random.Next(0, 255), _random.Next(0, 255));
        }
    }
    

    用法:

    colorRandom.GetNext();
    

    【讨论】:

    • 为什么这种方法可以确保不会连续产生两种相似的颜色?
    • Random() 函数会根据种子生成随机数,只要您重用 Random 对象。例如,在 RandomColor 类的构造函数中。
    • @KMan:你是对的。然而,从统计上看,没有什么可以阻止您建议的 sn-p 在第二次调用时产生与前一种颜色相似的颜色。实际上,发生这种情况的概率与一次绘制所有 3 个分量值时相同,就像在 OP 的 sn-p 中所做的那样。
    • @mjv: 你还怎么生成(*use Random *) 它?查看我的编辑。
    • @KMan。重用随机生成器只能确保 [出于某种奇怪的原因] 新生成的生成器不会碰巧具有相同的种子,因此不会生成相同的序列。为了防止连续产生两种相似的颜色,必须要么 a) 测试相似性并重新绘制,要么 b) 对各种组件使用特定的数学运算。然而,后一种选择可能会减少可能访问的颜色列表。
    【解决方案2】:
    Random r=new Random();
    var newCol=(r.Next(0,256)<<16)+(r.Next(0,256)<<8)+(r.Next(0,256));
    

    如果你想要更亮的颜色,考虑提高Next的最小参数

    【讨论】:

    • 为什么这种方法可以确保不会连续产生两种相似的颜色?
    • @Mjv:如果您在同一时间窗口内为每次使用创建一个新对象,您最终会得到几个具有相似种子的 Random 对象,结果相同。
    【解决方案3】:

    我看不到你的代码,但如果我猜对了代码的结构,这应该会有所帮助......它应该澄清为什么数字相同或接近它,因为我有一个类似的问题,这就是我如何解决它以及为什么我认为这是解决方案。

    我有一些代码生成的随机数看起来像这样(大大简化)

    for (some loop logic)
    {
      Random r = new Random();
      int myRandomNumber = Random.Next()
    }
    

    执行此操作时,它实际上为循环的一部分创建了完全相同的数字,(例如 8 次迭代)然后切换到重复 9 次迭代的新数字等。我通过将其更改为如下所示来解决它:

    Random r = new Random();
    for (some loop logic)
    {
      int myRandomNumber = Random.Next()
    }
    

    我相信其他人会更好地表达它,但是通过在循环之外声明 Random,Random 类的实例能够跟踪最后生成的随机数,并确保下一个实际上是随机的。通过将其置于循环中(如第一个示例所示),每次迭代都创建了一个新的 Random 对象,因此它只是使用任何逻辑(我假设是基于时间的)来生成一个随机数,而不知道不同的实例刚刚生成了相同的号码。

    男孩,我希望这是有道理的......这里已经很晚了,我没有解释清楚,但我认为您的问题可能是您正在循环逻辑中创建随机类的新实例,你需要在循环之外声明它。

    编辑 - 添加

    本文介绍了为什么会这样:

    http://geekswithblogs.net/kakaiya/archive/2005/11/27/61273.aspx

    【讨论】:

      【解决方案4】:

      我可能误解了这个问题...
      如果要避免随着时间的推移产生类似的颜色 sequences 的问题,请参阅 KMan 的响应,我认为这是第一个建议通过从同一生成器生成所有随机值(而不是生成一个新生成器)每次),就可以避免生成与以前使用的生成器具有相同种子的生成器的风险。

      如果要避免连续绘制两个“相似”颜色,则应使用以下响应。避免连续使用两种相似的颜色意味着要么

      • 使用一些数学逻辑(但存在所使用的函数可能无法像像样的随机数生成器那样覆盖所有可能颜色的光谱)
      • 绘制真正的随机颜色,但在它们被认为相似时拒绝它们(并重新尝试)。

      第二种方法是在下面的 sn-p 中说明的。
      风格是普通的,颜色接受标准有些武断,但这应该是一个好主意。
      此外,通过重用单个随机数生成器 (RNG),如果每次都以某种方式创建 RNG,并且偶然使用相同的种子,则可以避免重复序列的风险......

        const int minTotalDiff = 200;    // parameter used in new color acceptance criteria
        const int okSingleDiff = 100;    // id.
      
        int prevR, prevG, prevB;  // R, G and B components of the previously issued color.
        Random RandGen = null;
      
        public string GetNewColor()
        {
            int newR, newG, newB;
      
            if (RandGen == null)
            {
                RandGen = new Random();
                prevR = prevG = prevB = 0;
            }
      
            bool found = false;
            while (!found)
            {
                newR = RandGen.Next(255);
                newG = RandGen.Next(255);
                newB = RandGen.Next(255);
      
                int diffR = Math.Abs(prevR - newR);
                int diffG = Math.Abs(prevG - newG);
                int diffB = Math.Abs(prevB - newB);
      
                // we only take the new color if...
                //   Collectively the color components are changed by a certain
                //   minimum
                //   or if at least one individual colors is changed by "a lot".
                if (diffR + diffG + diffB >= minTotalDiff
                    || diffR >= okSingleDiff
                    || diffR >= okSingleDiff
                    || diffR >= okSingleDiff
                )
                  found = true;
              }
      
             prevR = newR;
             prevG = newG;
             prevB = newB;
      
            return String.Format("#{0:X2}{0:X2}{0:X2}", prevR, prevG, prevB);
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-20
        • 1970-01-01
        • 2015-11-07
        • 2012-02-19
        • 2013-04-02
        • 2018-04-02
        • 2021-05-23
        • 2011-03-09
        相关资源
        最近更新 更多