扫雷游戏的 c# 中的非重复随机数
本文关键字:随机数 游戏 扫雷 | 更新日期: 2023-09-27 18:31:42
我正在用C#开发一个维度(8 x 8)的扫雷游戏。难度级别会增加/减少网格上的地雷数量。
我使用一个随机类(最小值,最大值设置;)以生成随机单元格编号。我面临的问题是,随机对象不断重复相同的数字。我试图通过维护一个本地列表来解决此问题,该列表存储生成的唯一随机数。下次我调用Next()时,我会根据本地列表检查它,看看它是否已经存在。如果该号码已经存在,我会继续调用 Next(),直到我得到一个唯一的新号码并且不存在于列表中。但这本身看起来不是一个好的解决方案,因为有时生成新列表需要花费大量时间。
请对此提出任何建议
即使您使用相同的随机数生成器,也可以重复值。
避免这种情况的一种方法是生成一个可能值的列表,并使用生成的随机数访问此列表中的值(用作索引),并在找到放置地雷的位置时减少此列表。
对于 8 X 8 示例,您有 64 个可能的位置
List<int> possibleValues = new List<int>();
for (int i = 0; i < 64; i++)
{
possibleValues[i] = i;
}
List<int> result = new List<int>();
Random r = new Random();
int numberOfMines = 50; //say you want to put 50 mines there
for (int i = 0; i < numberOfMines; i++)
{
int indice = r.Next(possibleValues.Count);
int value = possibleValues[indice];
possibleValues.Remove(value);
result.Add(value);
}
看起来你想要一个基于固定数量的单元格(8,8)的随机播放,例如费舍尔-耶茨随机播放。这将保证任何坐标只出现一次(而不是重复使用 Random.Next(),在那里您可以多次绘制相同的数字),并且坐标的出现顺序是随机的。
初始化一个包含单元格所有坐标的数组,打乱数组并维护下一个"随机"单元格的索引,在索引的偏移量处返回单元格并增加索引。
首先计算地雷的数量和空字段。
Random rand=new Random();
int mines=GetMinesFromDifficulty(...);
int empty=TotalFields-mines;
然后对于每个字段:
for(int y=0;y<height;y++)
for(int x=0;y<height;y++)
{
if(random.Next(mines+empty) < mines))
{
field[x,y]=Mine;
mines--;
}
else
{
field[x,y]=Empty;
empty--;
}
}
与其选择地雷应该在的地方的插槽,不如循环遍历插槽并计算那里应该有地雷的概率。实现这一点变得非常简单,因为你只需要一个循环:
bool[] mines = new bool[64];
int cnt = 12;
Random rnd = new Random();
for (int i = 0; i < mines.Length; i++) {
if (rnd.Next(mines.Length - i) < cnt) {
mines[i] = true;
cnt--;
}
}
(改进空间:如果您不需要初始化所有插槽,则可以在cnt
达到零时退出循环。
如果您的网格是 8x8,并且您希望随机选择一个未使用的单元格,而不是抽取随机数直到您遇到未使用的单元格,请跟踪未使用的单元格的数量。假设已使用8个,剩余55个未使用。然后生成一个介于 0 和 54 之间的随机数。然后,您必须计数并找到第 n 个空单元格。
以更线性的方式思考问题可能更容易。而不是说 2D 数组...正方形[8][8]将其视为一维数组Squares[64]。
此时,您为随机地雷放置生成一个介于 0-63 之间的数字。如果假设值为 10,则可以存储以供以后使用以抵消后续数字。您现在可以将范围从 0 缩小到 62,如果您拉出值 16,您可能希望为已经在它下面拉出的每个值添加 +1(因此在这种情况下实际使用 17,但平方 10 已从我们的集合中排除)。
没有看到任何代码,很难理解事情的要点,但据我所知,你有以下内容:
一个用于游戏网格布局的多维数组 [8][8],您现在正在尝试随机放置地雷?
您需要保留一个 Random 实例来生成数字,否则您将一遍又一遍地获得相同的数字。像这样的东西
private readonly Random randomNumber = new Random();
for(int i = 0; i < 10; i++)
{
Console.WriteLine(this.randomNumber.Next(1, 10));
}
然后这将生成 10 个随机数,每个随机数都不同。