黑马程序员技术交流社区

标题: 今天遇到一个问题,调了一个下午,跟大家分享一下吧。 [打印本页]

作者: 暗影流光    时间: 2014-7-13 17:21
标题: 今天遇到一个问题,调了一个下午,跟大家分享一下吧。
问题描述:
打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。
如: n = 4 则打印:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7


代码:
  1. package com.java;

  2. public class PrintFangZhen {

  3.         /**
  4.          * 打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
  5.          * 1 2 3 4
  6.          * 12 13 14 5
  7.          * 11 16 15 6
  8.          * 10 9 8 7
  9.          *
  10.          */
  11.         public static void main(String[] args) {
  12.                 int n = 4;
  13.                 if (n <= 0) {
  14.                         System.out.println("n必须大于0!");
  15.                         return;
  16.                 }
  17.                 int[][] arr = method(n);
  18.                 traverse(arr);
  19.         }

  20.         /**
  21.          * 按从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列,并存到一个二维数组中
  22.          *
  23.          * @param n
  24.          *            这个方阵的边长
  25.          * @return 一个二维数组
  26.          */
  27.         public static int[][] method(int n) {
  28.                 // 定义一个储存数字的二维数组
  29.                 int[][] arr = new int[n][n];
  30.                 // 定义一个count计数,count即为数组中的元素
  31.                 int count = 0;
  32.                 int i = 0, j = 0;
  33.                 while (true) {
  34.                         // 当n为1的时候,直接存入数组中并结束循环
  35.                         if (n == 1) {
  36.                                 arr[0][0] = 1;
  37.                                 break;
  38.                         }
  39.                         // 当一个元素的上、右、下、左的值不是0的时候;或者是当其上和右有值,并且左和下越界时,结束循环
  40.                         if ((i - 1 >= 0 && j + 1 <= n - 1 && i + 1 <= n - 1 && j - 1 >= 0
  41.                                         && arr[i - 1][j] != 0 && arr[i][j + 1] != 0
  42.                                         && arr[i + 1][j] != 0 && arr[i][j - 1] != 0)
  43.                                         || (j - 1 < 0 && i + 1 > n - 1 && arr[i - 1][j] != 0 && arr[i][j + 1] != 0)) {
  44.                                 break;
  45.                         }
  46.                         // 如果上面的角标越界了,并且右面的角标没越界,则向右移动
  47.                         if ((i - 1 < 0 && j <= n - 1)) {
  48.                                 arr[i][j++] = ++count;
  49.                         } else if (j + 1 > n - 1 && i + 1 <= n - 1) {
  50.                                 // 如果右面的角标越界了,并且下面的角标没越界,则向下移动
  51.                                 if (j == n) {
  52.                                         j--;
  53.                                 }
  54.                                 i++;
  55.                                 arr[i][j] = ++count;
  56.                         } else if (i + 1 > n - 1 && j - 1 >= 0) {
  57.                                 // 如果下面的角标越界了,并且左边的角标没越界,则向左移动
  58.                                 arr[i][--j] = ++count;
  59.                         } else if (j - 1 < 0 && i - 1 >= 0 && arr[i - 1][j] == 0) {
  60.                                 // 如果左边的角标越界了,并且上边的角标没越界,并且上边的元素的值为0,则向上移动
  61.                                 arr[--i][j] = ++count;
  62.                         } else {
  63.                                 // 如果不是边缘,则按其他情况来计算
  64.                                 if (arr[i - 1][j] != 0 && arr[i][j + 1] == 0) {
  65.                                         // 如果右面元素的值为0,并且上面元素的值不为0,则向右移动
  66.                                         arr[i][++j] = ++count;
  67.                                 } else if (arr[i + 1][j] == 0) {
  68.                                         // 如果下面元素的值为0,则向下移动
  69.                                         arr[++i][j] = ++count;
  70.                                 } else if (arr[i][j - 1] == 0) {
  71.                                         // 如果左面元素的值为0,则向左移动
  72.                                         arr[i][--j] = ++count;
  73.                                 } else if (arr[i - 1][j] == 0) {
  74.                                         // 如果上面元素的值为0,则向上移动
  75.                                         arr[--i][j] = ++count;
  76.                                 }
  77.                         }

  78.                 }
  79.                 return arr;
  80.         }

  81.         /**
  82.          * 遍历二维数组
  83.          *
  84.          * @param arr
  85.          *            一个待遍历的二维数组
  86.          */
  87.         public static void traverse(int[][] arr) {
  88.                 for (int i = 0; i < arr.length; i++) {
  89.                         for (int j = 0; j < arr[i].length; j++) {
  90.                                 System.out.print(arr[i][j] + " ");
  91.                         }
  92.                         System.out.println();
  93.                 }
  94.         }

  95. }
