我的彩票计划错了吗?还是我太不走运了?

时间:2013-04-27 10:28:29

标签: c#

我做了一个彩票计划:http://yadi.sk/d/bBKefn9g4OC7s

以下是完整的源代码:http://yadi.sk/d/rnQMfrry4O8cu

Random rnd = new Random();
int[] loto;
loto = new int[7];

for (int f = 1; f <= 6; f++) {
    loto[f] = rnd.Next(1, 50); // Generating random number between 1-49

    for (int h = 1; h < f; h++) {
        if (loto[f] == loto[h]) { // Check with other numbers for the case of duplicate
            loto[f] = rnd.Next(1, 50); // If there is a duplicate create that number again
        }
    }
}

本节我在1-49

之间生成随机的6个不同的数字

我也想知道在这个例子中,嵌套循环会增加自发性吗?

我最多3-4次,这个程序错了,还是我太不走运了?

(请注意:那是我的第一个节目)

对于所有想要帮助我的人:我真的是编程的初学者(c#昨天| c ++ 3周我猜),如果你们澄清你在代码中的含义,它会很棒。 请不要给我极端的硬编码示例(我不想退出c#)

6 个答案:

答案 0 :(得分:3)

我认为除了for循环声明之外它是正确的:记住C#中的数组是从零开始的。因此循环应如下所示:

for (int f = 0; f < 7; f++)

甚至更好:

for (int f = 0; f < loto.Length; f++)

更新:我无法评论其他答案(声誉太少),因此我必须在此发布:

@Dan:只有一个循环不正确,因为在Loto中不允许两次具有相同的数字。在他的内部循环中,1342检查创建的随机数是否已经存在,因此将其遗漏是不正确的。

@James:由于1342刚刚开始编程,我认为没有必要使用静态字段。我猜他或她的全部代码都在Main方法中,因此使用静态变量没有任何好处。

答案 1 :(得分:3)

您的方法看起来不安全,因为在内循环中再次从Random获取值并不能保证它将返回非重复值。对于1-49的低值,您可以使用像这样的简单随机选择算法

    var numbers = new List<int>();
    for (int i = 1; i <= 49; i++) {
        numbers.Add(i);
    }
    Random r = new Random();
    var loto = new int[6];
    for (int f = 0; f < 6; f++) {
        int idx = r.Next(0, numbers.Count);
        loto[f] = numbers[idx];
        numbers.RemoveAt(idx);
    }

请注意,这在性能方面远非最佳解决方案,但如果您只在几秒钟或更长时间内运行一次,那么应该没问题。

答案 2 :(得分:1)

这里有一些问题 - 你有一个太多的循环开始,没有评论。

请参阅下面的(过度评论)示例:

// This is static so we don't recreate it every time.
private static Random _rnd;

static void Main(string[] args)
{
    _rnd = new Random();

    // You can declare and initialise a variable in one statement.
    // In this case you want the array size to be 6, not 7!
    Int32[] lotoNumbers = new Int32[6];

    // Generate 10 sets of 6 random numbers
    for (int i = 0; i < 10; i++)
    {
        // Use a meaningful name for your iteration variable
        // In this case I used 'idx' as in 'index'
        // Arrays in c# are 0-based, so your lotto array has
        // 6 elements - [0] to [5]
        for (Int32 idx = 0; idx < 6; idx++)
        {
            // Keep looping until we have a unique number
            int proposedNumber;
            do
            {
                proposedNumber = _rnd.Next(1, 50);
            } while (lotoNumbers.Contains(proposedNumber));

            // Assign the unique proposed number to your array
            lotoNumbers[idx] = proposedNumber;
        }
    }
}

你应该得到一个6元素的长数组,其中包含1到50之间的6个随机数。 希望有所帮助!

编辑: 同样值得注意詹姆斯的答案 - 如果你在循环中做上述事情,由于种子的使用方式,每次从Random获得相同的值。使用静态版本的Random会得到更好的结果。

答案 3 :(得分:1)

您不希望每次都重新创建Random的新实例,这可能是您每次都获得类似值的原因。更好的方法是创建一个static Random实例并在整个应用中使用它 - 这可以为您提供更实际的结果,例如。

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

static readonly Random rand = new Random();
...

List<int> lottoNumbers = new List<int>(6);
int drawnNumber = -1;
for (int i = 0; i < lottoNumbers.Count; i++) {
     do
     {
         drawnNumber = rand.Next(1, 50); // generate random number
     }
     while (lottoNumbers.Contains(drawnNumber)) // keep generating random numbers until we get one which hasn't already been drawn
     lottoNumbers[i] = drawnNumber; // set the lotto number 
}

// print results
foreach (var n in lottoNumbers)
    Console.WriteLine(n);

答案 4 :(得分:1)

为了便于测试,我已经为您保留了控制台日志和static void main。

您不需要两次迭代。另外 - 数组是基于0的,所以要么f必须等于0,要么小于7.我在下面等于0。

我创建了一个递归方法,它创建一个新值并检查数组contains是否为该值。如果它不包含它,它会添加它。但如果确实包含它,则该方法会调用自己来查找新值。它将继续执行此操作,直到找到新值。

Recursive methods是自称的方法。

,请不要尝试使用大于50的索引填充数组,因为您将获得无限循环。

private static readonly Random Rnd = new Random();

static void Main(string[] args)
{
    var loto = new int[7];

    for (int f = 0; f <= 6; f++)
    {
        var randomValue = GetRandomNumberNotInArr(loto);
        Console.WriteLine(randomValue);
        loto[f] = randomValue;
    }
    Console.Read();
}

/// <summary>
/// Finds a new random value to insert into arr. If arr already contains this another
///random value will be found.
/// </summary>
/// <param name="arr">arr with already found values</param>
/// <returns></returns>        
private static int GetRandomNumberNotInArr(int[] arr)
{
    var next = Rnd.Next(1, 50);
    return !arr.Contains(next) ? next : GetRandomNumberNotInArr(arr);
}     

答案 5 :(得分:0)

我可以看到你正在尝试模拟1到50之间的6个抽奖号码。

你的代码有一些逻辑错误,但不是修复它我建议以不同的方式做它。

有几种方法可以解决这个问题;一个常见的是:

Create an empty collection of numbers.
while there aren't enough numbers in the collection
    let randomNumber = new random number in the appropriate range
    if (randomNumber isn't already in the collection)
         add randomNumber to the collection

但是还有另一种可以很好地扩展的方法,所以我将演示这个(其他人可能已经写过另一种方法):

Add to a collection all the numbers you want to choose from
Randomly rearrange (shuffle) the numbers in the collection
Draw the required number of items from the collection

这几乎就是现实生活中的彩票。

要收集一个集合,我们可以使用Fisher-Yates Shuffle。这是一个实现:

/// <summary>Used to shuffle collections.</summary>

public class Shuffler
{
    /// <summary>Shuffles the specified array.</summary>
    /// <typeparam name="T">The type of the array elements.</typeparam>
    /// <param name="array">The array to shuffle.</param>

    public void Shuffle<T>(IList<T> array)
    {
        for (int n = array.Count; n > 1;)
        {
            int k = _rng.Next(n);
            --n;
            T temp = array[n];
            array[n] = array[k];
            array[k] = temp;
        }
    }

    private readonly Random _rng = new Random();
}

这是一个完整的可编辑示例。我在这个例子中避免使用Linq,因为我不想让你感到困惑!

using System;
using System.Collections.Generic;

namespace Demo
{
    public static class Program
    {
        private static void Main()
        {
            int[] lotoDraw = createDraw();

            Shuffler shuffler = new Shuffler();
            shuffler.Shuffle(lotoDraw); // Now they are randomly ordered.

            // We want 6 numbers, so we just draw the first 6:

            int[] loto = draw(lotoDraw, 6);

            // Print them out;

            foreach (int ball in loto)
                Console.WriteLine(ball);
        }

        private static int[] draw(int[] bag, int n) // Draws the first n items
        {                                           // from the bag
            int[] result = new int[n];

            for (int i = 0; i < n; ++i)
                result[i] = bag[i];

            return result;
        }

        private static int[] createDraw() // Creates a collection of numbers
        {                                 // from 1..50 to draw from.
            int[] result = new int[50];

            for (int i = 0; i < 50; ++i)
                result[i] = i + 1;

            return result;
        }
    }

    public class Shuffler
    {
        public void Shuffle<T>(IList<T> list)
        {
            for (int n = list.Count; n > 1; )
            {
                int k = _rng.Next(n);
                --n;
                T temp = list[n];
                list[n] = list[k];
                list[k] = temp;
            }
        }

        private readonly Random _rng = new Random();
    }
}