2

我正在用 c# 尺寸(8 x 8)开发扫雷游戏。难度级别增加/减少网格上的地雷数量。

我使用随机类(设置最小值,最大值;)生成随机单元格编号。我面临的问题是,随机对象不断重复相同的编号。我试图通过维护我存储的本地列表来解决这个问题生成的唯一随机数。下次我调用 Next() 时,我会根据本地列表检查它是否已经存在。如果数字已经存在,我会继续调用 Next(),直到我得到一个新号码这是唯一的并且不存在于列表中。但这本身看起来并不是一个好的解决方案,因为有时生成新列表需要花费大量时间。

请对此有任何建议

4

7 回答 7

2

即使您使用相同的随机数生成器,重复值也是可能的。

避免这种情况的一种方法是生成一个可能值的列表,并使用生成的随机数来访问此列表中的值(用作索引)并减少此列表,因为您可以找到放置地雷的位置。

对于 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);
}
于 2012-04-20T13:01:00.650 回答
1

看起来您想要基于固定数量的单元格 (8,8) 的 shuffle,例如Fisher -Yates shuffle。这将保证任何坐标只出现一次(而不是重复使用 Random.Next() 可以多次绘制相同的数字),并且坐标的出现顺序是随机的。

初始化一个包含所有单元格坐标的数组,打乱数组并维护下一个“随机”单元格的索引,返回索引偏移处的单元格并增加索引。

于 2012-04-20T12:54:06.083 回答
1

与其选择应该有地雷的槽位,不如遍历槽位并计算那里应该有地雷的概率。这个实现变得非常简单,因为你只需要一个循环:

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(改进空间:如果你不需要初始化所有的槽,你可以在达到零时退出循环。)

于 2012-04-20T12:55:05.180 回答
1

首先计算地雷的数量和空地。

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--;
    }
  }
于 2012-04-20T12:56:40.690 回答
0

如果您的网格是 8x8,并且您想随机选择一个未使用的单元格而不是拉随机数,直到您找到一个未使用的单元格,然后跟踪未使用的单元格的数量。假设 8 个已使用,剩下 55 个未使用。然后生成一个介于 0 和 54 之间的随机数。然后您必须数数,并找到第 n 个空单元格。

于 2012-04-20T12:54:01.607 回答
0

以更线性的方式考虑问题可能会更容易。而不是说二维数组... Squares[8][8] 将其视为一维数组 Squares[64]。

此时,您为随机地雷放置生成一个介于 0-63 之间的数字。如果说该值为 10,您可以存储以备后用以抵消后续数字。您现在可以将范围从 0-62 缩小,如果您拉出值 16,您希望为您已经在其下方拉出的每个值添加 +1(因此在这种情况下实际使用 17,但正方形 10 已经从我们的集合中排除)。

于 2012-04-20T12:54:12.047 回答
-1

在没有看到任何代码的情况下,很难了解事情的要点,但据我所知,您有以下几点:

一个多维数组[8][8] 用于游戏的网格布局,你现在是在尝试随机放置地雷吗?

您需要保留一个 Random 实例来生成数字,否则您将一遍又一遍地获得相同的数字。像这样的东西

private readonly Random randomNumber = new Random();

for(int i = 0; i < 10; i++)
{
    Console.WriteLine(this.randomNumber.Next(1, 10));
}

这将生成 10 个随机数,每一个都不同。

于 2012-04-20T12:54:09.690 回答