复制代码

如果大家还有更好的方法,欢迎交流。

作者: 001可望成功    时间: 2014-7-13 17:25
就是蜗牛呗,记得以前用C语言写,当时还没做出来
作者: GoodBoy123    时间: 2014-7-13 17:25
我表示完全看不懂是什么意思
作者: 乐此不疲    时间: 2014-7-13 18:18
好复杂啊  
作者: Bukeng    时间: 2014-7-13 18:26
这是入学考试题吧
作者: Caincxy    时间: 2014-7-13 18:35
学习下啊...
作者: 黎志勇    时间: 2014-7-13 19:56
本帖最后由 黎志勇 于 2014-7-13 20:02 编辑

试着写了下。
  1. package test;

  2. public class Test8 {
  3.     private final static int RIGHT = 0, DOWN = 1, LEFT = 2, UP = 3;// 定义方向常量

  4.     public static void main(String[] args) {
  5.         printArray(10);
  6.     }

  7.     public static void printArray(int length) {
  8.         int direction = RIGHT;// 移动方向
  9.         int[][] array = new int[length][length];// 注意,整形数组元素默认值是0,值为0即未被填充
  10.         // row、col为将要填充数据的行号和列号
  11.         for (int i = 1, row = 0, col = 0; i <= length * length; i++) {
  12.             array[row][col] = i;
  13.             // 根据方向,确定下一个填充数据的坐标的位置
  14.             switch (direction) {
  15.             case RIGHT:
  16.                 // 当右边不越界,且右边位置的值为0时,指针向右移动
  17.                 if (col + 1 < length && array[row][col + 1] == 0) {
  18.                     col++;// 列号增加表示指针右移
  19.                 } else {// 否则更改方向,向下移动
  20.                     direction = DOWN;
  21.                     row++;// 行好增加表示向下移动
  22.                 }
  23.                 break;
  24.             case DOWN:// 其他方向类似,右→下,下→左,左→上,上→右
  25.                 if (row + 1 < length && array[row + 1][col] == 0) {
  26.                     row++;
  27.                 } else {
  28.                     direction = LEFT;
  29.                     col--;
  30.                 }
  31.                 break;
  32.             case LEFT:
  33.                 if (col - 1 > -1 && array[row][col - 1] == 0) {
  34.                     col--;
  35.                 } else {
  36.                     direction = UP;
  37.                     row--;
  38.                 }
  39.                 break;
  40.             case UP:
  41.                 if (row - 1 > -1 && array[row - 1][col] == 0) {
  42.                     row--;
  43.                 } else {
  44.                     direction = RIGHT;
  45.                     col++;
  46.                 }
  47.                 break;
  48.             }
  49.         }
  50.         print(array);// 打印数组
  51.     }

  52.     private static void print(int[][] array) {
  53.         for (int i = 0; i < array.length; i++) {
  54.             for (int j = 0; j < array[i].length; j++) {
  55.                 System.out.print(array[i][j] + "\t");
  56.             }
  57.             System.out.println();

  58.         }

  59.     }
  60. }

