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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 bianbian18 于 2013-5-2 00:52 编辑

看看~!
看错题了{:soso_e109:}。。。要用数组,不过这的确是我自己做出来的。。。实在是抗不住咯,看在研究了两小时的份上
给点技术分吧。。。

--------------------------------以下是分析和代码----------------------------

/*
可以如图那样将这个螺旋矩形分解为一圈一圈的。当只有1时,设这个螺旋结果的圈数为0;
元素1被一圈数字包围,圈数为1;被两圈包围,圈数为2;被三圈包围,圈数为3;一次类推
每行打印元素count的个数与loop的关系:
loop=0→count=0
loop=1→count=3
loop=2→count=5
loop=3→count=7
得出loop与count的关系为:count=loop*2+1
在看圈数(设为loop)和左上顶点的数字(设为leftTop)关系:
loop=0→leftTop=1
loop=1→leftTop=7
loop=2→leftTop=21
loop=3→leftTop=43
leftTop=(loop*2+1)(loop*2+1)-(loop*2)
再设每圈左下顶点的数字为leftBottom,右上顶点为rightTop,右下为rightBottom
因为每圈上有count个元素,则在同一边上顶点之间的步长值为:x=count-1=loop*2
则:leftBottom=leftTop-x=((loop*2+1)(loop*2+1)-(loop*2))-(loop*2)=(loop*2+1)(loop*2+1)-loop*4
    rightTop=leftTop+x=((loop*2+1)(loop*2+1)-(loop*2))+loop*2=(loop*2+1)(loop*2+1)
    rightBottom=leftBottom-x=(loop*2+1)(loop*2+1)-loop*2
如图给这个螺旋结构加上坐标,元素1为(0,0),x正半轴向上,y正半轴向右
然后将每个顶点的值当做每个边的基础值,根据这个基础值去算每个边上每个元素的值,如图所示
控制台每输出一个数,都要去检查这个数是位于那一圈上的,然后根据相应圈上相应边的基础值算出每个
元素的值,并输出
判断元素在哪个圈上的方法?
如 21的坐标为(-2,2),在第二圈上
   45的坐标为(-1,3),在第三圈上
   33的坐标为(-3,1),在第三圈上
   从以上可得规律:x,y的绝对值谁大,那该元素就在第几圈上
最后,就是每个边上的每个元素值由哪个顶点基数算出?
这里我们取每基数所管边上的任意一个元素的坐标跟该基数坐标进行比较,如下:
比如第二圈:
21(-2,2)这个顶点基数所在管的左边,18(-2,-1)
17(-2,-2)这个顶点基数所在管的下边,14(1,-2)
13(2,-2)这个顶点基数所在管的右边,11(2,0)
25(2,2)这个顶点基数所在管的右边,24(1,2)
得出:1.当元素的x坐标等于(-loop)时,左边上元素由leftTop基数算出
      2.当元素的y坐标等于(-loop)时,下边边上元素由leftBottom基数算出
   3.当元素的x坐标等于(loop)时,右边边上元素由rightBottom基数算出
   4.当元素的y坐标等于(loop)时,上边边上元素由rightTop基数算出

*/
import java.io.*;
class Demo
{
public static void main(String[] args)
{
  
  int i=3;//代表圈数
  print(i);
}
public static void print(int loop)
{
  star(loop);
  for(int y=-loop+2;y<(loop);y++)  
  { //每行打印的元素个数与loop的关系为(loop*2+1),因为我是围绕1做的,所以要把第一行去掉
   System.out.print("* ");
   for(int x=-loop+2;x<(loop);x++)
   {//因为是个n*n的矩形,所以打印的行数跟每行打印的个数一样,要把第一列去掉
    System.out.printf("%4d", result(x,y));
   }
   System.out.println("  *");
  }
  star(loop);
}
public static int result(int x,int y)
{
  int loop = getLoop(x,y);   //得到没输出一个元素,先判断在哪一圈上
  int leftTop = (loop*2+1)*(loop*2+1)-(loop*2);//左上顶点的值
  int leftBottom = (loop*2+1)*(loop*2+1)-loop*4;//左下顶点的值
  int rightTop = (loop*2+1)*(loop*2+1);//右上顶点的值
  int rightBottom = (loop*2+1)*(loop*2+1)-loop*6;//右下定点的值
  if(y == -loop) //元素y=loop,是上边的边,则元素结基于rightTop算出
  {
   return rightTop-(loop-x);
  }
  else if(y == loop)//下
  {
   return leftBottom-(loop+x);
  }
  else if(x==loop)//右
  {
   return rightBottom-(loop-y);
  }
  else//左
  {
   return leftTop-(loop+y);
  }
}
public static int getLoop(int x,int y)//得到元素所在的圈
{
  int loop;
  if(x<0)
   x=-x;
  if(y<0)
   y=-y;
  return loop = x>y?x:y;
}
public static void star(int loop)//打印*
{
  for(int i=0;i<=2*loop-1;i++)
  {
   System.out.print("*   ");
  }
  System.out.println();
}
}

