我有一个函数,它创建一个数组并将其洗牌,但我不知道如何以我想要的方式调用它

时间:2015-04-25 14:29:29

标签: c#

这是一个函数,它创建一个数组并将其从LoLim填充到HiLim,然后将该顺序洗牌:

 static Random random = new Random();        //these two statics are to make a random number, i need the first static to be outside the function so it won't keep making the same random number
    static int RandomNum(int LoLim, int HiLim, int index)
    {
        var nums = Enumerable.Range(LoLim,HiLim).ToArray();  //these next lines make an array from LoLim to HiLim and then shuffle it 

        for (int i = 0; i < nums.Length; i++)
        {
            int randomIndex = random.Next(nums.Length);
            int temp = nums[randomIndex];
            nums[randomIndex] = nums[i];
            nums[i] = temp;

        }
        return nums[index];

然后我有这个函数创建一个二维数组然后打印它。它使用RandomNum但不是我想要的方式,但我不知道如何使它工作。

static Array Matrix(int Rows, int Columns) //this is a function to initiate and print the array
    {
        int[,] LotteryArray = new int[Rows, Columns];

        for (int i = 0; i < LotteryArray.GetLength(0); i++)  //this is a series of loops to initiate and print the array
        {
            for (int j = 0; j < LotteryArray.GetLength(1); j++)
            {
                LotteryArray[i, j] = RandomNum(1,46,j);       //the numbers are supposed to be between 1 and 45, so i tell it to do it until 46 because the upper limit is exclusive
                Console.Write("{0,3},", LotteryArray[i, j]); //the {0,3} the 3 is three spaces after the first variable
            }
            Console.WriteLine();
        }
        return LotteryArray;

基本上我希望它每个“行”调用RandomNum,这样它可以随机播放数组,然后我希望它拉出nums[index]并将其打印出来。我想要这个的原因是我每行都可以有非重复的随机数。例如:我不希望行是“21,4,21,5,40,30”。

3 个答案:

答案 0 :(得分:1)

您的代码存在各种问题,即使它有效。 “逻辑”问题是:

  • 您使用的是有偏差的洗牌算法。您应该使用Fisher-Yates进行正确的改组(参见http://blog.codinghorror.com/the-danger-of-naivete/
  • 如果你真的想做一个“好”的改组,你不应该使用Random数字生成器,而是使用RNGCryptoServiceProvider(参见http://www.cigital.com/papers/download/developer_gambling.php,但请注意这一点是一个比另一个问题小得多的问题...如果生成的随机播放都是等概率的话,我们可以通过“稍微不那么随机”的改组来生存。
  • 你错误地使用了Enumerable.Range()
  • 的论据

您的编码问题不同:您必须在某处保存洗牌行,然后获取第一个值。

这里我使用一个类用shuffling封装一行

public class ShuffledRow
{
    public static readonly Random Random = new Random();
    public readonly int[] Row;

    /// <summary>
    /// Generates and shuffles some numbers
    /// from min to max-1
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max">Max is excluded</param>
    public ShuffledRow(int min, int max)
    {
        int count = max - min;
        Row = Enumerable.Range(min, count).ToArray();
        Shuffle(Row);
    }

    private static void Shuffle<T>(T[] array)
    {
        // Fisher-Yates correct shuffling
        for (int i = array.Length - 1; i > 0; i--)
        {
            int j = Random.Next(i + 1);
            T temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }
}

另一个问题:除非你知道自己在做什么,否则不要在C#中使用多维数组。可悲的是,他们是.NET的混蛋和被遗忘的孩子。使用锯齿状数组(数组数组)。

public static int[][] Matrix(int rows, int columns)
{
    int[][] lottery = new int[rows][];

    for (int i = 0; i < lottery.Length; i++)
    {
        ShuffledRow sr = new ShuffledRow(1, 46);

        lottery[i] = sr.Row;
        Array.Resize(ref lottery[i], columns);
        Console.WriteLine(
            string.Join(",", lottery[i].Select(
                x => string.Format("{0,3}", x))));
    }

    return lottery;
}

public static int[][] Matrix(int rows, int columns)
{
    int[][] lottery = new int[rows][];

    for (int i = 0; i < lottery.Length; i++)
    {
        ShuffledRow sr = new ShuffledRow(1, 46);

        lottery[i] = new int[columns];

        for (int j = 0; j < columns; j++)
        {
            lottery[i][j] = sr.Row[j];
            Console.Write("{0,3},", lottery[i][j]);
        }

        Console.WriteLine();
    }

    return lottery;
}

我准备了两个版本的 Matrix 函数,一个与你正在使用的版本更相似,一个更LINQ和“高级”。

答案 1 :(得分:0)

生成随机数确实不使用随机函数,请使用:

private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
    // Main method. 
    public static int[] generateTrueRandomOK()
    {
        const int totalRolls = 2500;
        int[] results = new int[50]; //Number of random ints that you need

        // Roll the dice 25000 times and display 
        // the results to the console. 
        for (int x = 0; x < totalRolls; x++)
        {
            byte roll = RollDice((byte)results.Length);
            results[roll - 1]++;
        }

        return results;
    }

    // This method simulates a roll of the dice. The input parameter is the 
    // number of sides of the dice. 

    public static byte RollDice(byte numberSides)
    {
        if (numberSides <= 0)
            throw new ArgumentOutOfRangeException("numberSides");

        // Create a byte array to hold the random value. 
        byte[] randomNumber = new byte[1];
        do
        {
            // Fill the array with a random value.
            rngCsp.GetBytes(randomNumber);
        }
        while (!IsFairRoll(randomNumber[0], numberSides));
        // Return the random number mod the number 
        // of sides.  The possible values are zero- 
        // based, so we add one. 
        return (byte)((randomNumber[0] % numberSides) + 1);
    }

    private static bool IsFairRoll(byte roll, byte numSides)
    {
        // There are MaxValue / numSides full sets of numbers that can come up 
        // in a single byte.  For instance, if we have a 6 sided die, there are 
        // 42 full sets of 1-6 that come up.  The 43rd set is incomplete. 
        int fullSetsOfValues = Byte.MaxValue / numSides;

        // If the roll is within this range of fair values, then we let it continue. 
        // In the 6 sided die case, a roll between 0 and 251 is allowed.  (We use 
        // < rather than <= since the = portion allows through an extra 0 value). 
        // 252 through 255 would provide an extra 0, 1, 2, 3 so they are not fair 
        // to use. 
        return roll < numSides * fullSetsOfValues;
    }

答案 2 :(得分:0)

您可以使用锯齿状数组:

Random random = new Random(); 
int[] RandomNum(int LoLim, int HiLim)
{
    var nums = Enumerable.Range(LoLim,HiLim).ToArray();

    for (int i = 0; i < nums.Length; i++)
    {
        int randomIndex = random.Next(nums.Length);
        int temp = nums[randomIndex];
        nums[randomIndex] = nums[i];
        nums[i] = temp;

    }

    return nums;
}

int[][] Matrix(int Rows, int Columns)
{
    int[][] LotteryArray = new int[Rows][];

    for (int i = 0; i < LotteryArray.Length; i++)
    {
        LotteryArray[i] = RandomNum(1,46);

        for (int j = 0; j < LotteryArray[i].Length; j++)
        {
           Console.Write("{0,3},", LotteryArray[i][j]);
        }

        Console.WriteLine();
    }

    return LotteryArray;
}