解决 从减少列表中选择随机项目的最有效方法?

Ren6175

成员
加入
2019年8月5日
消息
22
编程经验
Beginner
你好,用c#完成noob。在25年前编码。开始C#2天前以便有趣创建一个用于个人使用的应用程序。需要能够点击一个按钮并从列表中返回一个随机项目。然后,当我再次按下按钮时,返回除了第一个项目之外的不同项目,直到所有物品都耗尽。具体应用程序将选择一个怪物在棋盘游戏中激活另一个怪物等,直到圆角结束,然后它将重置。

我可以想到方法可以像分配号码一样,选择随机数。然后,当我再次点击按钮时,如果选择相同的号码,我可以拥有它“reroll”,直到它选择不同的数字。这似乎是难以承的,很可能会减缓程序。

有有效的方法吗?
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
使用 随机类 并生成您的数字基础 列表<T>.count 您的列表项目。如果您的列表有5项,则在零和六之间生成随机选择,如果您的第一个随机是一个,则从下一个随机呼叫中选择两个和六等等,从而排除该号码。发布你尝试的东西,也许我们可以更好地努力。对于从随机生成器收到的每个数字,将其存储在像列表中的集合中,然后比较下一个随机数,以确保其与先前生成的数字不同。

根据您需要的数字有多少,您可以将一系列数字添加到列表和随机重新排列该列表。然后,您可以迭代列表,然后您将有一个随机生成的数字列表。有一系列方法可以实现它。
 
Last edited:

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
我将建议与避免第二选项相同。您可以生成一个随机的数字列表并将它们放在队列中,然后逐个排除。我不会编写代码,但我建议看起来alumable.range,alumable.orderby,wandom.next和队列<T> class.
 

Ren6175

成员
加入
2019年8月5日
消息
22
编程经验
Beginner
我将建议与避免第二选项相同。您可以生成一个随机的数字列表并将它们放在队列中,然后逐个排除。我不会编写代码,但我建议看起来alumable.range,alumable.orderby,wandom.next和队列<T> class.
令人惊讶的是,我真的明白你在说什么。那是一个好主意。我会写它让你知道会发生什么。
 

Ren6175

成员
加入
2019年8月5日
消息
22
编程经验
Beginner
我能够根据您的建议和一堆在MSDN阅读中解决我的问题。它可能不是最优雅的解决方案,而且它并不完整,但它正在做我想要的事情。我刚刚创建了一个简单的Windows表单来测试它,所以这不是我的最终解决方案。每次我的队列都是空的,我也一直在收到错误,所以我刚刚写下它来隐藏队列空的按钮。如果您有任何其他建议,请随时发表评论。此外,我想标记这一点。我会试着弄清楚。谢谢。

C#:
列表<string> monster = new List<string>();
        Queue<string> mq = new Queue<string>();
        Random rnd = new Random();               
        public Form1()
        {
          
            InitializeComponent();
            
            monster.Add("goblin");
            monster.Add("dragon");
            monster.Add("spider");
                      
            for (int i = 0; i < monster.Count;)
            {
            int nextmonster = rnd.Next(monster.Count);
                mq.Enqueue((string)monster[nextmonster]);
                monster.RemoveAt(nextmonster);
            }
            int qcount = mq.Count;
            if (qcount == monster.Count)
            {
                textBox1.Text = " ";
            }
         
        }

        private void Button1_Click(object sender, EventArgs e)
        {
                      
            textBox1.Text = Convert.ToString(mq.Peek());
            mq.Dequeue();
            textBox2.Text = Convert.ToString(mq.Count());
            if (mq.Count == 0)
            {
                button1.Hide();
            }

        }
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
以下是我如何从列表中创建一个随机队列:
C#:
var rng = new Random();
var monsters = new List<Monster>();

// ...

var monsterQueue = new Queue<Monster>(monsters.OrderBy(m => rng.NextDouble()));
The Queue<T> constructor accepts an IEnumerable<T>, so there's no need to enqueue items separately. If you know that you will only need a certain number then you can append a Take call:
C#:
var monsterQueue = new Queue<Monster>(monsters.OrderBy(m => rng.NextDouble()).Take(requiredMonsterCount));
 

Ren6175

成员
加入
2019年8月5日
消息
22
编程经验
Beginner
好的,我理解你建议的一切,但如果我希望这个队列发生在Form2上怎么办?要解释,我已经使用了所有代码(来自其他线程)来生成2-5个随机怪物。然后,我的程序打开了一种新形式,每次按下按钮时,我需要循环浏览那些2-5个随机怪物。我有一个标有一个按钮"激活一个随机的怪物"还有另一个按钮,"Reset Monsters."所以每个怪物都会是"activated"以随机的顺序。无论如何,当我尝试添加怪物时,我收到错误,我不确定如何修复它。我应该完全重建form2的怪物课程吗? (对不起,如果这没有意义。你可以告诉我忘记它。)

编辑:或者我可以每次按下按钮Form2并在Form2上显示结果显示结果1上运行此代码
C#:
private void Button11_Click(object sender, EventArgs e)
        {
            var rng = new Random();
            var monsters = new List<Form1.Monster>();
            monsters.Add([U]goblinarcher[/U]);
            monsters.Add([U]ettins[/U]);

            var monsterQueue = new Queue<Form1.Monster>(monsters.OrderBy(m => rng.NextDouble()).Take(monsters.Count));
 
Last edited:

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
首先,请不要在代码片段的第一行上切断前导空间,并将其留在其他一线上。很多人似乎通过从第一个字符拖动到最后一个并且只需忽略导致空格不一致的代码复制代码。选择代码有三种更好的方法来避免此问题:

  1. 从代码的末尾拖动到开始。
  2. 通过在左边距离中选择代码作为完整行。
  3. 拖动时按下ALT键。
选项2将在每行保留领先的空格,包括第一个。选项1允许您通过拖动第一个字符来执行相同的操作。

最好没有超越缩进的领先空间,但如果您要包含它,那就更好地是一致的。也就是说,此站点上的代码编辑器将为您删除所有内容,如果只需选择所有代码和命中班+选项卡。

选项3通常是最好的。如果将光标放在块的第一个字符上并按下鼠标按钮,然后按下ALT键,可以拖动鼠标选择一个矩形块,将从每一行中排除空格而不是第一个块。对于堆栈溢出等地,您需要在每一行上有四个领先的空间,您可以明确地选择那种领先的空格,不再这样。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,731
地点
悉尼,澳大利亚
编程经验
10+
至于您的问题,您不应该在Form1类中声明怪物类以开始。除非仅在该类型内使用,否则不应该在另一个类型中声明一种类型。应将怪物类声明为名为Monster.cs的文件中的唯一类型。

如果Form2需要Form1中的数据,则Form1可以在创建Form2时将其传递给它,无论是设置属性还是作为构造函数参数。如果Form2只需要随机队列,那么这就是应该传递的。如果Form2需要整个列表,以便它可以创建自己的随机队列,然后这就是应该传递的。
 
最佳 底部