【问题标题】:What is wrong with my validation for checking that a number is in an array and then changing it so it is different?我检查一个数字是否在数组中然后更改它以使其不同的验证有什么问题?
【发布时间】:2015-07-06 08:56:42
【问题描述】:

我正在做一个宾果游戏,想检查一个号码是否已经被叫过,那么如果它有一个新的号码被生成但没有被叫过。 bool[] 数字; 随机 r;

    private void button1_Click(object sender, EventArgs e)
    {
        this.Numbers = new bool[90];
        this.r = new Random();
        int attempt = this.r.Next(0, 90);

        while (this.Numbers[attempt] == true)
        {
            attempt = this.r.Next(0, 90);
            this.Numbers[attempt] = true;
        }

        textBox1.Text += (attempt + 1).ToString() + " ";
        textcurrent.Text += textBox1.Text;
        textBox1.Clear();

    }

【问题讨论】:

  • 您在每次点击时重新创建布尔值数组。重新创建数组时,有关已选择哪些数字的任何信息都将丢失。您需要在 button_Click 方法之外创建数组(或至少保存它),以便下次单击时仍然可以使用结果。

标签: c# arrays validation error-handling boolean


【解决方案1】:

这是一个无限循环:

    while (this.Numbers[attempt] == true)
    {
        attempt = this.r.Next(0, 90);
        this.Numbers[attempt] = true;
    }

在检查while 循环是否继续之前,您已立即将this.Numbers[attempt] 设置为true

【讨论】:

  • 那是一个错过的副本,应该在循环之外。即使在外面,数字仍然会重复。
  • 实际上,由于Numbers 被初始化为bool 的数组,所有值都将是false,所以while 甚至不会运行一次。
  • 啊 - 不错@juharr。错过了!
【解决方案2】:

那个sn-p会导致无限循环:

 while (this.Numbers[attempt] == true)
 {
      attempt = this.r.Next(0, 90);
      this.Numbers[attempt] = true;
 }

注意,您将this.Numbers[attempt] 设置为true,然后检查它是否为true,因此循环永远不会结束。

我会采取另一种方法:

var notUsed = this.Numbers.Where(used => !used)
                 .Select((val, idx) =>
                      new 
                      {
                          Idx = idx,
                          Val = val
                      }).ToList();

if (!notUsed.Any())
{
    //case when all numbers used
}
else
{
    attempt = notUsed[this.r.Next(0, notUsed.Count)].Idx;
    this.Numbers[attempt] = true;
}

编辑: 评论中的 OP 说分配是在循环外完成的:

 while (this.Numbers[attempt] == true)
 {
      attempt = this.r.Next(0, 90);
 }

 this.Numbers[attempt] = true;

好吧,在这种方法中,无限循环也可能发生 - 当数组中的所有值都设置为 true 时。更重要的是,你可以为设置为true的元素生成attempt(当有很多元素设置为true时,理论上得到false元素的机会很小)。

【讨论】:

  • 那是一个错过的副本,应该在循环之外。即使有它,外面的数字仍然会重复
  • 但它从来没有进入循环,因为数组中的所有值都被初始化为false
  • @juharr 就像 OP 所说的那样(assigmnet 在循环之外) - 它会起作用。
【解决方案3】:

我会采取不同的方法。创建一个宾果号码列表,然后随机播放。然后,从顶部开始读取每个数字:

void Main()
{
    //Create a list of BINGO numbers and the shuffle it randomly.
    string letters = "BINGO";
    var bingoNumbers = Enumerable.Range(1, 75)
                                 .Select(n => string.Format("{0}{1}", letters[(int)Math.Ceiling(n / 15.0) - 1], n))
                                 .OrderBy(o => Guid.NewGuid())
                                 .ToList();

    foreach (var number in bingoNumbers)
    {
        Console.WriteLine(number);        
    }                            
}

Math.Ceiling(...) 位只是使用 Linq 创建宾果数字数组的一个技巧。如果您不想使用 Linq,也可以使用两个嵌套的 for 循环。

通过使用OrderBy(o => Guid.NewGuid()),它会打乱列表。这可能不是最好的洗牌方法。其他的,比如 Fisher-Yates 可能会更好。如果您想使用不同的洗牌方法,您可以省略OrderBy 行并使用您想要的任何算法进行洗牌。

顺便说一句,我注意到您使用 90 作为宾果号码的计数,但在传统游戏中只有 75。如果您不使用传统的 BINGO 号码,那么您可以在代码中替换BINGO 字母和范围值。

【讨论】:

    猜你喜欢
    • 2022-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    相关资源
    最近更新 更多