【问题标题】:How to select random items from ListBox without repeating如何从 ListBox 中选择随机项而不重复
【发布时间】:2017-07-19 09:10:26
【问题描述】:

我正在从ListBox 创建另一个随机生成器。我希望他们从listBox 中随机选择3 个项目,然后将其显示在TextBox 上。

Random random = new Random();
int a = random.Next(0, listBox1.Items.Count);
listBox1.SelectedItem = listBox1.Items[a];
int b = random.Next(0, listBox1.Items.Count);
listBox1.SelectedItem = listBox1.Items[b];
int c = random.Next(0, listBox1.Items.Count);
listBox1.SelectedItem = listBox1.Items[c];
listBox1.Select();
textBox1.Text = listBox1.Items[a] + ", " + listBox1.Items[b] + ", " + listBox1.Items[c];

问题有时是项目被选择了两次。 示例:

listBox 项:一、二、三、四、五、六

输出:一,六,一(“一”项被选中了两次,我不想这样做)

谢谢。

【问题讨论】:

  • 使用 enumerable.range 得到一个从 0 到 list.count - 1 的整数列表。查找一个洗牌算法。就像洗一​​副牌一样。

标签: c# random listbox


【解决方案1】:

我会这样改变你的逻辑:

  1. 获取3个随机数
  2. ListBox 中选择值

代码可能看起来像。当当前已被选中时,此代码将获得一个新的随机数并将其存储在 List<int> 中。

Random random = new Random();
List<int> numbers = new List<int>();
for (int i = 0; i < 3; i++)
{
    int number = random.Next(0, listBox1.Items.Count);
    while (numbers.Contains(number))
    {
        number = random.Next(0, listBox1.Items.Count);
    }
    numbers.Add(number);
}

然后

textBox1.Text = $"{listBox1.Items[numbers[0]]}, {listBox1.Items[numbers[1]]}, {listBox1.Items[numbers[2]]}";

如果您的 ListBox 中的项目少于 3 个,则会以无限循环结束,请注意这一点。

【讨论】:

  • 谢谢。顺便问一下,$ 中的textBox1.Text 是什么?
  • @Alfian String interpolation docs.microsoft.com/en-us/dotnet/csharp/language-reference/… 这样你就可以像这样在文本中添加变量$"this is text this is {variableName}"
  • @Alfian string.format 的简写形式欢迎您,当它工作时请接受答案 ;)
  • 谢谢大家的澄清。并感谢@MightyBadaboom 的回答并且它有效。您可以通过删除 textBox1.Text 上的 ( 来编辑您的帖子,因为这让我很困惑。
【解决方案2】:

你可以把它放在一个while循环中,只有当它们不匹配时才退出:

Random random = new Random();
int listBoxItemCount = listBox1.Items.Count;
var itemA = listBox1.Items[random.Next( listBoxItemCount )];
var itemB = listBox1.Items[random.Next( listBoxItemCount )];
var itemC = listBox1.Items[random.Next( listBoxItemCount )];

while(itemA == itemB || itemA == itemC || itemB == itemC)//While any pair matches
{ 
    itemB = listBox1.Items[ random.Next( listBoxItemCount ) ];
    itemC = listBox1.Items[ random.Next( listBoxItemCount ) ];
}

这将产生一个唯一的itemAitemBitemC

【讨论】:

  • @Downvote 请解释一下,以便我改进我的帖子。此解决方案确实有效
  • 我不是投反对票的人,我什至不能投赞成票,因为我还是新用户。顺便说一句,感谢您的回答,它有效。我将使用它作为临时解决方法,因为可能会有更好的答案。
  • @Alfian 我已经看到你不能投反对票 :) 我并不介意投票本身,只是我无法在没有反馈的情况下改进我的帖子,并且在获得银色 c# 徽章方面失去进展- _-
【解决方案3】:

见:Randomize a List<T>

我修改并制作了一个.net fiddle:https://dotnetfiddle.net/a7RJbm

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

public class Program
{
    public static void Main()
    {
        List<int> list = Enumerable.Range( 0, 6 ).ToList();
        list.Shuffle();
        int a = list[0];
        int b = list[1];
        int c = list[2];
        Console.WriteLine( a );
        Console.WriteLine( b );
        Console.WriteLine( c );
    }       

}

public static class ListShuffler
{
    private static Random rng = new Random();
    public static void Shuffle<T>(this IList<T> list)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rng.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }
}

洗牌的好处是您可以随机浏览列表中的所有项目。如果你想做超过 3 个项目,其他一些方法开始变得有点难看。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多