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

本文关键字:计划 彩票 错了 我的 | 更新日期: 2023-09-27 18:11:03

我做了一个彩票程序: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#)

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

您的方法看起来不安全,因为在内部循环中再次从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);
    }

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

我认为这是正确的,除了for循环声明:记住,c#中的数组是从零开始的。因此循环应该是这样的:

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

或者更好:

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

更新:我无法评论其他答案(太不信誉),因此我不得不在这里发布:

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

@James:由于1342刚刚开始编程,在我看来没有必要使用静态字段。我猜他或她在Main方法中有他的整个代码,所以使用静态变量没有任何好处。

这里有几个问题-您在开始时使用了太多的循环,并且没有注释。

请看下面这个(过度注释)示例:

// 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个元素的长数组,其中包含6个1到50之间的随机数。希望这对你有帮助!

编辑:同样值得注意的是James的回答——如果你在循环中执行上述操作,由于种子的使用方式,你每次都会从Random获得相同的值。使用静态版本的Random会得到更好的结果。

您不希望每次都重新创建Random的新实例,这可能是每次都获得相似值的原因。更好的方法是创建Randomstatic实例,并在整个应用程序中使用它-这应该会给你更真实的结果,例如

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);

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

您不需要为此进行两次迭代。另外,数组是从0开始的,所以f要么等于0,要么小于7。

我创建了一个递归方法,它创建一个新值并检查数组是否包含值。如果它不包含它,它将添加它。但如果它确实包含它,则该方法调用自身来查找新值。它将继续这样做,直到找到一个新值。

递归方法是调用自己的方法。不要尝试用this来填充索引大于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);
}     

我可以看出您正在尝试模拟抽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洗牌。下面是一个实现:

/// <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();
    }
}