package com.java;
public class PrintFangZhen {
/**
* 打印等长的二维数组,要求从1開始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
* 1 2 3 4
* 12 13 14 5
* 11 16 15 6
* 10 9 8 7
*
*/
public static void main(String[] args) {
int n = 4;
if (n <= 0) {
System.out.println("n必须大于0!");
return;
}
int[][] arr = method(n);
traverse(arr);
}
/**
* 按从1開始的自然数由方阵的最外圈向内螺旋方式地顺序排列,并存到一个二维数组中
*
* @param n
* 这个方阵的边长
* @return 一个二维数组
*/
public static int[][] method(int n) {
// 定义一个储存数字的二维数组
int[][] arr = new int[n][n];
// 定义一个count计数,count即为数组中的元素
int count = 0;
int i = 0, j = 0;
while (true) {
// 当n为1的时候,直接存入数组中并结束循环
if (n == 1) {
arr[0][0] = 1;
break;
}
// 当一个元素的上、右、下、左的值不是0的时候;或者是当其上和右有值,而且左和下越界时,结束循环
if ((i - 1 >= 0 && j + 1 <= n - 1 && i + 1 <= n - 1 && j - 1 >= 0
&& arr[i - 1][j] != 0 && arr[i][j + 1] != 0
&& arr[i + 1][j] != 0 && arr[i][j - 1] != 0)
|| (j - 1 < 0 && i + 1 > n - 1 && arr[i - 1][j] != 0 && arr[i][j + 1] != 0)) {
break;
}
// 假设上面的角标越界了,而且右面的角标没越界,则向右移动
if ((i - 1 < 0 && j <= n - 1)) {
arr[i][j++] = ++count;
} else if (j + 1 > n - 1 && i + 1 <= n - 1) {
// 假设右面的角标越界了,而且以下的角标没越界,则向下移动
if (j == n) {
j--;
}
i++;
arr[i][j] = ++count;
} else if (i + 1 > n - 1 && j - 1 >= 0) {
// 假设以下的角标越界了,而且左边的角标没越界,则向左移动
arr[i][--j] = ++count;
} else if (j - 1 < 0 && i - 1 >= 0 && arr[i - 1][j] == 0) {
// 假设左边的角标越界了,而且上边的角标没越界,而且上边的元素的值为0,则向上移动
arr[--i][j] = ++count;
} else {
// 假设不是边缘,则按其它情况来计算
if (arr[i - 1][j] != 0 && arr[i][j + 1] == 0) {
// 假设右面元素的值为0,而且上面元素的值不为0,则向右移动
arr[i][++j] = ++count;
} else if (arr[i + 1][j] == 0) {
// 假设以下元素的值为0,则向下移动
arr[++i][j] = ++count;
} else if (arr[i][j - 1] == 0) {
// 假设左面元素的值为0,则向左移动
arr[i][--j] = ++count;
} else if (arr[i - 1][j] == 0) {
// 假设上面元素的值为0,则向上移动
arr[--i][j] = ++count;
}
}
}
return arr;
}
/**
* 遍历二维数组
*
* @param arr
* 一个待遍历的二维数组
*/
public static void traverse(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}