A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© sin 中级黑马   /  2014-12-5 17:43  /  1398 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

前两天的一道考试题,刚拿到手头都大了,不过功夫不负有心人,经过大半天努力 还是搞出来了。可能方法有点笨了,有高手有更好的方法,求指点
题目是这样的:  写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
1  2  3    4
12 13 14 5
11 16 15 6
10  9   8  7
  1. package com.itheima;

  2. import java.util.Scanner;

  3. public class Test9 {

  4.         public static void main(String[] args) {

  5.                 // 输入数组长度
  6.                 System.out.print("请输入数组长度:");
  7.                 Scanner sc = new Scanner(System.in);
  8.                 int n = sc.nextInt();

  9.                 // 打印从1开始的自然数开始由方阵的最外圈向内螺旋方式地顺序排列的数组
  10.                 printArray(n);

  11.         }

  12.         /**
  13.          * 打印指定长度的等长二维数组
  14.          * */
  15.         public static void printArray(int n) {

  16.                 // 构造一个空的数组
  17.                 Integer[][] it = new Integer[n][n];
  18.                 // 将起始元素设置为 1
  19.                 it[0][0] = 1;
  20.                 // 定义起始元素Point对象
  21.                 Point p = new Point(0, 0, 1);

  22.                 // 设定初始方向,向右
  23.                 int flg = 1;
  24.                 // 代表数组设值得方向
  25.                 Direction d = null;
  26.                 // 一次循环可以设值的个数,为零代表已经将数组填满
  27.                 int step = 0;

  28.                 // 循环维数组设置从自然数1开始的连续的值
  29.                 while (true) {

  30.                         // 方向依次为右下左上
  31.                         d = Direction.getDirection(flg);
  32.                         // 获取本次循环可以设置的元素个数
  33.                         step = Direction.nextPoint(p, d, it);

  34.                         // 为零代表已经将数组填满
  35.                         if (step == 0) {
  36.                                 break;
  37.                         }
  38.                         // 返回下次循环开始的点
  39.                         p = setValue(p, d, step, p.getV(), it);

  40.                         // 方向依次改变
  41.                         flg++;
  42.                 }

  43.                 // 循环打印给数组中的值
  44.                 for (int i = 0; i < it.length; i++) {

  45.                         for (int j = 0; j < it[i].length; j++) {

  46.                                 System.out.print(it[i][j] + "\t");
  47.                         }
  48.                         // 折行
  49.                         System.out.println();
  50.                 }
  51.         }

  52.         /**
  53.          * 给定点,给定方向和该方向上的空元素数,将该方向上的空元素依次设值,并返回最后一个元素,返回的元素需要改变方向
  54.          * */
  55.         public static Point setValue(Point p, Direction d, int step, int value,
  56.                         Integer[][] it) {

  57.                 // 获取元素坐标和方向
  58.                 int a = p.getA();
  59.                 int b = p.getB();
  60.                 int y = d.getY();
  61.                 int x = d.getX();

  62.                 // 循环累加给定点的值,并赋到数组中去
  63.                 for (int k = 0; k < step; k++) {

  64.                         it[a = a + y][b = b + x] = ++value;
  65.                 }

  66.                 // 返回最后一个点
  67.                 return new Point(a, b, value);
  68.         }

  69. }

  70. /**
  71. * 代表数组中一个数组元素
  72. * */
  73. class Point {

  74.         // a表示二维维数,
  75.         private int a = 0;
  76.         // b表示一维脚标
  77.         private int b = 0;
  78.         // v表示数组元素的值
  79.         private int v = 0;

  80.         public int getA() {
  81.                 return a;
  82.         }

  83.         public int getB() {
  84.                 return b;
  85.         }

  86.         public int getV() {
  87.                 return v;
  88.         }

  89.         // 构造方法
  90.         public Point(int a, int b, int v) {
  91.                 this.a = a;
  92.                 this.b = b;
  93.                 this.v = v;
  94.         }
  95. }

  96. /**
  97. * 方向类,将二维数组看成坐标系,左右为x轴,上下为y轴,将方向表示为(y,x)对应数组脚标
  98. * 方向向右表示为(0,1),向下为(1,0),向左(0,-1),向上(-1,0)
  99. * */
  100. class Direction {

  101.         // 向右为(0,1)
  102.         private static Direction rD = new Direction(0, 1);
  103.         // 向下为(1,0)
  104.         private static Direction dD = new Direction(1, 0);
  105.         // 向左为(0,-1)
  106.         private static Direction lD = new Direction(0, -1);
  107.         // 向上为(-1,0)
  108.         private static Direction uD = new Direction(-1, 0);

  109.         // 定义y轴和x轴的坐标值
  110.         private int y = 0;
  111.         private int x = 0;

  112.         public int getY() {
  113.                 return y;
  114.         }

  115.         public int getX() {
  116.                 return x;
  117.         }

  118.         // 构造方法,初始化方向类即指定相应坐标
  119.         public Direction(int y, int x) {
  120.                 this.y = y;
  121.                 this.x = x;
  122.         }

  123.         /**
  124.          * 给定原点和方向,获取可以移动的步数
  125.          */
  126.         public static int nextPoint(Point p, Direction d, Integer[][] it) {

  127.                 // 接收参数的坐标值
  128.                 int a = p.getA();
  129.                 int b = p.getB();
  130.                 int v = p.getV();
  131.                 // 可以移动的步数
  132.                 int step = 0;
  133.                 // 移动的方向
  134.                 int direct = 0;
  135.                 Point newP = null;

  136.                 // 判断移动的方向
  137.                 if ((direct = d.getX()) != 0) {
  138.                         if (direct > 0) {

  139.                                 // x轴向右移动,直到不为空,得到移动的步数
  140.                                 while (true) {
  141.                                         if (isNullPoint(a, ++b, it)) {
  142.                                                 step++;
  143.                                                 continue;
  144.                                         }
  145.                                         break;
  146.                                 }
  147.                         } else {

  148.                                 // x轴向左移动,直到不为空,得到移动的步数
  149.                                 while (true) {
  150.                                         if (isNullPoint(a, --b, it)) {
  151.                                                 step++;
  152.                                                 continue;
  153.                                         }
  154.                                         break;
  155.                                 }
  156.                         }
  157.                 } else {

  158.                         // 在y轴上移动
  159.                         direct = d.getY();

  160.                         if (direct > 0) {

  161.                                 // 在y轴上向下移动
  162.                                 while (true) {
  163.                                         if (isNullPoint(++a, b, it)) {
  164.                                                 step++;
  165.                                                 continue;
  166.                                         }
  167.                                         break;
  168.                                 }
  169.                         } else {

  170.                                 // 在y轴上向上移动
  171.                                 while (true) {
  172.                                         if (isNullPoint(--a, b, it)) {
  173.                                                 step++;
  174.                                                 continue;
  175.                                         }
  176.                                         break;
  177.                                 }
  178.                         }
  179.                 }

  180.                 return step;

  181.         }

  182.         /**
  183.          * 给定数组的维数脚标,判断数组中的某个元素是否为空 false不为空,true为空
  184.          * */
  185.         public static boolean isNullPoint(int a, int b, Integer[][] it) {

  186.                 // 维数脚标不合法,返回false
  187.                 if (a >= it.length || b >= it.length || a < 0 || b < 0) {
  188.                         return false;
  189.                 }
  190.                 // 判断值是否为空
  191.                 if (it[a][b] == null) {
  192.                         return true;
  193.                 } else {
  194.                         return false;
  195.                 }
  196.         }

  197.         /**
  198.          * 获取移动的方向,首先向右移动
  199.          */
  200.         public static Direction getDirection(int flg) {

  201.                 // 方向依次是右下左上,通过取余判断
  202.                 if (flg % 4 == 1) {
  203.                         return rD;
  204.                 } else if (flg % 4 == 2) {
  205.                         return dD;
  206.                 } else if (flg % 4 == 3) {
  207.                         return lD;
  208.                 } else {
  209.                         return uD;
  210.                 }
  211.         }

  212. }
