我无法理解那个“用棒人画楼梯”的程序。

27

你可能在Java 1班上看到过它:这是一个问题,要求你编写一个程序来绘制以下图形:

enter image description here

我必须使用常量。除了for循环、print和println之外,我不允许使用任何东西。没有参数,也没有数组。我知道我如何使用参数和数组来完成它,幸运的是。任何帮助都会受到赞赏!

这是我的不完整代码:

public class Stairs {
    public static final int LENGTH=5;

    public static void main(String[] args) {
        printStairs();
    }

    public static void printStairs() {
        for (int allStairs=1; allStairs<=15; allStairs++) {
            for (int spaces=1; spaces<=(-5*allStairs+30); spaces++) {
                System.out.print(" ");
            }
            for (int stair = 1; stair <= 5; stair++) {
                System.out.println("  o  *******");

            }
        }
    }
}
8个回答

26

这听起来像是一道作业题,所以我不想直接给你答案,但试着将它分解成几个步骤。思考你所知道的事情:

1)每个小人都有这个形状:

  o  ******
 /|\ *     
 / \ *     

2) 您可以使用以下代码将其打印出来:

System.out.println("  o  ******");
System.out.println(" /|\ *     ");
System.out.println(" / \ *     ");

3) 您可以使用循环打印多个:

for (int stair = 1; stair <= LENGTH; stair++) {
    System.out.println("  o  ******");
    System.out.println(" /|\ *     ");
    System.out.println(" / \ *     ");
}

思考这种输出会带给你什么,以及需要进行哪些更改。请意识到每个小人需要缩进一定的量。根据stair的值来确定如何适当地缩进它们。


您可能需要删除最后一行,每个小人有3行用于递归目的。 - Keppil
"找出如何修改打印语句以将一个小人的楼梯与下一个分开。" / "如果您重复这样做,每个小人都会有重复的楼梯。你该如何改变这种情况以防止发生这种情况?" 猫已经被放出来了 :P - Jon Newmuis
2
谢谢!我也不希望你只是给我答案,我真的想理解它。 - Monica
@JonathanNewmuis:抱歉,我错过了那一行。:) 我喜欢你的回答中的所有内容,除了那部分,我认为将第四行放在那里会增加更多的混淆,而不是帮助理解。不过,这是一个很好的解释。 - Keppil
由于某些原因,我无法将修改后的代码粘贴在这里并使其看起来整洁,但是无论如何,我已经让它打印出了正确缩进的楼梯和小人。我只需要完成后面的部分。非常感谢! - Monica
@Keppil已删除。我宁愿答案过于透明,也不愿过于混淆。 - Jon Newmuis

4
您可以看到这个图示,每个小人都有3行,每行包括:
  • 空格,如有必要,则与小人数量成比例
  • 小人的一部分 - 您可以硬编码此部分
  • 6个*或1个后跟5个空格的*
  • 空格,如有必要,则与小人数量成比例
  • *
最后一行是*,与小人数量成比例。

我在编写第一个嵌套循环的表达式时遇到了麻烦(它只打印空格)。它有点起作用,但我有很多额外的、不必要的行。 - Monica
  1. 你可以看到空间的数量是5的倍数。
  2. 比较数字小人“n”少一或多一的情况,你会发现第一行总是有“n”-1组空格。
  3. 在图形内部进行比较,下一行将少1组空格。
- nhahtdh

3

这是我的最终尝试,使用格式化功能。

public static void main(String[] args) {
    int steps = 5;
    for (int x = 0; x < steps; x++) {
        System.out.format(((steps == (x + 1)) ? "" : ("%"
                + ((steps - x - 1) * 5) + "s"))
                + "  o  ******"
                + ((x == 0) ? "" : ("%" + (x * 5) + "s"))
                + "*\n", " ", " ");
        System.out.format(((steps == (x + 1)) ? "" : ("%"
                + ((steps - x - 1) * 5) + "s"))
                + " /|\\ *     "
                + ((x == 0) ? "" : ("%" + (x * 5) + "s"))
                + "*\n", " ", " ");
        System.out.format(((steps == (x + 1)) ? "" : ("%"
                + ((steps - x - 1) * 5) + "s"))
                + " / \\ *     "
                + ((x == 0) ? "" : ("%" + (x * 5) + "s"))
                + "*\n", " ", " ");
    }
    for (int i = 0; i < (steps + 1) * 5 + 2; i++) {
        System.out.print("*");
    }
}

