我正在制作一个基本的Deal或No Deal游戏,这样做我必须从阵列中随机挑选10个决赛选手,不需要重复。
我的结构和数组就像这样
public struct People
{
public string firstname;
public string lastname;
public int age;
}
class Program
{
public static People[] People1 = new People[40];
public static People[] Finalists1 = new People[10];
public static People[] Finalist1 = new People[1];
我的决赛选手方法就像这样
Random rand = new Random();
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, People1.Length);
Finalists1[i].lastname = People1[num].lastname;
Finalists1[i].firstname = People1[num].firstname;
Finalists1[i].age = People1[num].age;
}
如何在阵列中维护10个人的同时消除重复的条目?
答案 0 :(得分:5)
由于初始数组不包含重复项,因此您可以按随机顺序对其进行排序,并选择10
个顶级项目:
Finalists1 = People1
.OrderByDescending(item => 1) // if people have some points, bonuses etc.
.ThenBy(item => Guid.NewGuid()) // shuffle among peers
.Take(10) // Take top 10
.ToArray(); // materialize as an array
如果人们被选中进入决赛并非完全随机(例如选手可以获得积分,奖金等),请更改.OrderByDescending(item => 1)
,例如
.OrderByDescending(item => item.Bonuses)
如果您不想使用 Linq ,则可以从People
中抽取urn
而不返回:
private static Random random = new Random();
...
List<People> urn = new List<People>(People1);
for (int i = 0; i < Finalists1.Length; ++i) {
int index = random.Next(0, urn.Count);
Finalists1[i] = urn[index];
urn.RemoveAt(index);
}
答案 1 :(得分:2)
您可以保存已绘制的列表或哈希数字集。然后再次掷骰子以获得另一个随机数。
Random rand = new Random();
HashSet<int> drawnNumbers = new HashSet<int>();
for (int i = 0; i < Finalists1.Length; i++)
{
do
{
num = rand.Next(0, People1.Length);
}
while (drawnNumbers.Contains(num));
Finalists1[i] = People1[num];
}
答案 2 :(得分:0)
您可以将Finalists1
的类型更改为HashSet,但不允许重复。
然后将循环更改为
while(Finalists1.Length < 10)
{
// random pick from array People1 (you don't need to create a new one)
num = rand.Next(0, People1.Length);
var toAdd = People1[num];
// add to hash-set. Object won't be added, if already existing in the set
Finalists1.Add(toAdd);
}
如果您确实需要创建要添加到哈希集的新对象,则可能需要覆盖类Equals
的{{1}}方法。
答案 3 :(得分:0)
将People1中的每个选定元素与数组的末尾交换,并递减数组结束索引,以便您只选择下一次迭代中剩下的内容。
People tempPerson = new People;
int lastElem = People1.length - 1;
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, lastElem + 1);
Finalists1[i] = People1[num];
//swap last entry in People1 with People1[num]
tempPerson = People1[num];
People1[num] = People1[lastElem];
People1[lastElem] = tempPerson;
lastElem--;
}
很抱歉,如果出现语法错误,我现在主要使用Java和C#。
BTW您不必单独设置字段,因为每个数组都存储Person类型的对象。
答案 4 :(得分:0)
您可以对人员数组进行分组,并选择不同的方式。 如果您使用列表,则可以从列表中删除人员 `var peopleArray = new People [40];
var peopleCollection = peopleArray.GroupBy(p => new { p.age, p.firstname, p.lastname }).Select(grp => grp.FirstOrDefault()).ToList();
var finalists = new People[10];
var rand = new Random();
for (var i = 0; i < finalists.Length; i++)
{
var index = rand.Next(0, peopleCollection.Count);
var person = peopleCollection[index];
finalists[i].lastname = person.lastname;
finalists[i].firstname = person.firstname;
finalists[i].age = person.age;
peopleCollection.Remove(person);
}
答案 5 :(得分:0)
洗牌并取前10个,例如
People1.Shuffle();
Finalists1= People1.Take(10).ToArray();
您可以从StackOverflow中找到随机播放代码或搜索“Fisher-Yates shuffle C#”以下方法取自This SO Post。阅读答案以获取有关为什么不使用GUID等的更多信息。
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}