12.jpg (96.38 KB, 下载次数: 0)

12.jpg

113.jpg (9.17 KB, 下载次数: 0)

113.jpg

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2

查看全部评分

回复 使用道具 举报
我要挑战一下!
回复 使用道具 举报
谭威 发表于 2013-4-30 17:47
la aa a a a aa

:L,我得先看到题目呢
回复 使用道具 举报
hyw840705183 发表于 2013-4-30 09:09
我看下什么题目

以下是我的代码:运行结果如图

是哦,好像没考虑到,我修改下。。。
回复 使用道具 举报
{:soso_e113:}~~
老师辛苦了~~我是学。Net的,想参加最近的一期黑马,昨天看到滔哥在群里的留言就写了,也没看是JAVA还是C#~
注释我一定会注意的{:soso_e113:}~
回复 使用道具 举报
我测试了,没有bug啊。。。是滔哥在我们.net群里发的,我过来挑战下。这是用C#写的控制台应用程序。我测试了,完全正常。麻烦你再试下,谢谢。
回复 使用道具 举报
过来看看。。
回复 使用道具 举报
清朗的晨风 发表于 2013-5-1 13:23
我测试了,没有bug啊。。。是滔哥在我们.net群里发的,我过来挑战下。这是用C#写的控制台应用程序。我测试 ...

不好意思啊,我的问题,确实不知道滔哥在.net宣传了,我还以为是java呢,对不起啊,我在运行一下。
回复 使用道具 举报
看看。
回复 使用道具 举报
崔宏奎 发表于 2013-5-1 13:20
~~
老师辛苦了~~我是学。Net的,想参加最近的一期黑马,昨天看到滔哥在群里的留言就写了,也 ...

没关系的,只要你参与了,我就会想办法测试运行的,并且会给你相应的技术分的。写的不错,很好
回复 使用道具 举报
回帖仅作者可见,我看不到你的回帖。不好意思。
回复 使用道具 举报
用C#写的,不会java

MySecondProject.rar

24.67 KB, 下载次数: 28

回复 使用道具 举报
我来试试
回复 使用道具 举报
本帖最后由 strawberry2013 于 2013-5-2 09:32 编辑
  1. import javax.swing.JOptionPane;

  2. class Demo
  3. {
  4.         private static int MAX_N = 10;//支持最大自然数为20
  5.         public static void main(String[] args)
  6.         {
  7.                 int[][] val = new int[MAX_N][MAX_N];       
  8.                 int n = getNumber("请输入自然数N");//获取自然数N

  9.                 if(n<=MAX_N && n>=1)                                //判断自然数N的有效范围
  10.                 {
  11.                         if(n%2 == 1)       
  12.                                 exec(val, 0, n-1, n);
  13.                         else
  14.                                 exec(val, n-1, 0, n);
  15.                 }
  16.                 show(val, n);
  17.         }

  18.         public static void exec(int[][] val, int m, int n, int len)
  19.         {
  20.                 int i, key;                        //exec(val, m, n, len) ->m,n分别代表目标点的横纵坐标 len表示该目标运动的长度;

  21.                 if (len%2 == 0)
  22.                         key = 1;                //判断运动的方向 key=1表示向右或者向上 key=-1表示相反方向
  23.                 else
  24.                         key = -1;

  25.                 for(i=0; i <= len-1; i++)
  26.                 {
  27.                         val[m][n+key*i] = len*len - i;
  28.                 }
  29.                 int temp = val[m][n+key*(len-1)];        //存储拐点的val值
  30.                 for(i=0; i<=len-1; i++)
  31.                 {
  32.                         val[m-key*i][n+key*(len-1)] = temp - i;
  33.                 }
  34.                 if (len == 1)
  35.                         return;
  36.                 exec(val, m-key*(len-1), n+key*(len-2), len-1);
  37.         }

  38.         public static void show(int[][] val, int n)//打印信息
  39.         {
  40.                 for(int i=0; i<n; i++)
  41.                 {
  42.                         for(int j=0; j<n; j++)
  43.                         {
  44.                                 if(val[i][j] != 0)
  45.                                 System.out.print(val[i][j]+"\t");
  46.                         }
  47.                         System.out.println("\n");
  48.                 }
  49.         }
  50.         public static int getNumber(String message)//获取自然数n值
  51.         {
  52.                 int number = 0;
  53.                 String str = JOptionPane.showInputDialog(null, message, "提示",JOptionPane.INFORMATION_MESSAGE);
  54.                 try
  55.                 {
  56.                         number = Integer.parseInt(str); // 得到输入的正整数
  57.                 }
  58.                 catch( Exception e)
  59.                 {
  60.                         JOptionPane.showMessageDialog(null, "输入非数字字符\n程序结束", "错误警告", JOptionPane.ERROR_MESSAGE);
  61.                         return -1; // 输入的不是数字字符,程序结束
  62.                 }
  63.                 if (number < 1 || number > MAX_N)
  64.                 {
  65.            JOptionPane.showMessageDialog(null, "自然数N范围为:1-"+MAX_N+"\n程序结束", "错误警告",JOptionPane.ERROR_MESSAGE);
  66.            return -1; // 输入的数不在范围,程序结束
  67.                  }
  68.                  else
  69.                          return number;
  70.         }

  71. }
