C# 如何:为列表中的每个条目分配唯一编号?

C# 如何:为列表中的每个条目分配唯一编号?,c#,list,random,xna,tile,C#,List,Random,Xna,Tile,我想要的是做瓷砖。这些瓷砖大约有30个应该在游戏中有一个固定的位置,但每次我加载游戏时,它们应该有随机数,这会影响它们的图形外观 我知道如何使用随机方法给一个瓷砖一个数字来改变它的外观,但是如果我要制作一个存储多个瓷砖位置的列表,我不知道如何使用随机方法。如何为列表中的每个条目分配一个唯一的随机数 我的游戏需要这个,你在平面2D地图中,随机生成你要探索的房间、宝藏房间、竞技场房间等。如果你有这样的东西: public class Tile { public int Number {g

我想要的是做瓷砖。这些瓷砖大约有30个应该在游戏中有一个固定的位置,但每次我加载游戏时,它们应该有随机数,这会影响它们的图形外观

我知道如何使用随机方法给一个瓷砖一个数字来改变它的外观,但是如果我要制作一个存储多个瓷砖位置的列表,我不知道如何使用随机方法。如何为列表中的每个条目分配一个唯一的随机数


我的游戏需要这个,你在平面2D地图中,随机生成你要探索的房间、宝藏房间、竞技场房间等。

如果你有这样的东西:

public class Tile 
{
     public int Number {get;set;} 
     ...
}
var numbers = Enumerable
  .Range(1, tilesList.Count)  // generates list of sequential numbers
  .OrderBy(x => Guid.NewGuid()) // shuffles the list
  .ToList();

for (int i = 0; i < tiles.Count; i++) 
{
    tile[i].Number = numbers[i];
}
您可以这样做:

public class Tile 
{
     public int Number {get;set;} 
     ...
}
var numbers = Enumerable
  .Range(1, tilesList.Count)  // generates list of sequential numbers
  .OrderBy(x => Guid.NewGuid()) // shuffles the list
  .ToList();

for (int i = 0; i < tiles.Count; i++) 
{
    tile[i].Number = numbers[i];
}
它所做的是,计算下一个guid比当前guid小多少倍以及大多少倍。在理想情况下,应该有相同数量的较大和较小的next guid,这将表明这两个事件当前guid和next guid是独立的。还测量了时间,只是为了确保它不会太慢

使用1000万个guid获得了以下结果:

较大:5000168 较小:4999832 秒数:00:00:01.1980686

另一个测试是直接比较Fisher-Yates和Guid shuffling:

static void Main(string[] args)
    {
        var numbers = Enumerable.Range(1, 7).ToArray();
        var originalNumbers = numbers.OrderBy(x => Guid.NewGuid()).ToList();

        var foundAfterListUsingGuid = new List<int>();
        var foundAfterListUsingShuffle = new List<int>();

        for (int i = 0; i < 100; i++)
        {
            var foundAfter = 0;
            while (!originalNumbers.SequenceEqual(numbers.OrderBy(x => Guid.NewGuid())))
            {
                foundAfter++;                    
            }

            foundAfterListUsingGuid.Add(foundAfter);

            foundAfter = 0;

            var shuffledNumbers = Enumerable.Range(1, 7).ToArray();
            while (!originalNumbers.SequenceEqual(shuffledNumbers))
            {
                foundAfter++;
                Shuffle(shuffledNumbers);
            }

            foundAfterListUsingShuffle.Add(foundAfter);
        }

        Console.WriteLine("Average matching order (Guid): {0}", foundAfterListUsingGuid.Average());
        Console.WriteLine("Average matching order (Shuffle): {0}", foundAfterListUsingShuffle.Average());
        Console.ReadKey();
    }

    static Random _random = new Random();

    public static void Shuffle<T>(T[] array)
    {
        var random = _random;
        for (int i = array.Length; i > 1; i--)
        {
            // Pick random element to swap.
            int j = random.Next(i); // 0 <= j <= i-1
            // Swap.
            T tmp = array[j];
            array[j] = array[i - 1];
            array[i - 1] = tmp;
        }
    }
