将随机数随机放入2d数组

时间:2014-05-15 07:19:17

标签: java random multidimensional-array

我有一个2d数组,我已将所有单元格设置为枚举类型State.SAFE。现在我想把这些单元格中的5个随机放到State.HIT中。所以我有:

Random objrandom = new Random();

State[][] playField = new State[5][5];
int w;

for (w = 0; w < 5; w++) {                  // set all states to SAFE first
    int h = 0;
    playField[w][h] = State.SAFE;

    for (h = 0; h < 5; h++) {
        playField[w][h] = State.SAFE;
    }
}

for (int i = 0; i < 5; i++) {           // try and set 5 states, randomly, to HIT
    playField[objrandom.nextInt(5)][objrandom.nextInt(5)] = State.HIT;
}

问题在于每次运行它时,所有单元格仍处于SAFE状态或Hit状态非随机分布,即每列的第一行或超过5个HIT状态。

3 个答案:

答案 0 :(得分:1)

如果您需要将5个单元格设置为HIT,则不能使用这样的随机数,因为您可能会多次获得相同的数字。我就是这样做的:

public static void main(String[] args) {
  State[][] playField = new State[5][5];

  setStateToSafe(playField);
  List<Integer> hits = getRandomIndices(5);
  applyHitStateToIndices(hits, playField);

  System.out.println(Arrays.deepToString(playField));
}

private static void setStateToSafe(State[][] playField) {
  for (int w = 0; w < playField.length; w++) {
    Arrays.fill(playField[w], State.SAFE);
  }
}
private static List<Integer> getRandomIndices(int n) {
  List<Integer> hits = new ArrayList<>();
  for (int i = 0; i < n * n; i++) hits.add(i);
  Collections.shuffle(hits);
  return hits.subList(0, n);
}
private static void applyHitStateToIndices(List<Integer> hits, State[][] playField) {
  for (int i = 0; i < hits.size(); i++) {
    int hitIndex = hits.get(i);
    int row = hitIndex / playField.length;
    int column = hitIndex % playField.length;
    playField[row][column] = State.HIT;
  }
}

答案 1 :(得分:0)

您的解决方案存在问题,因为行playField[objrandom.nextInt(5)][objrandom.nextInt(5)]=...可能会导致同一个单元格被引用两次。我无法确定这是否是您问题的原因,但它可能至少是其中的一部分。

如果您想解决此问题,则必须根据已更改的单元格的历史记录检查每个随机数,并在双击时请求不同的随机数。

我建议采用完全不同的方法。随机应该表示值将改变的概率,而不是请求改变值的单元格的行和列的索引。

换句话说:

  • 遍历数组中的所有单元格,生成介于0和1之间的随机值(使用nextDouble()
  • 如果该值低于此单元格应更改的概率(25个中的5个单元表示5/25 = 0.2概率= 20%),如果是,请将值设置为State.HIT,否则将其设置为State.SAFE

代码看起来像这样:

Random objrandom = new Random();

State[][] playField = new State[5][5];

for (int w = 0; w < 5; w++) {             
    for (int h = 0; h < 5; h++) {
        playField[w][h] = (objrandom.nextDouble() < 0.2d) ? State.HIT : State.SAFE;
    }
}

答案 2 :(得分:0)

如果小开销不会造成太大麻烦,那么你可以这样做:

创建一个用于表示字段上的点的类。

final class Point {
    public final int x;
    public final int y;

    public Point(final int x, final int y) {
        this.x = x;
        this.y = y;
    }
}

填写包含所有可能点的列表,并将其随机播放。

List<Point> points = new ArrayList<>();
for (int x = 0; x < 5; x++) {
    for (int y = 0; y < 5; y++) {
        points.add(new Point(x, y));
    }
}
Collections.shuffle(points);

现在第一个N(在你的情况下为5)点将被随机化,100%不一样。

for (int i = 0; i < 5; i++) {
    Point p = points.get(i);
    playField[p.x][p.y] = State.HIT;
}