复制代码



作者: idency    时间: 2014-7-13 20:16
我也有这个题,这是我的做法,略显麻烦!:L
  1. package com.itheima;

  2. /**
  3. * 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
  4. * 1        2        3        4
  5. * 12        13        14        5
  6. * 11        16        15        6
  7. * 10         9        8         7
  8. *
  9. *思路:
  10. *1.定义一个二维数组,请arr用来接收要打印的数据
  11. *2.打印该螺旋方式,可以将螺旋看成是多次循环,每次循环的开始位置都是a[0][0]  a[1][1] a[2][2]...
  12. *3.只需根据给定的n的值确定循环次数即可,循环次数为(n+1)/2
  13. *4.另外需要确定每次开始位置的值,随后按照螺旋顺序让对应角标值递增即可
  14. *5.遍历数组并按要求打印
  15. *
  16. *
  17. */
  18. public class Test9 {

  19.         public static void main(String[] args) {
  20.                
  21.                 //定义变量n用来表示需要打印的数组的大小
  22.                 int n = 15;
  23.                
  24.                 //定义print()方法,用来完成数组内容的确定并打印
  25.                 print(n);
  26.         }

  27.         public static void print(int n) {
  28.                
  29.                 //定义一个int型数组,用来接收需要打印的数据
  30.                 int[][] arr = new int[n][n];
  31.                
  32.                 //定义int型变量count,用来表示螺旋数组循环的次数
  33.                 int count = (n + 1) / 2;
  34.                
  35.                 //确定每个循环开始出的初始值a[0][0] a[1][1] a[2][2]...
  36.                 arr[0][0] = 1;
  37.                 for (int i = 1; i < count; i++) {
  38.                         arr[i][i] = arr[i - 1][i - 1] + ((n - (i - 1) * 2) * 2 - 2) * 2;
  39.                 }
  40.                
  41.                 //使用for循环,依次循环确定每次回环上的对应角标的值
  42.                 for (int i = 0; i < count; i++) {
  43.                        
  44.                         //该循环用于确定每次回环上上边缘数据
  45.                         for (int j = i + 1; j < arr.length - i; j++) {
  46.                                 arr[i][j] = arr[i][j - 1] + 1;
  47.                         }
  48.                        
  49.                         //该循环用于确定每次回环上右边缘的数据
  50.                         for (int j = i + 1; j < arr.length - i; j++) {

  51.                                 arr[j][arr.length - i - 1] = arr[j - 1][arr.length - i - 1] + 1;
  52.                         }
  53.                        
  54.                         //该循环用于确定每次回环上下边缘的数据
  55.                         for (int j = arr.length - i - 2; j >= 0 + i; j--) {
  56.                                 arr[arr.length - i - 1][j] = arr[arr.length - i - 1][j + 1] + 1;

  57.                         }
  58.                        
  59.                         //该循环用于确定每次回环上左边缘的数据
  60.                         for (int j = arr.length - i - 2; j > 0 + i; j--) {
  61.                                 arr[j][i] = arr[j + 1][i] + 1;
  62.                         }

  63.                 }
  64.                
  65.                 //使用for循环获得一维数组
  66.                 for (int i = 0; i < arr.length; i++) {
  67.                         int[] js = arr[i];
  68.                        
  69.                         //使用for循环获取每个一维数组中的元素,并按要求打印
  70.                         for (int j = 0; j < js.length; j++) {
  71.                                 System.out.print(js[j] + "\t");

  72.                         }
  73.                         //每次打印完成一个一维数据后进行换行
  74.                         System.out.println();

  75.                 }
  76.         }
  77. }
复制代码

作者: ╰_〃无法释怀的    时间: 2014-7-13 20:27
顶一下!!!
作者: 暗影流光    时间: 2014-7-14 11:01
Bukeng 发表于 2014-7-13 18:26
这是入学考试题吧

是的。:)




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2