打印如下图案
16 15 14 13
5 4 3 12
6 1 2 11
7 8 9 10
要求可动态更改任意行数和列数
以下提供两种方法,个人觉得方法二的思路清晰些,因为使用递归每次填充一圈数据,直到填充完所有圈数据.还有,填充一圈数据时,没必要一个一个数字循环填写,其实只要循环首行的数据,就能计算出末行的数据,只要循环首列的数据,就能计算出末列的数据,这样就能节省一半的循环操作.
方法一:
/**
*
该程序可以更改打印几行几列
原理:通过定位行号与列号,逐个逐个从大往小赋值.
@author zhangle
*/
public static void main(String[] args) {
int row=4;//几行
int col=4;//几列
int[][] m=new int[row][col];//二维数组,用于存放结果
int n=col*row;//该矩阵中的最大值
int i=0;//行号
int j=1;//列号
int t_col=col;//列循环变量
int t_row=row;//行循环变量
while(true) {
//赋值某行
for(int k=0;k<t_col;k++) {
j+=-1;
m[Math.abs(i)][Math.abs(j)]=n--;
}
if(n==0) break;//如果值已赋完,则退出
t_col--;//列循环--
t_row--;//行循环--
//赋值某列
for(int k=0;k<t_row;k++) {
i+=-1;
m[Math.abs(i)][Math.abs(j)]=n--;
}
if(n==0) break;//如果值已赋完,则退出
j=-j;
i=-i;
}
print(m);
}
/**
* 打印二维数组
* @param a
*/
static void print(int[][] a) {
for(int i=0;i<a.length;i++) {
for(int j=0;j<a[i].length;j++) {
System.out.print(" "+a[i][j]);
}
System.out.println();
}
}
方法二:
原理:先填写最外一圈的数据,如果还有内圈数据,则递归调用本身继续填写内圈数据,直到填写完毕
public class Round {
public static void main(String[] args) {
int row=10; //几行
int col=10; //几列
int[][] a=new int[row][col];
fill(a,row,col,0,0);
print(a);
}
/**
* 填写最外一圈的数据,如果还有内圈数据,则递归调用本身继续填写内圈数据,直到填写完毕
* @param a
* @param row
* @param col
* @param i
* @param j
*/
private static void fill(int [][] a,int row,int col,int i,int j) {
int n=row*col;
for(int c=0;c<=col-1;c++) { //横向填充数值
a[i][j+c]=n-c; //在首行从左到右填值
if(row!=1)
a[i+row-1][j+c]=n-(col*2+row-3)+c; //如果不只1行,在末行从左到右填值
}
for(int r=0;r<row-2;r++) { //竖向填充数值
a[i+row-2-r][j]=a[i+row-1][j]-r-1; //在首列从下往上填值
if(col!=1) //如果不只1列,大末列从下往上填值
a[i+row-2-r][j+col-1]=a[i+row-1][j+col-1]+r+1;
else //否则覆盖首列数据
a[i+row-2-r][j]=a[i+row-1][j]+r+1;
}
if(row-2>0 && col-2>0) fill(a,row-2,col-2,i+1,j+1); //如果还没填完数据,则递归填写
}
/**
* 打印二维数组
* @param a
*/
private static void print(int[][] a) {
for(int i=0;i<a.length;i++) {
for(int j=0;j<a[0].length;j++) {
System.out.printf("%4d",a[i][j]);
}
System.out.println();
}
}
}