限制c#中的随机类

时间:2011-03-27 21:18:52

标签: c# random

我想对c#中的随机类进行限制,比如从2个范围生成随机变量而不重复它? 例如:

Xpoints[i] = random.Next(0, 25);
Ypoints[i] = random.Next(0, 12);

其中25我们12是图像尺寸所以我需要这个图像中的所有像素但随机?任何建议如果我使用这个代码我没有得到一些像素和一些像素重复

6 个答案:

答案 0 :(得分:3)

看看Fisher-Yates算法:

http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

它易于实施,并且运行良好。

它会混洗一个数字数组,如果你想确保没有重复,你可以按顺序访问它们。

答案 1 :(得分:3)

更新简化,不需要任何特定的哈希[1]

更新广泛使用通用的SimpleShuffle扩展方法

        public static IEnumerable<T> SimpleShuffle<T>(this IEnumerable<T> sequence)
        {
            var rand = new Random();
            return sequence.Select(i => new {i, k=rand.Next()})
                .OrderBy(p => p.k)
                .Select(p => p.i);
        }

我除了downvoting(喊叫?抱歉:) :) Anx的回答我认为显示我的代码会是什么样的更好:

using System;
using System.Linq;
using System.Collections.Generic;

namespace NS
{
    static class Program
    {
        public static IEnumerable<T> SimpleShuffle<T>(this IEnumerable<T> sequence)
        {
            var rand = new Random();
            return sequence.Select(i => new {i, k=rand.Next()}).OrderBy(p => p.k).Select(p => p.i);
        }

        public static void Main(string[] args)
        {
            var pts = from x in Enumerable.Range(0, 24)
                from y in Enumerable.Range(0, 11)
                select new { x, y };

            foreach (var pt in pts.SimpleShuffle())
                Console.WriteLine("{0},{1}", pt.x, pt.y);
        }
    }
}

我完全解决了我之前关于如何通过实现我们不需要哈希来生成好哈希的问题,除非:

  • 一个。源包含(逻辑)重复
  • 湾我们需要那些具有等效排序顺序的
  • ℃。并且我们希望每次都有相同的“随机”排序顺序(确定性散列)

一个。和b。在这种情况下是假的,c。甚至会成为一个问题(取决于OP需要什么)。所以现在,没有任何附加条件,不再担心性能(即使是非理性的担忧),

祝你好运!

[1]顺便说一句,这使得整个事情变得更加灵活,因为我不再需要将字符串表示为字节[];你现在可以随意洗牌。

答案 2 :(得分:1)

您可能希望在索引列表上使用随机算法(例如,对于X轴,值为0..24的25个元素)而不是随机的。

设计随机并不保证不重复任何值;重复很可能。

另见:Optimal LINQ query to get a random sub collection - Shuffle(寻找Fisher-Yates-Durstenfeld解决方案)

答案 3 :(得分:1)

我也相信,随机不应该是可预测的,我们甚至不应该预测这个值不会重复。

但我认为有时可能需要随机获取非重复的int,因为我们需要维护状态,比如Random类的特定实例,返回所有值。

这是我刚想到的算法的一个小而快速和脏的实现,我不确定它是否与Fisher-Yates解决方案相同。我刚刚编写了这个类,以便您可以使用它而不是System.Random类。

所以它可以帮助您满足您的要求,根据您的需要使用NonRepeatingRandom以下课程......

class NonRepeatingRandom : Random
{
    private HashSet<int> _usedValues = new HashSet<int>();
    public NonRepeatingRandom()
    {

    }
    public NonRepeatingRandom(int seed):base(seed)
    {

    }
    public override int Next(int minValue, int maxValue)
    {
        int rndVal = base.Next(minValue, maxValue);
        if (_usedValues.Contains(rndVal))
        {
            int oldRndVal = rndVal;
            do
            {
                rndVal++;
            } while (_usedValues.Contains(rndVal) && rndVal <= maxValue);
            if (rndVal == maxValue + 1)
            {
                rndVal = oldRndVal;
                do
                {
                    rndVal--;
                } while (_usedValues.Contains(rndVal) && rndVal >= minValue);
                if (rndVal == minValue - 1)
                {
                    throw new ApplicationException("Cannot get non repeating random for provided range.");
                }
            }
        }
        _usedValues.Add(rndVal);
        return rndVal;
    }
}

请注意,只有“Next”方法被覆盖,而不是其他方法,如果你想要,你也可以覆盖“Random”类的其他方法。

聚苯乙烯。在点击“发布你的答案”之前,我看到了sehe的答案,我喜欢他的整体想法,但要哈希2个字节,创建一个16字节的哈希?还是我错过了什么?在我的代码中,我使用HashSet,它使用int的GetHashCode方法的实现,这只是int本身的值,因此没有散列的开销。但我可能会错过一些观点,因为它是在印度的凌晨3点59分:)

希望它有助于salamonti ......

答案 4 :(得分:0)

随机数的重点是你得到重复。

但是,如果要确保不这样做,请在选择下一个数字之前从阵列中删除最后选择的值。所以如果你有一个数字列表:

index = random.Next(0, originallist.Length);
radomisedList.Add(originalList[index]);
originalList.RemoveAt(index);

该列表将被随机化,但不包含重复。

答案 5 :(得分:0)

不是通过两个一维数组创建图像,而应通过一个二维矩阵创建图像。每次获得新的随机坐标时,检查是否已设置该像素。如果是,则重复该像素的过程。