复制代码

点评

程序的思路较清晰,也较简练;但没按题目要求做,并没打印出星号,且输出后程序还在运行,希望你能改进一下存在的bug,而且打印只能到10。  发表于 2013-5-2 11:13
不好意思啊,刚才评分出了点问题,请见谅  发表于 2013-5-2 11:07

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2

查看全部评分

回复 使用道具 举报
接受挑战
回复 使用道具 举报
这个注释比较好。。。。
  1. class Program
  2.     {
  3.         static int find(int i, int j, int n)
  4.         {//从外层向内层
  5.             if (n % 2 == 1)//边长为奇数时调用这个,先上边,左边,下边,然后右边
  6.             {
  7.                 if (i == 1) return n * (n - 1) + j;//上边的数值
  8.                 if (j == 1) return n * (n - 1) + 2 - i;//左边的数值
  9.                 if (i == n) return (n - 1) * (n - 1) - j + 2;//下边的数值
  10.                 if (j == n) return (n - 2) * (n - 2) - 1 + i;//右边的数值
  11.                 return find(i - 1, j - 1, n - 2);//递归调用内圈的矩阵,边长-2
  12.             }
  13.             else//边长为偶数数时调用这个,先下边,右边,上边,然后左边
  14.             {
  15.                 if (i == n) return n * n - j + 1;//下边的数值
  16.                 if (j == n) return n * n - 2 * n + 1 + i;//右边的数值
  17.                 if (i == 1) return (n - 1) * (n - 2) + j;//上边的数值
  18.                 if (j == 1) return (n - 1) * (n - 2) + 2 - i;//左边的数值
  19.                 return find(i - 1, j - 1, n - 2);//递归调用内圈的矩阵,边长-2
  20.             }
  21.         }

  22.         static void Main(string[] args)
  23.         {
  24.             int n, i, j;
  25.             Console.Write("请输入一个数字:");
  26.             if (Int32.TryParse(Console.ReadLine(), out n))//判断输入的是否是数字
  27.             {
  28.                 if (n <= 0)//判断输入的数字是否有效
  29.                 {
  30.                     Console.WriteLine("输入的数字无效,请输入大于0的整数");
  31.                     return;
  32.                 }
  33.                 int[,] number = new int[n + 2, n + 2];//定义个二维数组
  34.                 for (i = 1; i <= n; i++)//遍历整个矩阵
  35.                     for (j = 1; j <= n; j++)
  36.                         number[i, j] = find(i, j, n);//把数值存到数组中

  37.                 for (i = 0; i <= n + 1; i++)
  38.                 {
  39.                     for (j = 0; j <= n + 1; j++)
  40.                     {
  41.                         if (i == 0 || j == 0 || i == n + 1 || j == n + 1)
  42.                             Console.Write("  * ");//打印最外层的*
  43.                         else
  44.                             Console.Write("{0,4}", number[i, j]);
  45.                     }
  46.                     Console.WriteLine();
  47.                 }
  48.                 Console.ReadKey();
  49.             }
  50.             else
  51.                 Console.WriteLine("输入的不是数字");
  52.         }
  53.     }
复制代码

点评

嗯,不错  发表于 2013-5-2 11:14
回复 使用道具 举报
刘胜寒 发表于 2013-5-1 11:42
要是个0
应该输出
**

win8不想用....
然后就搞啊搞...
然后就崩了...
现在正在安装win7系统哈哈
回复 使用道具 举报
看一下 先看题目再说
回复 使用道具 举报
搞过acm的路过
C语言版
#include "stdafx.h"
#include <stdio.h>
int main()
{
        int n,a[21][21],i,j,k;
        while(scanf("%d",&n),n)
        {
                for(i=0;i<n;i++)
                for(j=0;j<n;j++)
                a[i][j]=0;
                k=n*n;j=0,i=0;
                while(k>=1)
                {
                        while(a[i][j]==0&&j<n)
                        {
                                a[i][j]=k--;
                                j++;
                        }
                        j--;i++;
                        while(a[i][j]==0&&i<n)
                        {
                                a[i][j]=k--;
                                i++;
                        }
                        i--;j--;
                        while(a[i][j]==0&&j>=0)
                        {
                                a[i][j]=k--;
                                j--;
                        }
                        j++;i--;
                       
                        while(a[i][j]==0&&i>=0)
                        {
                                a[i][j]=k--;
                                i--;
                        }
                        i++;j++;
                }
                for(i=0;i<n;i++)
                {
                        for(j=0;j<n-1;j++)
                        printf("%d ",a[i][j]);
                        printf("%d\n",a[i][n-1]);
                }
                printf("\n");
        }
        return 0;
}

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2

查看全部评分

回复 使用道具 举报
我来看一下究竟是什么题目?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马