6
\$\begingroup\$

I'd like someone to suggest a better way to create this pattern in Java which I'm sure is possible:

*********
*       *
*       *
*       *
*       *
*       *
*       *
*       *
*********

I'm working my way through a new Java book and am examining string patterns.

public static void drawRectangle() {

    // y axis
    for( int y = 0; y <= 8; y++ )
    {
        if( y == 0 || y == 8 )
        {
            System.out.print( "*********\n" );
            if( y == 8 )
            {
                // Leave loop
                break;
            }
        }

        // x axis
        for( int x = 0; x <= 8; x++ )
        {
            if( x == 0 || x == 8 )
            {
                System.out.print( "*" );
                if( x == 8 )
                {
                    System.out.println();
                }
            }
            else
            {
                System.out.print( " " );
            }
        }
    }
}

Off the top of my head, I'd say that I could replace the values in the loops with constants to work towards. For example:

final static int END_POINT = 8;

Any thoughts?

\$\endgroup\$
  • \$\begingroup\$ When doing a lot of string concatenations, you should instead use a StringBuilder. This is for performance reasons, so it is actually not very important for your problem. \$\endgroup\$ – toto2 Sep 17 '13 at 1:46
  • \$\begingroup\$ it may be for this particular problem but I'm sure I'll come across it again at some point. Thanks \$\endgroup\$ – Katana24 Sep 17 '13 at 9:19
9
\$\begingroup\$

It's ok for a first iteration.

  1. But your 2nd iteration should be drawRectangle(int width, int height). That will force you to not hard-code your numbers.
  2. Your 3rd iteration should be noticing that your rectangle only has 2 different rows (one row fills up the width with * and the other only has * in the beginning and end). You might want to make a method drawHorizontal to draw the top and bottom and drawEnds to draw the sides. For example

    void drawHorizontal(int width) {
      for (int i=0 ; i<width ; i++) {
         System.out.print("*");   /* notice I'm using print() not println() */
      }
      System.out.println("");     /* notice I'm using println() */
    }

    void drawEnds(int width) {
      System.out.print("*");
      for (int i=1 ; i<width-1 ; i++) {
         System.out.print(" ");
      }
      System.out.println("*");
    }
\$\endgroup\$
  • \$\begingroup\$ Just for your information, I put together a fast speed test. Creating a string and outputting the whole string instead of printing single characters is a lot faster. Now that I think about it, iteration 4 should most likely return complete strings anyway. \$\endgroup\$ – Bobby Sep 17 '13 at 10:04
  • \$\begingroup\$ @Bobby, yes but I wasn't sure if I should tell the OP about StringBuilder at this point. \$\endgroup\$ – Apprentice Queue Sep 17 '13 at 15:43
  • \$\begingroup\$ I think a fourth or even fifth iteration with changes up to "I'd do it like this in the end" would be a very good addition and shouldn't be too hard to understand. \$\endgroup\$ – Bobby Sep 17 '13 at 16:19
2
\$\begingroup\$

Interface suggestions

Anything that can be parameterized instead of hard-coded should be. I would pass the dimensions to the Rectangle constructor. Then I would create a draw(PrintStream out) method. In other words, the rectangle knows how to draw itself to a PrintStream of your choice, whether it's System.out or some other output destination.

Loop Simplification

You can simplify your code by letting Arrays.fill() do the boring looping work to populate some buffers. Then, you only need one for-loop to iterate over the rows. A bonus is that you take advantage of the fact that many of the lines to be printed are identical to each other.

Solution

import java.io.PrintStream;
import java.util.Arrays;

public class Rectangle {
    private int rows, cols;

    public Rectangle(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
    }

    public void draw(PrintStream out) {
        char[] buf = new char[cols];

        Arrays.fill(buf, '*');
        String cap = new String(buf);

        Arrays.fill(buf, 1, cols - 1, ' ');
        String body = new String(buf);

        out.println(cap);
        for (int i = rows - 2; i >= 0; i--) {
            out.println(body);
        }
        out.println(cap);
    }

    public static void main(String[] args) {
        (new Rectangle(8, 8)).draw(System.out);
    }
}
\$\endgroup\$
0
\$\begingroup\$

Alternative way to make Rectangle.

public class myclass {
    // Input the size of the Rectangle.

    static int hight = 8;
    static int width = 8;

    public static void main(String[] args) {
        line(width);
        for (int m = 0; m < hight - 2; m++) {
            starWithSpace();
            System.out.println();
        }
        line(width);
    }

    public static void space() {
        System.out.print(" ");
    }

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

    public static void starWithSpace() {
        printStar();
        for (int i = 0; i <= hight - 2; i++) {
            space();
        }
        printStar();
    }

    public static void line(int width) {
        for (int header = 0; header <= width; header++) {
            printStar();
        }
        System.out.println("");
    }
}
locked by Jamal May 4 '18 at 3:45
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.