4

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

4

6 回答 6

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

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

于 2013-04-27T11:18:55.843 回答
3

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

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

甚至更好:

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

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

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

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

于 2013-04-27T10:45:50.587 回答
1

为了轻松测试它,我为您留下了控制台日志和静态 void main。

您不需要为此进行两次迭代。另外 - 数组是基于 0 的,所以 f 必须等于 0 或小于 7。我在下面选择了等于 0。

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

递归方法是调用自身的方法。不要尝试用它填充索引大于 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);
}     
于 2013-04-27T10:57:57.967 回答
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 元素长数组,其中包含 6 个 1 到 50 之间的随机数。希望有帮助!

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

于 2013-04-27T10:45:41.350 回答
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);
于 2013-04-27T10:45:46.433 回答
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();
    }
}
于 2013-04-27T10:47:05.483 回答