明确了方阵数字是螺旋递增以后,发现每一个“口”字型的一圈数字正好闭合且连续递增。所以解题思路是由“口”字型的
递增依次向内嵌套。先填充最外层“口”字型的一圈数字,接着填充次外层……最后填充最内层的四个数。由一些较简单的画图可以
看出,层数的奇偶会影响到最内层的填充。当为奇数时,最内层只剩一个数字需要填充。所以奇数层需要单独考虑。
先是填充顶部的(n-1)个数字,接着由顶部的最后一个数字开始向下,填充右部的(n-1)个数字,接着是底部的(n-1)个和左部的(n-1)个,这样就填充了最外层的一圈“口”字型数字。(定一个静态的成员变量,从1开始,每填充一次,自增一次),依照同样的方法填充次外层,第三层……一直到偶数层的最内层。
*
填充的算法是:每一层未填充的个数是(n-2*l)个,n是总层数,l是当前层数,为了便于数组的计算,这里层数也是从0开始,
* 即l=0时是第一层。每一轮填充都是从(l,l)开始的。←---字母l,不是数字1。 但是每一层都需要为邻边的填充留一个地方,比如填充顶部的时候,需要留出一个位置作为填充右部的开始,所以真正需要填充的个数是(n-2*l-1)。
* 当层数为l时,每一边的起始坐标分别是(上,右,下,左):
* (l,l)
* (l,n-l-1)
* (n-1,n-1)
* (n-1,l)
*
* 当层数为偶数层的时候,恰好最后一层每一边填充一个数。当层数为奇数层的时候,最后一层只剩一个数未填充(n-2*l-1)=0,所以需要手动将最后一个数填充进方阵中。
*
* 最后将填充好的方阵打印在控制台上。以上就是本题的思路和解决办法。
public static void main(String[] args) {
System.out.println("输入方阵的层数(层数过大方阵的可读性会变差):");
Scanner sc = new Scanner(System.in);
//层数
int n = sc.nextInt();
//填充的数字,没填充一次自增一次
int var = 1;
//方阵的中间,表示需要循环的次数,或者需要填充的“口”字个数。
int limit = (int)Math.ceil(n/2.0) - 1;
//定义一个n×n的矩阵来存储填充的数字
int[][] metrix = new int[n][n];
//嵌套的层数,循环limit次---limit个“口”
for(int l=0;l<=limit;l++){
/*填充顶部
* 填充这一层时,i(横坐标)不变,j(纵坐标)递增,直到填充了(n-2*l-1)个数后退出这一层循环。
*/
for(int i=l,j=i;j<l+(n-2*l-1);j++){
metrix[i][j] = var++;
}
/*填充右边
* 填充这一层时,j(纵坐标)不变,i(横坐标)递增,直到填充了(n-2*l-1)个数后退出这一层循环
*/
for(int j=n-l-1,i=l;i<l+(n-2*l-1);i++){
metrix[i][j] = var++;
}
/*填充底部
* 填充这一层时,i(横坐标)不变,j(纵坐标)递减,直到填充了(n-2*l-1)个数后退出这一层循环。
*/
for(int i=n-l-1,j=i;j>(n-l-1)-(n-2*l-1);j--){
metrix[i][j] = var++;
}
/*填充左边
* 填充这一层时,j(纵坐标)不变,i(横坐标)递减,直到填充了(n-2*l-1)个数后退出这一层循环
*/
for(int i=n-l-1,j=l;i>(n-l-1)-(n-2*l-1);i--){
metrix[i][j] =var++;
}
}
//当层数是奇数时,以上算法并没有处理处于最中间的数,这里需要单独处理。
if(n%2==1 && metrix[limit][limit] == 0){
metrix[limit][limit] = var;
}
//打印
printMetrix(metrix);
}
//打印矩阵,如果层数过高,需要将数字间的间隔加大(比如加更多的\t),否则可读性级差。
public static void printMetrix(int[][] metrix){
for(int i=0;i<metrix.length;i++){
for(int j=0;j<metrix[i].length;j++){
System.out.print(metrix[i][j] + "\t\t");
}
System.out.println();
}
}