Как выбрать три случайных пятна в двумерном массиве? - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть некоторый код, который создаст двумерный логический массив, выберет 3 случайных пробела и присвоит им значение true. Прямо сейчас мой код может выбрать 2 одинаковых пробела и присвоить им значение true, поэтому возможно, что я не получу 3 пробела, которые будут истинными. Как я могу изменить свой код, чтобы выбрать 3 случайных и уникальных пробела из моего массива?

boolean mineLocations[][] = new boolean[rows][cols];

int rRow = random.nextInt(rows);
int rCol = random.nextInt(cols);
mineLocations[rRow][rCol] = true;

rRow = random.nextInt(rows);
rCol = random.nextInt(cols);
mineLocations[rRow][rCol] = true;

rRow = random.nextInt(rows);
rCol = random.nextInt(cols);
mineLocations[rRow][rCol] = true;

Ответы [ 5 ]

1 голос
/ 10 апреля 2019

Вот решение с использованием Random и IntStream / forEach

boolean mineLocations[][] = new boolean[rows][cols];

int count = rows * cols;
new Random().ints(3, 0, rows * cols - 1).forEach( rand -> {
  int y = rand / rows;
  int x = rand % cols;
  mineLocations[x][y] = true;
});
1 голос
/ 10 апреля 2019

Сначала вы можете убедиться, что создали три уникальные координаты, случайным образом сгенерировав их и сохранив их в наборе, если размер набора не достигнет трех.Затем выполните итерацию по набору, верните координаты и инициализируйте массив.Вы можете закодировать его примерно так:

public static void main(String[] args) throws Exception {
    Set<String> coordSet = new HashSet<>();
    Random random = new Random();
    int rows = 3;
    int cols = 3;
    boolean mineLocations[][] = new boolean[rows][cols];

    while(coordSet.size() < 3) {
        int rRow = random.nextInt(rows);
        int rCol = random.nextInt(cols);
        coordSet.add(String.format("%d:%d", rRow, rCol)); // set always stores unique values hence no need to check for existing data
    }
    System.out.println(coordSet);

    coordSet.stream().forEach(x -> {
        String[] pair = x.split(":");
        mineLocations[Integer.parseInt(pair[0])][Integer.parseInt(pair[1])] = true;
    });     
}

Несколько случайных значений, напечатанных этим кодом в независимом исполнении,

[1:0, 0:2, 2:0]
[1:0, 2:0, 2:1]
[1:0, 0:1, 1:2]
[2:0, 2:1, 2:2]

Как видите, ни одна из каждой координаты не совпадает водна запись.

Здесь я сохранил координаты в виде строки, разделенной двоеточиями, но если вы хотите лучшую реализацию, вы можете создать собственный класс для хранения координат X и Y, так как это будет чище.

Как вы можете заметить, этот код будет работать в целом для любых значений строк и столбцов, которые вы можете инициализировать, и количество выбранных случайных точек также можно изменить, просто изменив значение 3 в условии while.

1 голос
/ 10 апреля 2019

Вот пример, как вы можете это сделать:

boolean mineLocations[][] = new boolean[rows][cols];
Random random = new Random();

int counter = 0;
while (counter < 3) { //looping while 3 distinct cells are not set to true
    int rRow = random.nextInt(rows);
    int rCol = random.nextInt(cols);

    if (!mineLocations[rRow][rCol]) {
        mineLocations[rRow][rCol] = true;
        counter++; //increasing the counter only when a new cell is set to true
    }
}

Логика проста: на каждой итерации вы генерируете новую координату. Затем вы проверяете, является ли значение по этой координате все еще ложным (еще не было изменено). И если это так, установите значение true.

Повторите это N раз.

1 голос
/ 10 апреля 2019

Как насчет создания отдельного метода для установки начальных случайных местоположений мин?

Например:

import java.util.Arrays;
import java.util.Random;

class Main {
  public static void main(String[] args) {
    int rows = 3, cols = 4;
    boolean mineLocations[][] = new boolean[rows][cols];
    System.out.println(Arrays.deepToString(mineLocations));
    placeMines(3, mineLocations);
    System.out.println(Arrays.deepToString(mineLocations));
  }

  private static void placeMines(int numMines, boolean mineLocations[][]) {
    int n = mineLocations.length;
    int m = mineLocations[0].length;
    if (numMines > n * m) {
      System.err.println("Can't place more mines than slots avalaible on the grid!");
      return;
    }
    int minesPlaced = 0;
    while (minesPlaced != numMines) {
      int randomRow = new Random().nextInt(n);
      int randomCol = new Random().nextInt(m);
      if (!mineLocations[randomRow][randomCol]) {
        mineLocations[randomRow][randomCol] = true;
        minesPlaced++;
      }
    }
    return;
  }
}

Пример вывода:

[[false, false, false, false], [false,false, false, false], [false, false, false, false]]
[[false, false, false, true], [false, true, false, false], [false, true, false, false]]
1 голос
/ 10 апреля 2019

Вы можете попробовать что-то вроде:

//if already true, keep rolling new row and col,
//then when you find one that isn't, the loop breaks, and
//you set it to true
while(mineLocations[rRow][rCol])
{
   //try again
   rRow = random.nextInt(rows);
   rCol = random.nextInt(cols);
}
mineLocations[rRow][rCol] = true;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...