再说说坐标移动的原理: 上图的表格用二维数组表示为:int[][] intArray = new int[5][5]; 第一个下标代表y轴,第二个下标代表x轴,假如1是放在坐标1、1的位置,完成螺旋状的步骤如下: 1、首先确定数字1的位置为 1 1 2、右移放2,右移即x轴加1,用代码表示为intArray[1][1+1] = 2; 3、下移放3,下移即y轴加1,用代表码示为intArray[1+1][2] = 3; 4、左移放4,左移即x轴减1,用代码表示为intArray[2][2-1] = 4; 4、左移放5,左移即x轴减1,用代码表示为intArray[2][1-1] = 5; 。。。依此类推 如用变量来移动数组的下标代码为: switch(direction) { case UP: intArray[--y][x] = num++; break; // 上,Y坐标减1 case DOWN: intArray[++y][x] = num++; break; // 下,Y坐标加1 case LEFT: intArray[y][--x] = num++; break; // 左,X坐标减1 case RIGHT: intArray[y][++x] = num++; break; // 右,x坐标加1 } 现在最关键的就是先找出1的坐标位置了,自已多画几个图,多看看就能找到规律了,如果是顺时针先右移,那么1的坐标中x轴与y轴的值相等。假如要求n的螺旋图,则1的位置它的计算公式为:(n + 1) / 2 - 1 后来我想到要做一个全能的,就是上面说的两种大变化8种微变化,其实最关键的是要找到1的位置,其它的万变不离其宗,通过观察,我发1的位置都是相对某个角的坐标是对称的,有思路的可以自己挑战一下,实在做不出来可以看我后面的代码,代码并不多80行左右,效果如下,如果你觉得看了有思路了就自己做一下再看我代码吧:
下面代码是看了论坛里陈圳的代码,我加以修改完成的8种变化,它的那个枚举用的实在是太漂亮了!- public static void main(String[] args) {
- int n = 2;
- int[][] intArray = fillIntArray(n, false, Direction.RIGHT);//获取螺旋状的int数组
- drawCustomShape(intArray);
- //System.out.println("\n=========================================\n");
- //drawCustomShape(null); //打印一个空框
- }
- /**
- * 填充螺旋整形数组的方法
- * @param n 指示数据的长度
- * @param isClockwise 指示是否顺时针显示
- * @param direction 指示先向哪个方向移动
- * @return 螺旋整形数组
- */
- public static int[][] fillIntArray(int n, boolean isClockwise, Direction direction) {
- if (n <= 0) throw new IllegalArgumentException("参数n必须是大于或等于1的整数");
- int[][] intArray = new int[n][n];
- int max = n * n; // 最大输出数,可用来做结束循环的条件
- int num = 1; // 当前要输出的数,默认从1开始
- int x; // 当前要输出的数字在X轴的位置
- int y; // 当前要输出的数字在Y轴的位置
-
- //根据各种情况初始化数字1在数组中的x、y坐标
- int upleft = x = y = (n + 1) / 2 - 1; //顺时针先向右、或逆时针先向下 的情况下 1的坐标相对左上角对称
- if(n%2==1) {
- // n是单数的情况下,数字1在整个图形的正中间,算法跟顺时针先向右一样
- } else if ((isClockwise && direction==Direction.UP) ||(!isClockwise && direction==Direction.RIGHT)) { // 顺时先向上或逆时先向右
- y = n - upleft - 1;
- x = n - upleft - 2;
- } else if ((isClockwise && direction==Direction.DOWN) ||(!isClockwise && direction==Direction.LEFT)) { // 顺时先向下或逆时先向右
- y = n - upleft - 2;
- x = n - upleft - 1;
- } else if ((isClockwise && direction==Direction.LEFT) ||(!isClockwise && direction==Direction.UP)) { // 顺时先向左或逆时先向上
- y = x = n - upleft - 1;
- }
- intArray[y][x] = num++; // 把1放到固定的位置
- int moveCount = 1; // 控制一个方向要存几个数字
- for (int i=1; num<=max; i++) {
- for(int j=0; j<moveCount && num<=max; j++) {
- switch(direction) {
- case UP: intArray[--y][x] = num++; break; // 上
- case DOWN: intArray[++y][x] = num++; break; // 下
- case LEFT: intArray[y][--x] = num++; break; // 左
- case RIGHT: intArray[y][++x] = num++; break; // 右
- }
- }
- direction = direction.nextDirection(isClockwise); //上面的for循环结束后说明一个方向的数字存满了,得换一个方向继承存
- if(i%2 == 0) moveCount++;//i每循环两次count就自加1
- }
- return intArray;
- }
- /** 画自定义图形方法 */
- public static void drawCustomShape(int[][] intArray) {
- int n = intArray!=null ? intArray.length : 3;
- int starWidth = n + 2; // 星星的宽度
- for (int i = 1; i <= starWidth; i++) { // 控制输出的行数
- for (int j = 1; j <= starWidth; j++) { // 控制输出的列数
- if (j == starWidth) /*如果是最后一列: */ System.out.print("*\n");
- else if ((i == 1 || i == starWidth || j == 1)) /* 如果是第一行、或最后一行、或第一列: */ System.out.print("*\t");
- else /* 其他情况 */ System.out.print(intArray == null ? "\t" : intArray[i-2][j-2] + "\t");
- }
- }
- }
-
- enum Direction {
- UP, DOWN, LEFT, RIGHT;// 上、下、左、右
- public Direction nextDirection(boolean isClockwise) {// 参数isClockwise指示是否使用顺时针
- switch (this) {
- case UP: return isClockwise?RIGHT:LEFT; // 顺时针上移后右移,逆时针上移后左移
- case DOWN: return isClockwise?LEFT:RIGHT; // 顺时针下移后左移,逆时针下移后右移
- case LEFT: return isClockwise?UP:DOWN; // 顺时针左移后上移,逆时针左移后下移
- case RIGHT: return isClockwise?DOWN:UP; // 顺时针右移后下移,逆时针右移后上移
- default: return null;
- }
- }
- }
复制代码 |