输出:

                      o  *******
                     /|\ *     *
                     / \ *     *
                 o  ******     *
                /|\ *          *
                / \ *          *
            o  ******          *
           /|\ *               *
           / \ *               *
       o  ******               *
      /|\ *                    *
      / \ *                    *
  o  ******                    *
 /|\ *                         *
 / \ *                         *
********************************

\o/

以下的方法也很有趣(根据您的幽默偏好不同),但不是完整的解决方案:

    for (String s = "                           o  *****                          /|\\ *                              / \\ *    "; s
            .charAt(8) != '*'; s = s.substring(5, s.length() / 3) + "     "
            + s.substring(s.length() / 3 + 5, 2 * s.length() / 3) + "     "
            + s.substring(2 * s.length() / 3 + 5, s.length()) + "     ") {
        System.out.println(s.substring(0, s.length() / 3) + "*");
        System.out
                .println(s.substring(s.length() / 3, 2 * (s.length() / 3))
                        + "*");
        System.out.println(s.substring(2 * (s.length() / 3), s.length())
                + "*");
    }

输出:

                       o  ******
                      /|\ *    *
                      / \ *    *
                  o  *****     *
                 /|\ *         *
                 / \ *         *
             o  *****          *
            /|\ *              *
            / \ *              *
        o  *****               *
       /|\ *                   *
       / \ *                   *
   o  *****                    *
  /|\ *                        *
  / \ *                        *

请注意,原帖作者说“没有参数”,我们将其解释为“除了main()方法之外没有其他方法”。 - Ernest Friedman-Hill
Ernest,谢谢你提醒我。我已经删除了该方法(它并非必要),最终通过格式化找到了解决方法。可惜需要使用条件语句来避免零宽参数的问题。 - Adriaan Koster

2

有一个递归块,白色空间逐渐减少。递归以LEFT_SPACE == 0 结束。递归块为:

LEFT_SPACE o  ******RIGHT_SPACE*
LEFT_SPACE/|\ *     RIGHT_SPACE*
LEFT_SPACE/ \ *     RIGHT_SPACE*

2

以下是一些提示:

  • 你应该从水平方向考虑它。
  • 你的主循环必须与楼梯数量相关,因为你受制于你需要绘制的楼梯数。
  • 最容易的方法可能是分别打印每行,所以要了解绘制每行所需的所有信息。

1

我稍微有些不同。以下脚本适用于任意数量的楼梯。我已经添加了注释,这样你就可以清楚地知道我在做什么。

public class stairman {

//establishing class constants
public static final int STAIR_NUM = 5;
public static final int WIDTH = STAIR_NUM * 5;

public static void main(String[] args) {

    //perform this loop for as many times as there are stairs
    for (int i=1; i<=STAIR_NUM; i++) { 

        //calculating number of spaces before the top line of the stair
        for (int x=1; x<=(WIDTH+(i*(-5))); x++) {
            System.out.print(" ");
        }

        //printing top line of the stair
        head();

        //calculating the number of spaces after the top line of the stair
        for(int y=1; y<=((i-1)*5); y++){ 
            System.out.print(" ");
        }
        System.out.println("*");

        //calculating the number of spaces before the 1st middle line of the stair
        for (int x=1; x<=(WIDTH+(i*(-5))); x++) {
            System.out.print(" ");
        }

        //print the first middle line of the stair
        middle1();

        //calculating the number of spaces after the 1st middle line of the stair           
        for (int y=1; y<=(i*5); y++){ 
            System.out.print(" ");
        }
        System.out.println("*");

        //calculating the number of spaces before the 2nd middle line of the stair          
        for (int x=1; x<=(WIDTH+(i*(-5))); x++) {
            System.out.print(" ");
        }

        //printing the 2nd middle line of the stair
        middle2();

      //calculating the number of spaces after the 2nd middle line of the stair
        for (int y=1; y<=(i*5); y++){ 
            System.out.print(" ");
        }
        System.out.println("*");
    }

    //calculating the number of stars needed for the bottom of the stairs
    for (int z=1; z<=(WIDTH+7); z++) {
        System.out.print("*");
    }
}

public static void head() {
    System.out.print("  o  ******");
}
public static void middle1() {
        System.out.print(" /|\\ *");
}
public static void middle2() {
    System.out.print(" / \\ *");
}   

}


