矿井清扫车游戏中c#中的非重复随机数

时间:2012-04-20 12:42:57

标签: c# .net

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

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

对此有任何建议

7 个答案:

答案 0 :(得分:2)

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

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

对于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);
}

答案 1 :(得分:1)

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

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

答案 2 :(得分: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达到零时退出循环。)

答案 3 :(得分: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--;
    }
  }

答案 4 :(得分:0)

如果您的网格是8x8,并且您想要随机选择一个未使用的单元格而不是拉随机数,直到您找到一个未使用的单元格,然后跟踪未使用的单元格的数量。说使用了8,留下55未使用。然后生成0到54之间的随机数。然后你必须计算,并找到第n个空单元格。

答案 5 :(得分:0)

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

此时,您可以为随机排雷生成0-63之间的数字。如果说值为10,您可以存储以便稍后抵消后续数字。你现在可以从0-62缩小你的范围,如果你拿出值16你想为你已经在它下面拉出的每个值加上+1(所以实际上在这种情况下使用17,但是方10已经从我们的集合中排除。)

答案 6 :(得分:-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个随机数,每个数字不同。