通过直接比较,我的意思是,我正在产生一个无序序列,然后尝试再次无序以得到相同的序列,并且假设,我需要越多的尝试来产生相同的序列,随机性越好,这在数学上是不必要的,我认为这是过于简单化了

因此,对于1000次迭代以减少误差的小集合,结果是:

平均匹配订单Guid:5015.097 平均匹配顺序洗牌:4969.424

因此,如果我的指标正确,Guid会更好地执行事件:

在10000次迭代中,它们更接近:

平均匹配订单Guid:5079.9283 平均匹配顺序洗牌:4940.749


因此,在我看来,对于目前游戏中使用的洗牌室号,GUI是合适的解决方案。

如果您有以下内容:

public class Tile 
{
     public int Number {get;set;} 
     ...
}
var numbers = Enumerable
  .Range(1, tilesList.Count)  // generates list of sequential numbers
  .OrderBy(x => Guid.NewGuid()) // shuffles the list
  .ToList();

for (int i = 0; i < tiles.Count; i++) 
{
    tile[i].Number = numbers[i];
}
您可以这样做:

public class Tile 
{
     public int Number {get;set;} 
     ...
}
var numbers = Enumerable
  .Range(1, tilesList.Count)  // generates list of sequential numbers
  .OrderBy(x => Guid.NewGuid()) // shuffles the list
  .ToList();

for (int i = 0; i < tiles.Count; i++) 
{
    tile[i].Number = numbers[i];
}
它所做的是,计算下一个guid比当前guid小多少倍以及大多少倍。在理想情况下,应该有相同数量的较大和较小的next guid,这将表明这两个事件当前guid和next guid是独立的。还测量了时间,只是为了确保它不会太慢

使用1000万个guid获得了以下结果:

较大:5000168 较小:4999832 秒数:00:00:01.1980686

另一个测试是直接比较Fisher-Yates和Guid shuffling:

static void Main(string[] args)
    {
        var numbers = Enumerable.Range(1, 7).ToArray();
        var originalNumbers = numbers.OrderBy(x => Guid.NewGuid()).ToList();

        var foundAfterListUsingGuid = new List<int>();
        var foundAfterListUsingShuffle = new List<int>();

        for (int i = 0; i < 100; i++)
        {
            var foundAfter = 0;
            while (!originalNumbers.SequenceEqual(numbers.OrderBy(x => Guid.NewGuid())))
            {
                foundAfter++;                    
            }

            foundAfterListUsingGuid.Add(foundAfter);

            foundAfter = 0;

            var shuffledNumbers = Enumerable.Range(1, 7).ToArray();
            while (!originalNumbers.SequenceEqual(shuffledNumbers))
            {
                foundAfter++;
                Shuffle(shuffledNumbers);
            }

            foundAfterListUsingShuffle.Add(foundAfter);
        }

        Console.WriteLine("Average matching order (Guid): {0}", foundAfterListUsingGuid.Average());
        Console.WriteLine("Average matching order (Shuffle): {0}", foundAfterListUsingShuffle.Average());
        Console.ReadKey();
    }

    static Random _random = new Random();

    public static void Shuffle<T>(T[] array)
    {
        var random = _random;
        for (int i = array.Length; i > 1; i--)
        {
            // Pick random element to swap.
            int j = random.Next(i); // 0 <= j <= i-1
            // Swap.
            T tmp = array[j];
            array[j] = array[i - 1];
            array[i - 1] = tmp;
        }
    }
通过直接比较,我的意思是,我正在产生一个无序序列,然后尝试再次无序以得到相同的序列,并且假设,我需要越多的尝试来产生相同的序列,随机性越好,这在数学上是不必要的,我认为这是过于简单化了

因此,对于1000次迭代以减少误差的小集合,结果是:

平均匹配订单Guid:5015.097 平均匹配顺序洗牌:4969.424

因此,如果我的指标正确,Guid会更好地执行事件:

在10000次迭代中,它们更接近:

平均匹配订单Guid:5079.9283 平均匹配顺序洗牌:4940.749