1

这是我最终得出的结果:

public class Stairs {
    public static final int LENGTH=5;

    // The 'main method' prints out all the stairs with the appropriate indentations.
    public static void main(String[] args) {
        // outer loop
        for (int allStairs=0; allStairs<=4; allStairs++) {
            // first nested loops print the heads and tops of steps
            for (int spaces=1; spaces<=(-5*allStairs+20); spaces++) {
                printSpace();
            }
            System.out.print("  o  ******");
            for (int backWall=0; backWall<allStairs*(LENGTH); backWall++) {
                printSpace();
            }
            printStar();
            // second nexted loops print the body and the backs of the stairs
            for (int spaces = 1; spaces <= (-5 * allStairs + 20); spaces++) {
                printSpace();
            }
            System.out.print(" /|\\ *");
            for (int backWall=1; backWall<=LENGTH*(allStairs+1); backWall++) {
                printSpace();
            }
            printStar();
            // third nested loops print the legs and lower backs of stairs
            for (int spaces = 1; spaces <= (-5 * allStairs + 20); spaces++) {
                printSpace();
            }
            System.out.print(" / \\ *");
            for (int backWall=1; backWall<=LENGTH*(allStairs+1); backWall++) {
                printSpace();
            }
            printStar();
        }
        // this loop prints the very bottom line of stars
        for (int lastLine=1; lastLine<=32; lastLine++) {
            System.out.print("*");
        }
        System.out.println();
    }

    // printSpace() prints out a space
    public static void printSpace() {
        System.out.print(" ");
    }

    // printStar() prints out an asterisk
    public static void printStar() {
        System.out.println("*");
    }
}

我认为这看起来非常冗余,但由于变量作用域的原因,我无法将循环放入新方法中。然而,在Eclipse中运行时,它看起来与我所给的绘图一样。感谢所有帮助我的人,我非常想知道是否仍然可以进一步简化它。 - Monica
只是为了好玩看看我的答案。可能无法满足任务要求,因为它使用了条件语句,但很简洁(也很难读懂)。 - Adriaan Koster
我真的很喜欢你的代码,因为它非常简洁。可惜我没能做出类似的东西。谢谢 :) - Monica

0

我测试了上面的代码,但它对我来说不起作用。所以我试着去做,并使用了一些他们的想法。

public class DrawStairs {   

public static final int HEIGHT= 5;

public static final int TOTALHEIGHT= HEIGHT*5;

public static void main(String[] args){
    //Main Outer Loop
    for(int i=1; i<=HEIGHT; i++){

        //Loop for the spaces before, then print the head
        for(int j=1; j<=TOTALHEIGHT+(i*(-5)); j++){ 
            System.out.print(" ");
        }
        printTop();

        //Loop for spaces after, then print asterisk
        for(int j=1; j<=(i-1)*5; j++){ 
            System.out.print(" ");
        }
        System.out.println("*");

        //Loop for the spaces before, then print the body
        for(int j=1; j<=TOTALHEIGHT+(i*(-5)); j++){ 
            System.out.print(" ");
        }
        printMiddle();

        //Loop for spaces after, then print asterisk
        for(int j=1; j<=(i-1)*5; j++){ 
            System.out.print(" ");
        }
        System.out.println("*");

        //Loop for spaces before, then print the legs
        for(int j=1; j<=TOTALHEIGHT+(i*(-5)); j++){ 
            System.out.print(" ");
        }
        printBottom();

        //Loop for spaces after, then print asterisk
        for(int j=1; j<=(i-1)*5; j++){ 
            System.out.print(" ");
        }
        System.out.println("*");            
    }

    // for loop for printing the floor of asterisks
    for(int i=1; i<= TOTALHEIGHT+7; i++){
        System.out.print("*");
    }
}   

public static void printTop() {
    System.out.print("  o  ******");
}

public static void printMiddle() {
    System.out.print(" /|\\ *     ");
}

public static void printBottom() {
    System.out.print(" / \\ *     ");
}
}

需要解释什么?这是一个非常复杂的解释,需要解释一切... 如果你复制粘贴并运行它,甚至将 HEIGHT 常量更改为任何 >5 的值,它都会完美地工作。 - Andrew Engelhardt
我已经审查了你的答案,并建议你通过添加一些解释来改进你的答案。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接