int i=5;   
1  2  3  4  5  
16 17 18 19 6  
15 24 25 20 7  
14 23 22 21 8  
13 12 11 10 9  
  
int i=6  
1  2  3  4  5   6  
20 21 22 23 24  7  
19 32 33 34 25  8  
18 31 36 35 26  9  
17 30 29 28 27 10  
16 15 14 13 12 11  
请问应该怎么打印出上面的数字,并且这样排列?

解决方案 »

  1.   


    class snakePrint {   
        static int length = 7;   
        static int value = 1;   
        static int[][] snake = new int[length][length];   
        static Direction lastDirection = Direction.Right;   
      
        static enum Direction {   
            Right, Down, Left, Up;   
        }   
      
        public static void initialArray() {   
            int row = 0, line = 0;   
            for (int c = 0; c < length * length; c++) {   
                snake[row][line] = value;   
              lastDirection = findDirection(row, line);   
                switch (lastDirection) {   
                    case Right:   
                        line++;   
                        break;   
                    case Down:   
                        row++;   
                        break;   
                    case Left:   
                        line--;   
                        break;   
                   case Up:   
                        row--;   
                        break;   
                    default:   
                        System.out.println("error");   
                }   
                value++;   
            }   
        }   
      
        static Direction findDirection(int row, int line) {   
            Direction direction = lastDirection;   
            switch (direction) {   
                case Right: {   
                    if ((line == length - 1) || (snake[row][line + 1] != 0))   
                        direction = direction.Down;   
                    break;   
                }   
                case Down: {   
                    if ((row == length - 1) || (snake[row + 1][line] != 0))   
                       direction = direction.Left;   
                   break;   
               }   
                case Left: {   
                    if ((line == 0) || (snake[row][line - 1] != 0))   
                        direction = direction.Up;   
                    break;   
                }   
                case Up: {   
                    if (snake[row - 1][line] != 0)   
                       direction = direction.Right;   
                    break;   
                }   
           }   
            return direction;   
        }   
      
        public static void main(String[] args) {   
            initialArray();   
     
           // display.....   
           for (int i = 0; i < length; i++) {   
                for (int j = 0; j < length; j++) {   
                    System.out.print(snake[i][j] + "  ");   
                }   
               System.out.println();   
            }   
        }   

      

  2.   


    class Direction {
    public static final int RIGHT = 1;
    public static final int DOWN = 2;
    public static final int LEFT = 3;
    public static final int UP = 4;
    public static final int[] DirectionArray = {RIGHT, DOWN, LEFT, UP};
    }
    class DirectsWithInteger {
    private static int[] directs = null;
    private static int[] prints = null;
    private static int[] getDirects(int n) {
    directs = new int[2*n-1];
    for(int i=0; i<directs.length; i++) {
    if(0 == i) {
    directs[i] = n;
    }else {
    if(0 == i%2) {
    directs[i] = n - i/2;
    }else {
    directs[i] = n - (i+1)/2;
    }
    }
    }
    return directs;
    }
    public static int[] getPrintDirects(int n) {
    directs = getDirects(n);
    prints = new int[n*n];
    int startIndex = 0;
    for(int i=0; i<directs.length; i++) {
    for(int j=0; j<directs[i]; j++) {
    prints[startIndex++] = Direction.DirectionArray[i%Direction.DirectionArray.length];
    }
    }
    return prints;
    }
    }
    //MainClass
    public class ScrewRectangle {
    public static final int N = 10;
    public static int[] direction = Direction.DirectionArray;
    public static int[] directs = DirectsWithInteger.getPrintDirects(N);
    public static int printDirection = direction[0];
    public static void main(String[] args) {
    int[][] p = printScrew();
    System.out.println("Init-N=" + N);
    for(int i=0; i<p.length; i++) {
    for(int j=0; j<p[i].length; j++) {
    System.out.print(p[i][j] + "\t");
    }
    System.out.println();
    }
    }

    public static int[][] printScrew() {
    System.out.println();
    int[][] a = new int[N][N];
    int xIndex = 0;
    int yIndex = 0;
    for(int i=0; i<N*N; i++) {
    a[yIndex][xIndex] = i+1;
    if(i == N*N-1) {
    break;
    }

    if(1 == directs[i+1]) {
    xIndex++;
    }else if(2 == directs[i+1]) {
    yIndex++;
    }else if(3 == directs[i+1]) {
    if(xIndex > 0) {
    xIndex --;
    }
    }else {
    yIndex--;
    }
    }
    return a;
    }
    }
    //Result:
    //Init-N=10
    //1 2 3 4 5 6 7 8 9 10
    //36 37 38 39 40 41 42 43 44 11
    //35 64 65 66 67 68 69 70 45 12
    //34 63 84 85 86 87 88 71 46 13
    //33 62 83 96 97 98 89 72 47 14
    //32 61 82 95 100 99 90 73 48 15
    //31 60 81 94 93 92 91 74 49 16
    //30 59 80 79 78 77 76 75 50 17
    //29 58 57 56 55 54 53 52 51 18
    //28 27 26 25 24 23 22 21 20 19
      

  3.   

    got it   也许哪次换工作遇到这个的笔试题呢
      

  4.   

    对3楼的代码做个注释:
    class Direction定义了静态int常量和一个静态int数组,并且是逆时针顺序
    class DirectsWithInteger定义了两个静态int数组:directs, prints。其中directs保存int N平方的分解:
    例如5 5*5=25 = 5 + 4 + 4 + 3 + 3 + 2 + 2 + 1 + 1;
    再如6 6*6=36 = 6 + 5 + 5 + 4 + 4 + 3 + 3 + 2 + 2 + 1 + 1;
    另外的prints保存int i从0到N*N-1的打印方向如果 i如果落在了directs的第i个元素里,对应的打印方向为Direction.DirectionArray[i%Direction.DirectionArray.length],从而得以循环RIGHT - > DOWN - > LEFT - > UP - > ...
    在main方法所在的类里边定义一个返回一个二维数组的方法,返回的二维数组记录了将要打印的顺序:
    如果向右走对应的游标xIndex++,向下则yIndex++,向左xIndex--,向上yIndex--...
    由于prints已经定义了从0到N*N-1对应的方向,所以一路走下来就完成了对返回数组的赋值,打印即可
    另外如果想要逆时针顺序的,只要把代码a[yIndex][xIndex] = i+1;换为a[xIndex][yIndex] = i+1;即可,起点默认在(0,0),换起点了对应的修改游标加减的方法即可...
    仅供参考,多多指正if(1 == directs[i+1]) {
                    xIndex++;
                }else if(2 == directs[i+1]) {
                    yIndex++;
                }else if(3 == directs[i+1]) {
                    xIndex --;
                }else {
                    yIndex--;
                }头部定义的几个没用到的变量,可以注释掉的
      

  5.   

    另类实现方法
    请参见
    http://blog.csdn.net/icy_csdn/archive/2010/03/09/5359153.aspx
      

  6.   

    public class Test {
    public static void main(String[] args)throws Exception{ int  size=10;
    SpeedState  sps=new SpeedState();
    int[][]  a=new int[size][size];

    for(int i=1,x=0,y=0,max=size*size;i<=max;i++){
    //output at current position
    a[x][y]=i;

    //get next position
    int[] state;
    int  nxtX,nxtY;

    while(i<max){
    state=sps.getState();
    nxtX=x+state[0];
    nxtY=y+state[1];

    if((nxtX>=0&&nxtX<=size-1)
     &&(nxtY>=0&&nxtY<=size-1)
         &&(a[nxtX][nxtY]==0)){
    x=nxtX;
    y=nxtY;
    break;
    }

    sps.nextState();
    }
    }



    //print Matrix
    for(int i=0;i<size;i++){
    for(int j=0;j<size;j++){
    System.out.print(String.format("%-4s",a[i][j]));
    }
    System.out.print('\n');
    }
    }}class SpeedState{
    private int[][] state={//x,y
    {0 ,1 },
    {1 ,0 },
    {-1 ,0 },
    {0 ,-1 }
    };

    private int stateIndex;

    public SpeedState(){
    stateIndex=0;
    }

    public int[] getState(){
    return state[stateIndex];
    }

    public void nextState(){
    stateIndex++;
    stateIndex%=4;
    }
    }
      

  7.   

    看了楼上几位大人的回复,都很佩服啊...高人就是多.. 小弟不才,(擦,别装嫩,还小弟,张的跟大叔似的),也想了一个方法,从面向对象的方法来考虑一下这个问题,可能这个题目用面向过程的方法更容易一些,我就楞套用了一下,参考了一下状态模式,也可以实现,不过代码比其他大人们的代码都长...大家.凑合看看我考虑这个问题是这个样子的,看结果那个数组,就想象成数字的填写,填写的路径是有规律的,填写的数字也是有规律的。1.数字的规律 :从1开始,自增1。这个如果变化的话,是很容易的,例如变成从100开始,自增10。
    2.路径的规律 :
    a。填写的几个路径可以简单的归纳成四种,从左向右——针对数组来说,就是横坐标不动,纵坐标增加1。其他三个基本路径是从右向左,从上向下和从下向上。
    b。针对这个题目,这几个基本的路径应该是 (从左向右)-(从上向下)-(从右向左)-(从下向上)然后循环。
    c. 如果定义一个int N , 那么结果产生的数组是一个 N*N 的数组,数组产生的具体路径是 (从左向右移动N位)- -(从上向下移动N-1位)-(从右向左N-1位)-(从下向上移动N-2位)
       也就是步数的变化是 {N,N-1,N-1,N-2,N-2...1,1} (我的例子中这个步骤的规律的产生,没有具体些)我在我写的方法中,首先 定义了一个结果类 ,其中 int[][] 用于存放结果的代码,一些变量用来记录填写这个结果用到的状态,比如第几行(row)第几列(col)填写数字(fnum)几,请看程序:(get,set方法我就省去了)
    public class Result {
    private int row;  //记录向数组中填写数字的时候,要填写位置的横坐标
    private int col;  //记录向数组中填写数字的时候,要填写位置的纵坐标
    private int conut = 1; //要填写的步数。如向右填写3步,如果默认从第一行第一列开始填写,则[0][0],[0][1],[0][2]填写数字
    private int len;  //len维数组
    private int fnum = 1 ; //填写的数组,默认从0开始,增加1。当然这个起始值和增量可以由客户端定义,这里先省去了。
    private Toward toward; //填写数字的方向。

    enum  Start{
    UPPERLEFT , UPPERRIGHT , UNDERLEFT , UNDERRIGHT } ;
    //起始位置  UPPERLEFT 左上角 ..类推..这个参数可以了去掉,换成两个int值,用来定义起始位置,这样的话,就可以不局限于只从数组的四个角上开始
    private int[][] result; //记录填写的结果

    public Result(){ //默认是一个 5*5的数组,起始位置在左上角
    this.row = 0 ;
    this.col = -1 ;
    this.len = 5 ;
    toward = new RightToward();
    result = new int[5][5];
    }

    public Result(int len , Start start ){ //可以传递进来参数 (len维数组,起始位置)
    this.len = len ;
    result = new int[len][len];   //运行结果是一个 len * len 的二维数组

    if(Start.UPPERLEFT.equals(start)){   //如果起点在数组的左上角,则row=0,col=-1,(先移动后填写数字),并且第一步要向右走,第一步移动到[0][0],填写....下面类推
    this.row = 0 ;
    this.col = -1 ;
    toward = new RightToward();
    }else if(Start.UPPERRIGHT.equals(start)){
    this.row = -1;
    this.col = len - 1 ;
    toward = new DownToward();
    }else if(Start.UNDERLEFT.equals(start)){
    this.row = len  ;
    this.col = 0;
    toward = new UpToward();
    }else{
    this.row = len - 1 ;
    this.col = len ;
    toward = new LeftToward();
    }
    }

    public void fillNum(){
    try{
    this.result[row][col] = fnum ;
    }catch(Exception e){
    //数组越界
    e.printStackTrace();
    }
    }

    public void systemResult(){
    for(int r = 0 ; r < len ; r ++){
    for(int c = 0 ; c < len ; c ++){
    System.out.print(result[r][c] + "   ");
    }
    System.out.println();
    }
    } public void execute(){
    this.toward.handle(this);
    }
    }下面我们要把填写路径的方法提取出来,首先定义一个抽象类:public abstract class Toward {
        public abstract void handle(Result result);   
        public abstract void changeDirection(Result result);   
    }
    然后定义具体四个填写路径的类,例如从左到右:public class RightToward extends Toward { @Override
    public void changeDirection(Result result) {
    // TODO Auto-generated method stub
    result.setToward(new DownToward()); //从左到右填写完了,要告诉结果类,下一步要从上向下填写了,DownToward()这个类就是从上向下填写的类
    } @Override
    public void handle(Result result) {
    for(int step = 0 ; step < result.getConut() ; step ++){
    result.setRow(result.getRow());  //先移动
    result.setCol(result.getCol()+1);
    result.fillNum();                //后填写
    result.setFnum(result.getFnum()+1); //这里的+1可以修改,将自增值自己定义
    }
    this.changeDirection(result);
    // TODO Auto-generated method stub

    }}其他三个填写路径的类差不多,请参考第一个路径即可。changeDirection(Result result) 中要注意他们的顺序,(从左向右)-(从上向下)-(从右向左)-(从下向上)-(从左向右)好了,来看看我们的客户端吧:public class Client {
    public static void main(String[] args){
    int arrlen = 6 ;
    Result result = new Result(arrlen , Result.Start.UPPERLEFT);

    //判断 arrlen > 0
    //int[] route = new int[2*arrlen - 1];
    int[] route = {6,5,5,4,4,3,3,2,2,1,1};
    for(int i = 0 ; i < route.length ; i++){
    result.setConut(route[i]);
    result.execute();
    }
    result.systemResult();
    }
    }其中 int[] route = {6,5,5,4,4,3,3,2,2,1,1};
    应该是根据 int arrlen = 6 ; 得来的,这个应该好弄,是有规律的,具体我就不在这里写了。
    运行一下看看结果:
    1   2   3   4   5   6   
    20   21   22   23   24   7   
    19   32   33   34   25   8   
    18   31   36   35   26   9   
    17   30   29   28   27   10   
    16   15   14   13   12   11 
    还行...我们换一下 Result result = new Result(arrlen , Result.Start.UNDERLEFT);
    让它从左下角开始,结果:
    6   7   8   9   10   11   
    5   24   25   26   27   12   
    4   23   34   35   28   13   
    3   22   33   36   29   14   
    2   21   32   31   30   15   
    1   20   19   18   17   16 
    也还行。不过我现在想要这种的了:
    1  2  3  4  5
    10 9  8  7  6
    11 12 13 14 15
    20 19 18 17 16
    21 22 23 24 25
    这种貌似就不能实现了...怎么办... 童鞋们想想...想出来的童鞋,楼主送香吻一枚。要是这种呢:
    1  2  3  4 
    5  6  7  8
    9  10 11 12
    13 14 15 16童鞋们想想...想出来的童鞋,楼主送....嘿嘿嘿嘿...
    可能要想的太复杂了,不要介意
      

  8.   

    最面向对象的是对着电脑屏幕吼一声:给我打印个螺旋方阵,然后电脑屁颠儿屁颠儿的给你打印了个螺旋方阵;
    再吼一声:给我打印个H电影出来,然后电脑屁颠儿屁颠儿的跑了半天,然后冒烟儿了!!!
    O(∩_∩)O哈哈~,玩笑了~~~
      

  9.   

    厄..至少也要几个参数...
    (男人,女人)
    (男人,男人,女人)
    (list<男人> , list<女人>)
    ...方法名相同,参数不同,这叫什么...童鞋回答..
      

  10.   

    谢谢各位的回答了,你们真是太厉害了!!我感觉自己的脑袋动不了了都,“Dazzlingwinter”看到你的很多回复了,好厉害哦,崇拜ing!!!