Java程序:生成圣诞树:格式化?

时间:2014-09-05 12:30:24

标签: java

所以在我的CS课程中,我们有一个小问题,并且它不会在一周左右到期而且几乎除了一小块之外还有效。这是作业:

  

编写一个名为ChrisTree的程序,它生成圣诞树的图像作为输出。它应该有一个带有两个参数的方法:一个用于树中的段数,另一个用于每个段的高度。例如,左边显示的树有三个高度为4的段,右边的一个有两个高度为5的段。

Image of two ASCII Christmas trees, with the left tree having three triangles, and the right having two triangles.

所以我的代码工作正常,除了树的最后一行是树的一些树,而树干都是空格。我似乎无法在没有制作新洞的情况下插上那个洞。任何人都看到问题的可能“根”? PS树的分段和高度是可变的,通过改变类常量(我知道,它是一种改变它们的可怕方法,但这就是这个人想要的东西)(我知道它可能非常多余)

public class ChrisTree {
  public static final int SEGMENTS = 4;
  public static final int HEIGHT = 4;
  public static void main(String[] args){
  makeTree();
  }
  // makeTree: code that prints the tree; params: num. of segments of tree, height of tree segments
  public static void makeTree(){
  // maxStars: calculation the length of each line which is the sum of spaces and stars for any line
    int maxStars = 2*HEIGHT+2*SEGMENTS-3;
    // maxStr: master variable string that will be changed and printed for each line
    String maxStr = "";
    // populates maxStr will spaces; will be used with substring to generate needed spaces
    for (int len=0; len < maxStars; len++){
      maxStr+=" ";
    }
    // loops once per segment
    for (int i=1; i <= SEGMENTS; i++){
      // starStr: variable string that changes perline that holds the stars

      // populates starStr with stars
      // loops through each line
      for (int line=1; line <= HEIGHT; line++){
        String starStr = "";
        for (int j=1; j <= 2*line+2*i-3; j++){
          starStr+="*";
        }
        for (int space=0; space <= maxStars-(HEIGHT+line+i); space++){
          starStr = " " + starStr;
        }
        System.out.println(starStr);
      }
    }

    for (int i=0; i <= maxStars/2;i++){
      System.out.print(" ");
    }
    System.out.print("*\n");
    for (int i=0; i <= maxStars/2;i++){
      System.out.print(" ");
    }
    System.out.print("*\n");
    for (int i=0; i <= maxStars/2-3;i++){
      System.out.print(" ");
    }
    System.out.print("*******\n");
  }
}

2 个答案:

答案 0 :(得分:1)

在我做明显的家庭作业问题的辩护中,这里的解决方案太过伤害了我的眼睛。 (而且我知道这些都是标准的家庭作业问题,我在80年代用Pascal做过它们。)

package com.edwinbuck.christmas;

/**
 * Draws a ChristmasTree.

 * @author Edwin Buck
 */
public class ChristmasTree {

    public static final int SEGMENTS = 4;
    public static final int HEIGHT = 4;

    public static void main(String[] args) {
        int maxSize = 1 + 2 * (SEGMENTS - 1) + 2 * (HEIGHT - 1);
        // for each segment beyond zero, we need 2 more asterisks.
        for (int segmentContrib = 0; segmentContrib < 2 * SEGMENTS; segmentContrib += 2) {
            // for each segment slice beyond zero, we need 2 more asterisks.
            for (int sliceContrib = 0; sliceContrib < 2 * HEIGHT; sliceContrib += 2) {
                drawCentered(maxSize, 1 + segmentContrib + sliceContrib);
            }
        }
        // draw the trunk
        drawCentered(maxSize, 1);
        drawCentered(maxSize, 1);
        // draw the base
        drawCentered(maxSize, 7);
    }

    /**
     * Draws a line of asterisks, centered within size spaces.
     *
     * @param size The size to center on.
     * @param asterisks The number of asterisks to draw.
     */
    private static void drawCentered(int size, int asterisks) {
        int before = (size - asterisks) / 2;
        int after = size - before - asterisks;
        print(before, " ");
        print(asterisks, "*");
        print(after, " ");
        System.out.println();
    }

    /**
     * Draws a character a number of times.
     *
     * @param count The number of time to draw the character.
     * @param character The character to draw.
     */
    private static void print(int count, final String character) {
        for (int i = 0; i < count; i++) {
            System.out.print(character);
        }
    }

}

关键是要意识到所有的线都是可变大小的中心星号。一旦你这样做,那么你只需要找出绘制截面的循环(以及最大的线条大小)。

最大线宽由最底部控制。每个输入(SEGMENTSHEIGHT)需要从“从1开始计数”转换为“从0开始计数”。每个附加段都会在星号大小上添加两个,每个附加切片也是如此。树必须至少有一个星号,一个(树干)沿着中心向下延伸。这导致公式

 1 + 2*(SEGMENTS-1) + 2(HEIGHT-1)

许多已简化为

 2*SEGMENTS + 2*HEIGHT - 3

我没有简化它,因为它隐藏了 intent ,一旦丢失,很难在代码中恢复。

然后,当我走过循环时,我决定让大小增加的贡献者增加两个。它使数学的其余部分更容易,因为我们不必将“魔术”公式和数学放在奇数位置。这意味着我们可以使用参数drawCentered(...)重用我们的1 + segmentContrib + sliceContrib,其中两个其他变量是段和切片“星号”贡献。

最后,我们绘制了一个由两个垂直星号和底座组成的主干。

答案 1 :(得分:0)

我知道这已经很晚了,但我刚写了这篇文章并且有效。

public class ChrisTree {
    public static final int SEGMENTS = 4;
    public static final int HEIGHT = 4;

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

    public static void makeTree() {
        int maxStars = 2 * HEIGHT + 2 * SEGMENTS - 3;
        String maxStr = "";
        for (int l = 0; l < maxStars; l++) {
            maxStr += " ";
        }
        for (int i = 1; i <= SEGMENTS; i++) {
            for (int line = 1; line <= HEIGHT; line++) {
                String starStr = "";
                for (int j = 1; j <= 2 * line + 2 * i - 3; j++) {
                    starStr += "*";
                }
                for (int space = 0; space <= maxStars - (HEIGHT + line + i); space++) {
                    starStr = " " + starStr;
                }
                System.out.println(starStr);
            }
        }

        for (int i = 0; i <= maxStars / 2; i++) {
            System.out.print(" ");
        }
        System.out.println(" " + "*" + " ");
        for (int i = 0; i <= maxStars / 2; i++) {
            System.out.print(" ");
        }
        System.out.println(" " + "*" + " ");
        for (int i = 0; i <= maxStars / 2 - 3; i++) {
            System.out.print(" ");
        }
        System.out.println(" " + "*******");
    }
}