用从0到15 C#的唯一随机数填充2d数组



我不能用0-15的数字填充它,然后打乱数组,所以这不是的解决方案

我在C中使用过这段代码,但现在在C#中它不起作用,出于某种原因,这段代码让一些数字通过了do while。

Random r = new Random();
bool unique;
int rand_num;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
do
{
unique = true;
rand_num = r.Next(16);
for (int k = 0; k < 4; k++)
{
for (int l = 0; l < 4; l++)
{
if (numbers[k, j] == rand_num)
{
unique = false;
}
}
}
} while (!unique);

numbers[i, j] = rand_num;
}
}

}

如果可能的数字列表很小,就像在这种情况下一样,只需创建完整的列表并首先将其随机化,然后按照项目的出现顺序进行处理。在您的情况下,您可以将随机数放入队列,然后根据需要出列。

var r = new Random();
var numberQueue = new Queue<int>(Enumerable.Range(0, 16).OrderBy(n => r.NextDouble()));
var numbers = new int[4, 4];
for (var i = 0; i <= numbers.GetUpperBound(0); i++)
{
for (var j = 0; j <= numbers.GetUpperBound(1); j++)
{
numbers[i, j] = numberQueue.Dequeue();
}
}

我建议您使用Fisher Yates算法来生成不可重复的随机数序列。

那么,实现一个用这些数字填充二维数组的代码将是非常直接的。

List<int> seq = Enumerable.Range(0,16).ToList();
int[,] numbers = new int[4,4];
Random r = new();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int n = r.Next(0, seq.Count);
numbers[i,j] = seq[n];
seq.RemoveAt(n);
}
}

您所采用的方法可能会以连续循环结束,并且需要花费大量时间才能完成。

此外,使用嵌套for循环检查二维中的值也不高效。

您可以使用HashSet来跟踪唯一的值。在HashSet中搜索很快。

以下是我建议的代码方法。

var hashSet = new HashSet<int>();
var r = new Random();
var arr = new int[4, 4];
for(var i = 0;i<4;i++)
{
for(var j = 0;j<4;j++)
{
// Generate random value between 0 and 16.
var v = r.Next(0, 16);
// Check if the hashSet has the newly generated random value.   
while(hashSet.Contains(v))
{
// generate new random value if the hashSet has the earlier generated value.
v = r.Next(0, 16);
}
//Add value to the hashSet.
hashSet.Add(v);
// add value to the 2D array.
arr[i, j] = v;
}
}

我希望这将有助于解决你的问题。

当前方法的问题是,随着距离数组的末尾越来越近,您必须越来越努力地获得下一个随机值。

想象一下,你掷骰子,每次你都想获得一个独特的价值。第一次滚动时,任何结果都将是唯一的。下一次,你有1/6的机会得到一个已经获得的数字。然后是2/6的机会,等等,最后你的大部分掷骰子都是非唯一的。

在您的示例中,您有16个要用数字0到15填充的位置。这不是随机生成数字的情况,而是随机放置数字。我们如何用一副牌做到这一点?我们嘘他们!

我的建议是用唯一的序列值填充数组,然后对它们进行混洗:

Random random = new Random();
int dim1 = array.GetLength(0);
int dim2 = array.GetLength(1);
int length = dim1 * dim2;
for (int i = 0; i < length; ++i)
{
int x = i / dim1;
int y = i % dim1;
array[x, y] = i; // set the initial values for each cell
}
// shuffle the values randomly
for (int i = 0; i < length; ++i)
{
int x1 = i / dim1;
int y1 = i % dim1;
int randPos = random.Next(i, length);
int x2 = randPos / dim1;
int y2 = randPos % dim1;
int tmp = array[x1, y1];
array[x1, y1] = array[x2, y2];
array[x2, y2] = tmp;
}

此代码中的混洗基于

int[,] numbers = new int[4, 4];
Random r = new Random();
bool unique;
int rand_num;
List<int> listRandom = new List<int> { };
for ( int i = 0; i < 4; i++ )
{
for ( int j = 0; j < 4; j++ )
{
do
{
unique = false;

if (!listRandom.Contains( rand_num = r.Next( 0, 16 )))
{
listRandom.Add( rand_num );
numbers[i, j] = rand_num;
unique = true;
}
} while ( !unique );
}
}

最新更新