1

我正在创建一个宾果游戏,我正在使用Random在数组中生成随机数,int但我的问题是有时会在索引中再次使用一个数字。如何使索引中的数字唯一?

这是我的工作:

namespace Bingo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

    Random randNum1 = new Random();

    int[] random1 = new int[5];
    int qwe = 0;
    int i = 0;

    private void button1_Click(object sender, EventArgs e)
    {
        Class1 class1 = new Class1();
        class1.checker(this);

        if (label1.Text == label2.Text || label3.Text == label4.Text) {

            label2.Text = randNum1.Next(1, 15).ToString();
            label4.Text = randNum1.Next(1, 15).ToString();
        }

        if (label5.Text == label1.Text || label5.Text == label2.Text) {

            label5.Text = randNum1.Next(1, 15).ToString();            
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Class1 class1 = new Class1();

        class1.SetTwo(this);

        for (int i = 0; i < random1.Length; i++)
        {
            random1[i] = randNum1.Next(1, 15);

            label1.Text = random1[0].ToString();
            label2.Text = random1[1].ToString();
            label3.Text = random1[2].ToString();
            label4.Text = random1[3].ToString();
            label5.Text = random1[4].ToString();
        }
    }
}
4

4 回答 4

7

循环直到找到一个未使用的数字的问题在于,随着游戏的进行,您将花费越来越长的时间来找到一个有效的数字。从理论上讲,您的循环可能永远不会结束(无限可能,但仍然......)

最简单的事情是在真正的宾果游戏中发生的事情。从一个有限的集合开始,每次绘制时实际从集合中移除该项目。用您的初始可能性填充列表或任何其他动态索引容器,从 0 到列表大小随机选择一个索引,然后从列表中删除选择。

这将保证每个选择都会产生唯一的结果,没有循环。

于 2013-10-09T14:07:36.377 回答
2

我认为Scott Mermelstein的回答可能会有所帮助:

List<int> AvailableNumbers;
Random random; 
private void Form1_Load(object sender, EventArgs e)
{
    //Create a list of numbers, 1-14
    AvailableNumbers = Enumerable.Range(1, 14).ToList();
    random = new Random();

    label1.Text = GetNextNumber().ToString();
    label2.Text = GetNextNumber().ToString();
    label3.Text = GetNextNumber().ToString();
    label4.Text = GetNextNumber().ToString();
    label5.Text = GetNextNumber().ToString();
}
private int GetNextNumber()
{
    //Get a random index within the bounds of AvailableNumbers
    var nextIndex = random.Next(0, AvailableNumbers.Count);

    var nextNumber = AvailableNumbers[nextIndex];
    AvailableNumbers.RemoveAt(nextIndex);

    return nextNumber;
}
于 2013-10-09T14:28:03.857 回答
1

另一种方法是打乱排序的数字列表:

var numbers = Enumerable.Range(1, 15).OrderBy(i => Guid.NewGuid()).ToArray();

这是如何运作的?

  • 从整数列表开始 ( Enumerable.Range(1, 15) => [1, 2, 3, ..., 15])
  • 重新排序 ( OrderBy)
  • 带有“随机”索引Guid.NewGuid()

显然,这只有在Guid.NewGuid()不产生连续 GUID 的情况下才有效,但是,我认为默认值不会,因为这是 GUID 算法的第一个实现的安全问题。

(我从这里得到了使用 GUID 提示的改组: Randomize a List<T>

您可以使用其他更有效的方法来洗牌“牌组”,但对于宾果风格的应用程序,这应该可以正常工作。

另一个想法:

var rand = new Random();
var numbers = Enumerable.Range(1, 15).OrderBy(i => rand.Next()).ToArray();

由于起始列表中的元素是唯一的,因此可以保证结果重现该属性。

于 2013-10-09T14:16:15.793 回答
0

每次您获取一个新号码时,只需将其包围:

int num;
do
{
   num = randNum1.Next(1, 15);
}
while(random1.Contains(num))

random1[i] = num;

保证它是独一无二的

于 2013-10-09T14:05:14.247 回答