因此,在我看来,对于游戏中当前使用的洗牌房间号,guid是合适的解决方案。

制作一个由30个连续数字组成的数组,镜像您的瓷砖数组。然后从中选择您喜欢的阵列洗牌解决方案,例如:


然后平铺[23]的编号将是numberArray[23]。

制作一个由30个连续数字组成的数组,镜像平铺数组。然后从中选择您喜欢的阵列洗牌解决方案,例如:


然后,平铺[23]的编号将为numberArray[23]。

请查看。如果我没看错你的问题,它非常容易使用,应该对你很有用。

请看下面的。如果我没有看错你的问题,它非常容易使用,应该对你很有用。

I通过你的列表创建,并使用键值对分配随机值。随机数不必是唯一的。在我看来,这里关于随机数的90%的问题是三件事之一:1糟糕地播种RNG,就像将srand放入循环中一样。2需要添加到常量和的随机数,3将随机数生成与洗牌混淆。这是第3条-您不希望平铺具有随机位置,而是希望平铺具有随机顺序的所有标准位置。将这些坐标保留在一个数组中,将其洗牌,然后将其应用于平铺。我创建列表并使用键值对分配随机值。随机数不必是唯一的。在我看来,这里关于随机数的90%的问题是三件事之一:1糟糕地播种RNG,就像将srand放入循环中一样。2兰特
om数字加上一个常数和,3混淆随机数生成与洗牌。这是第3条-您不希望平铺具有随机位置,而是希望平铺具有随机顺序的所有标准位置。将这些坐标保持在一个数组中,将它们洗牌,然后将它们应用到瓷砖上。但是,如果我想使用Random,因为我可能需要多个宝藏室,我该怎么做呢?我知道这不是唯一的,但我所说的唯一是指列表中的所有条目都应该有相同的编号。@新手-唯一是指列表中的所有条目都应该有相同的编号-这是唯一的一个完全相反的定义,我认为:只要可枚举。范围创建从1到titleList的数字列表。长度,该列表中的所有数字都是唯一的。然后我使用Guid来洗牌它们,它提供了足够不可预测的序列,仍然保持唯一性。我已经解决了很多问题,但我仍然不明白最后一段代码对for循环做了什么。我有这样的变量:room_position list跟踪向量2,room_键入一个int来描述房间的属性。所以我想随机选择哪个数字得到哪个位置。var似乎占据了所有的房间,并根据房间的数量给它们一个随机数,对吗?GUI不是随机的,它们只是唯一的,不应该用作随机数生成器。@Servy>我用一些非常简单的随机性测试更新了我的答案。但是,如果我想使用Random,因为我可能需要多个宝藏室,我会怎么做?我知道这不是唯一的,但我所说的唯一是指列表中的所有条目都应该有相同的编号。@新手-唯一是指列表中的所有条目都应该有相同的编号-这是唯一的一个完全相反的定义,我认为:只要可枚举。范围创建从1到titleList的数字列表。长度,该列表中的所有数字都是唯一的。然后我使用Guid来洗牌它们,它提供了足够不可预测的序列,仍然保持唯一性。我已经解决了很多问题,但我仍然不明白最后一段代码对for循环做了什么。我有这样的变量:room_position list跟踪向量2,room_键入一个int来描述房间的属性。所以我想随机选择哪个数字得到哪个位置。var似乎占据了所有的房间,并根据房间的数量给它们一个随机数,对吗?GUI不是随机的,它们只是唯一的,不应该用作随机数生成器。@Servy>我用一些非常简单的随机性测试更新了我的答案。我不只是发布一个指向答案的链接,请将答案的详细信息包含在您的帖子中,并附上相应的归属。重要的是,答案必须是独立的,虽然使用链接是可以的,但读者不应该被要求通过链接来获得问题的答案。与其只发布答案的链接,还不如在文章中包含答案的详细信息,并根据情况加上归因。重要的是,答案应该是独立的,虽然使用链接是可以的,但读者不应该被要求通过链接来获得问题的答案。