змейка в двухмерном массиве java
Заполните массив числами увеличивающимися от 1 до n*n таким образом, чтобы последовательность чисел составляла змейку. Отобразить значения заполненного массива в консоль в виде таблицы. Программа должна корректно работать для любых значений n >= 2. Пример вывода результата для массива n = 3:
1 2 3
6 5 4
7 8 9
у меня вышло только:
1 2 3
7 8 9
6 5 4
final int n = 3;
final int range = n * n;
int[][] masiv = new int[n][n];
int x = 0;
int y = n - 1;
int ctr = 1;
while (ctr <= range) {
for (int i = 0; i < masiv.length; i++) {
if (masiv[x][i] == 0) {
masiv[x][i] = ctr++;
}
}
for (int i = 0; i < masiv.length; i++) {
if (masiv[i][y] == 1) {
masiv[i][y] = ctr++;
}
}
for (int i = masiv.length - 1; i >= 0; i--) {
if (masiv[y][i] == 0) {
masiv[y][i] = ctr++;
}
}
for (int i = masiv.length - 1; i >= 0; i--) {
if (masiv[i][x] == 0) {
masiv[i][x] = ctr++;
}
}
x++;
y--;
}
for (int i = 0; i < masiv.length; i++) {
for (int j = 0; j < masiv.length; j++) {
System.out.printf("%-2d ", masiv[i][j]);
}
System.out.println("");
}
Если можете оставьте комментарии чтоб можно было понять как это работает
Ответы (3 шт):
Мой вариант решения: идея в том, что при заполнении цикла мы, переходя к каждой строчке, определяем с помощью переменной start и значения а порядок заполнения. Если старт = 0, и а=1, то заполнение с лева на право. Если старт = n-1, и а=-1, то заполнение с права на лево. (где n - размерность массива). Слева на право мы заполняем четные строки, справа на лево, нечетные строки Остальное вроде должно быть понятным.
Сам код:
public class Snake {
public static void main(String[] args) {
int n = 7;
makeSnake(n);
}
public static void makeSnake(int n) {
int[][] array = new int[n][n];
int a = -1;
int count = 1;
for (int i = 0; i < n; i++) {
a *= -1;
int start = 0;
if (i % 2 != 0) start = n - 1;
else start = 0;
for (int j = start; (j < n) & (j >= 0); j += a) {
array[i][j] = count++;
}
}
printMatrix(array);
}
public static void printMatrix(int[][] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++)
System.out.print(array[i][j] + " ");
System.out.println();
}
}
}
Выход:
1 2 3 4 5 6 7
14 13 12 11 10 9 8
15 16 17 18 19 20 21
28 27 26 25 24 23 22
29 30 31 32 33 34 35
42 41 40 39 38 37 36
43 44 45 46 47 48 49
Process finished with exit code 0
Ну у меня такая идея (на примере n = 3):
генерируем табличку с числами так (слева номер строки):
0 | 1 2 3
1 | 4 5 6
2 | 7 8 9
а зачем строки с нечётным номером (выделен жирным) переворачиваем:
0 | 1 2 3
1 | 6 5 4 <-- перевернули
2 | 7 8 9
Вуаля! Ну только можно сразу перевёрнутыми генерировать, ну и в итоге получаем что-то такое:
public int[][] snake(int n) {
int[][] res = new int[n][0];
for (int i = 1, o = 0; i <= n * n; i += n, o++)
res[o] = (o % 2 == 0 ? IntStream.range(i, i + n) : IntStream.iterate(i + n - 1, j -> --j).limit(n)).toArray();
return res;
}
Если что-то непонятно (как часто бывает с тернарными операторами и потоками), то вот версия с объяснениями:
public int[][] snake_(int n) {
int[][] res = new int[n][0];
/*
переменные:
o - номер текущей строки;
i - стартовый индекс строки (начинается с 1, шаг - n);
*/
for (int i = 1, o = 0; i <= n * n; i += n, o++)
res[o] = (
// ЕСЛИ номер строки чётный
o % 2 == 0 ?
// ТО генерируем прямую строку в виде потока
IntStream.range(i, i + n) :
// ИНАЧЕ в обратном порядке (так же в виде потока, чтобы не писать лишний код)
IntStream.iterate(i + n - 1, j -> --j).limit(n))
// ну и в массив надо преобразовать
.toArray();
return res;
}
Ну вроде работает, протестировал на n от 1 до 7.
В квадратном массиве размером n x n будет содержаться n2 элементов. Поскольку индексация элементов массива начинается с 0, индексы и строк и столбцов будут находиться в диапазоне [0, n - 1].
Таким образом, для использования одного цикла при итерации по массиву следует взять последовательность чисел в диапазоне [0, n * n) или [0, n * n - 1], и такой индекс нужно будет перевести в индексы строк / столбцов при помощи операций целочисленного деления и остатка по модулю n соответственно:
int r = i / n;
int c = i % n;
arr[r][c] = i + 1; // сдвинуть значение на 1 в диапазон [1, n * n]
Оставшийся нюанс в том, что для реализации змейки в каждой строке с чётным индексом 0, 2,... индексы колонок идут в прямом порядке, а в строках с нечётным индексом - в обратном порядке:
r = 0; // для значений i = [0.. n - 1], c = i % n;
arr[r][0] = 1; arr[r][1] = 2; ... arr[r][n - 1] = n;
r = 1; // для значений i = [n.. 2 * n - 1], c = n - 1 - i % n;
arr[r][0] = 2 * n; arr[r][1] = 2 * n - 1; ... arr[r][n - 1] = n + 1;
Предоставленной информации должно быть достаточно для самостоятельного решения.
Полное решение:
public static int[][] snake(int n) {
int[][] arr = new int[n][n];
for (int i = 0, n2 = n * n; i < n2; ) {
int r = i / n;
int c = r % 2 == 0 ? i % n : n - 1 - i % n;
arr[r][c] = ++i;
}
return arr;
}