复制代码




评分

参与人数 1黑马币 +3 收起 理由
杨佳名 + 3 淡定

查看全部评分

13 个回复

倒序浏览
代码我都没敢看  ,这么简单的代码 , 我写了这么多 , 我也就是醉了 ,  拿到题目多思考  
有了思路代码就容易了,别写了代码再来想思路。
敲代码之前一定要有自己的逻辑思路

  1. public class Rows {
  2.         public static void main(String[] args) {
  3.                 int arr[][] =new int[5][5];
  4.                 int i = 0;
  5.                 int j = 0;
  6.                 int count = 1;
  7.                 boolean flag = true;
  8.                 for(int num = 1;num<=25;num++){
  9.                         arr[i][j]=num;
  10.                
  11.                         if(flag){
  12.                                 j++;
  13.                                 if(j>5-count){
  14.                                         i++;
  15.                                         j--;
  16.                                         if(i>5-count){
  17.                                                 flag=false;
  18.                                                 i--;
  19.                                                
  20.                                         }
  21.                                 }
  22.                         }
  23.                         if(!flag){
  24.                                 j--;
  25.                                 if(j<count-1){
  26.                                         i--;
  27.                                         j++;
  28.                                         if(i<count){
  29.                                                 flag=true;
  30.                                                 i++;
  31.                                                 j++;
  32.                                                 count++;
  33.                                         }
  34.                                 }
  35.                                
  36.                         }
  37.                        
  38.                 }
  39.                 for(i=0;i<5;i++){
  40.                         for(j=0;j<5;j++){
  41.                                 System.out.print(arr[i][j]+"\t");
  42.                         }
  43.                         System.out.println();
  44.                 }
  45.         }
  46. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1

查看全部评分

回复 使用道具 举报
后面一种方式更加简单,通过修改区调整i,j的位置区设定值。
回复 使用道具 举报
给力啊哈哈
回复 使用道具 举报
完爆的节奏~
回复 使用道具 举报
默默丶 发表于 2014-12-5 18:51
代码我都没敢看  ,这么简单的代码 , 我写了这么多 , 我也就是醉了 ,  拿到题目多思考  
有了思路代码就 ...

瞬间感觉高大上
回复 使用道具 举报
不明觉厉!
回复 使用道具 举报
曾勇 中级黑马 2014-12-5 23:05:08
8#
不都说,赞一个
回复 使用道具 举报
  1. <div class="blockcode"><blockquote>
  2. class Luoxuan
  3. {
  4.         //打印数组
  5.         public static void main(String[] args)
  6.         {
  7.                 int n=5;
  8.                 int arr[][]=fun(n);
  9.                
  10.                
  11.                 for(int i=0;i<n;i++)
  12.                 {
  13.                         for(int j=0;j<n;j++)
  14.                         {
  15.                                 System.out.print(arr[i][j]+"\t");
  16.                         }
  17.                         System.out.println();
  18.                 }
  19.                
  20.         }
  21.         //数组带入值的函数fun
  22.         public static int[][] fun(int n)
  23.         {       
  24.         //两种情况:n=偶数;n=奇数。
  25.        
  26.        
  27.        
  28.                 int arr[][]=new int[n][n];
  29.                 int num=1,t=n;
  30.                 //jishu是外循环次数,螺旋层数。
  31.                 int jishu=(n+1)/2;
  32.                 //n=奇数。
  33.                 if(t%2==1)
  34.                 arr[t-t/2-1][t-t/2-1]=t*t;
  35.                 //n=偶数。
  36.                 while(jishu>0)
  37.                 {
  38.                         for(int i=t-n,j=t-n;j<n-1;j++)
  39.                                 {
  40.                                 arr[i][j]=num;num++;
  41.                                 }
  42.                         for(int i=t-n,j=n-1;i<n-1;i++)
  43.                                 {
  44.                                 arr[i][j]=num;num++;
  45.                                 }
  46.                         for(int i=n-1,j=n-1;j>t-n;j--)
  47.                                 {
  48.                                 arr[i][j]=num;num++;
  49.                                 }
  50.                         for(int i=n-1,j=t-n;i>t-n;i--)
  51.                                 {
  52.                                 arr[i][j]=num;num++;
  53.                                 }
  54.                        
  55.                         n--;
  56.                         jishu--;
  57.                                
  58.                 }
  59.                 return arr;
  60.         }       
  61. }
复制代码
最重要的是要找到规律。楼上的代码看不懂,我水平有限。自己想了一种容易想的方法。如下图:
奇数和偶数的情况不同是调试时候发现的,要从调试中找错误。


回复 使用道具 举报
sin 中级黑马 2014-12-6 20:56:28
10#
默默丶 发表于 2014-12-5 18:51
代码我都没敢看  ,这么简单的代码 , 我写了这么多 , 我也就是醉了 ,  拿到题目多思考  
有了思路代码就 ...

哈哈,确实,不过我这是照着面向对象来的。当然放到这个具体问题来说,肯定是小题大做,哈哈:D
回复 使用道具 举报
这个题有啥意义吗。完全是逗你玩的没有循环
回复 使用道具 举报
评论收藏。给力的回答
回复 使用道具 举报
sin 中级黑马 2014-12-7 08:54:29
13#
高慧觉 发表于 2014-12-6 10:24
最重要的是要找到规律。楼上的代码看不懂,我水平有限。自己想了一种容易想的方法。如下图:奇数和偶数的情 ...

你的图很受用啊,当时想复杂了
  1. package cn.jx.test2;

  2. public class test0 {

  3.         public static void main(String[] args) {
  4.                
  5.                 int n = 11;
  6.                 int arr[][] = new int[n][n];
  7.                 int num = 1;
  8.                 int a = 0,b = 0;
  9.                 int m = n;
  10.                 if(n%2!=0){
  11.                         arr[(n-1)/2][(n-1)/2] = n*n;
  12.                 }
  13.                 for(int i=0; i<((n+1)/2);i++){
  14.                         int x = 0,y = 1;
  15.                         int f=0;
  16.                         while(f++<4){
  17.                                 for(int j=0;j<m-1;j++){
  18.                                         arr[a][b]=num++;
  19.                                         a=a+x;b=b+y;
  20.                                 }
  21.                                 x=x+y;y=y-x;x=x+y;
  22.                         }
  23.                         m = m-2;
  24.                         a = a + 1;
  25.                         b = b + 1;
  26.                 }
  27.                
  28.                 for(int j=0;j<n;j++){
  29.                         for(int k=0;k<n;k++){
  30.                                 System.out.print(arr[j][k] + "\t");
  31.                         }
  32.                         System.out.println();
  33.                 }
  34.         }
  35. }
复制代码
回复 使用道具 举报
不明觉励。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马