This solution is maybe a bit long, but effective. I tried to solve this with java streams:
First what you need is to convert 2D array into a simple IntStream. The simplest way could be something like:
Arrays.stream(arr).flatMapToInt(intArr -> Arrays.stream(intArr));
Our stream now looks like this:
{5,0,0,0,5,0,4,0,0,4,7,9...}
Next you need to get stream with values like key-value (index-value in this case). This is quite hard with streams and there is maybe an easier solution, but I created a KeyValue class with auto-incrementation of index:
class KeyValue {
int index;
int value;
static int nextIndex;
public KeyValue(int v) {
this.index = nextIndex;
nextIndex++;
this.value = v;
}
public static void restart() {
nextIndex = 0;
}
}
Now it is easy to convert our stream to index-value items. Call:
.mapToObj(KeyValue::new)
Now our stream looks like this:
{KeyValue[i=0 v=5], KeyValue[i=1 v=0], KeyValue[i=2 v=0], KeyValue[i=3 v=0]...}
Now filter zeros and collect stream to an array:
.filter(kv -> kv.value == 0).toArray(KeyValue[]::new);
Whole code to create an array is:
KeyValue[] zeros = Arrays
.stream(arr)
.flatMapToInt(intArr -> Arrays.stream(intArr))
.mapToObj(KeyValue::new)
.filter(k -> k.value == 0)
.toArray(KeyValue[]::new);
Now it is pretty easy to get a random value from the array:
int ourResult = zeros[random.nextInt(zeros.length)].index;
Whole code will look like this:
int[][] arr = new int[][]
{
{5, 0, 0, 5, 0},
{4, 0, 0, 4, 7},
{9, 0, 4, 8, 9},
{0, 8, 4, 0, 1}
};
Random random = new Random();
KeyValue.restart();
KeyValue[] zeros = Arrays
.stream(arr)
.flatMapToInt(intArr -> Arrays.stream(intArr))
.mapToObj(KeyValue::new)
.filter(k -> k.value == 0)
.toArray(KeyValue[]::new);
int ourResult = zeros[random.nextInt(zeros.length)].index;
Happy coding :)