将随机数随机放入二维数组中



我有一个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;
}

问题是每次我运行它时,所有的细胞要么仍然处于安全状态,要么命中状态是非随机分布的,即每列的第一行或有超过5个命中状态。

如果你需要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;
  }
}

您的解决方案有一个问题,因为行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;
    }
}

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

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

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;
}

相关内容

  • 没有找到相关文章