/** * Problems: *
* Given a user-specified width: * 2) Print a line of "width" asterisks (*) * That is, if the user enters 3, print 3 asterisks. * 3) Print a square box of *s with the given width (and height) * That is, if the user enters 3, prints: * *** * *** * *** * 4) Print a box with a hole in its center. * That is, print a box as in #3 but with the single * in the center * (or one close to the center for boxes with an even width) replaced * with a space. * 5) Print an equilateral triangle of *s with the given width. * The right angle should be on the lower left. So, given a width of 4: * * * ** * *** * **** * 6) Print an equilateral triangle of *s with the given width. * The right angle should be on the lower right. So, given a width of 4: * * * ** * *** * **** ** * Uncomment each solution below to run it. Uncommenting more than one at * a time may give you "bogus" output as all the boxes will run together. * * @author Zach Tomaszewski * @version 08 Oct 2009 */ public class PrintingBoxes { public static void main(String[] args) { //get user input java.util.Scanner keybd = new java.util.Scanner(System.in); System.out.print("Enter a width: "); int width = keybd.nextInt(); //XXX: Demo code, so I'm not bothering with catching exceptions // // 2) Print a line of "width" asterisks (*) // /* // // 2a) Pretty standard for loop. // for (int i = 0; i < width; i++) { System.out.print("*"); } //terminate the line properly when we're done System.out.println(); */ /* // // 2b) We don't always need to start at 0, or use only < or > // (If your loops ever produces one more or one less iteration than you // intended, look at the starting value and whether you used <= or <) // for (int i = 1; i <= width; i++) { System.out.print("*"); } System.out.println(); */ /* // // 2c) Assuming we don't need the value in width again after the loop // we could use it directly as the loop counter. // while (width > 0) { System.out.print("*"); width--; } System.out.println(); */ /* // // 2d) This loop does essentially the same thing as 2c. // While more concise than 2c, it is still probably a bad idea: // it fails to follow coding standards and is (arguably) harder // to understand. // while (width-- > 0) System.out.print("*"); System.out.println(); */ /* // // 2e) Note that all the loops above print only a blank line if given // a negative number. This one will print about 4 billion *s before // stopping if given a width of -1. Otherwise identical to 2a, // this demonstrates the subtle difference between using != and < // It still works fine for positive widths though. // for (int i = 0; i != width; i++) { System.out.print("*"); } System.out.println(); */ // // 3) Print a square box of asterisks: width x width. // /* // 3a) We already know how to print a row of width *s from above: // We used a for loop to print a single "*" width times. // Now we want to repeat all of that code--printing one row--width times. // This suggests just putting it all in a second, outer for loop: // for (int row = 1; row <= width; row++) { for (int col = 1; col <= width; col++) { System.out.print("*"); } System.out.println(); //end row } // // Above, I renamed my loop variables to make it clearer what I'm printing: // // col = 1234 (width == 4) // 1 **** // 2 **** // 3 **** // 4 **** // ^ // row // // The inner loop prints each * (or column) on a row (the horizontal numbers). // The outer loop repeats the printing each line (or row) (the vertical numbers). // So, if we think of the box as a coordinate plane, we always know the // position of the current character we're printing, as given by (col, row). // (You can also use x and y, instead of col and row, respectively.) // */ /* // 3b) This is another way to do it with only one for loop rather than two. // Basically, we know we need width * width stars to make a box; we just need // to figure out where to put the line-breaks to get a box: // for (int i = 1; i <= width * width; i++) { System.out.print("*"); if (i % width == 0) { System.out.println(); } } */ /* // // 4) Print a box with a hole in its center. // Basically, when row = width/2 and height = width/2, we're on // the center character of the box. So we should print a space in // that position. // // (This math is correct if we start at 0; if we start counting at 1, // we'd have to use (width/2)+1 instead. Also, the empty square is // off-center for even-width boxes--but see the challenge problems for // a chance to fix this!) // for (int row = 0; row < width; row++) { for (int col = 0; col < width; col++) { if (row == width / 2 && col == width / 2) { System.out.print(" "); }else { System.out.print("*"); } } System.out.println(); //end row } // To try: // What happens if we only have one of the two conditions in the if? // What happens if we use || instead of &&? // What happens if we instead test if (row == col)? // Do you understand why each such change produces the output that it does? */ // // 5) Print a right triangle with width height and width base, with the // hypotenuse going from upper-left to lower-right. // /* // 5a) To do this, we can just stop printing each row a little earlier than // if we were printing a box. Here's a triangle of size 5: // // *s printed row // * 1 1 // ** 2 2 // *** 3 3 // **** 4 4 // ***** 5 5 // // We can see that we're printing one more * on each success row. Furthermore, // the number of *s printed on each line is the exact same as the row number. // Therefore, we just need to print as long as col is <= to the length // of the row we're currently on: col <= row. Thus: // for (int row = 1; row <= width; row++) { for (int col = 1; col <= row; col++) { System.out.print("*"); } System.out.println(); } //Compare this to solution 3a. for a box. What's different? //Do you understand why it produces the output that it does? */ /* // // 5b) A different way to end the inner printing loop early. // Also, I chose to count from 0 here, which just means the loop test // needs to use < rather than <=. // for (int y = 0; y < width; y++) { for (int x = 0; x < width; x++) { System.out.print("*"); if (x == y) { System.out.println(); break; //break out of the inner for loop } } } */ /* // // 5c) In 5a and 5b, we just ended the each line early. Instead, we // could still print a width*width box of character, only replace those // we don't want to see with spaces (just like for #4). Note that we // still need to recognize the (col <= row) relationship of where *s // occur in the box, though. // for (int row = 1; row <= width; row++) { for (int col = 1; col <= width; col++) { if (col <= row) { System.out.print("*"); }else { System.out.print(" "); } } System.out.println(); } */ // // 6) Print a right triangle with width height and width base, with the // hypotenuse going from lower-left to upper-right. // /* // 6a) Again, lets look at the problem. This time, we can't just stop // printing a row early (as we did in 5a), as we need to print spaces // in order to indent the *s we print later in the line. // // So, that means we'll end up printing a character in every position // in the box. It's just that some characters will be spaces and others // will be *s. So, our printing loops will be the same as for // printing a box (3a); we just need to change which character is printed // at each position (similar to 4 and 5c). // // But what is the relationship that determines whether the currently- // printed character should be a space or *? // // spaces *s row width // * 5 1 1 6 // ** 4 2 2 6 // *** 3 3 3 6 // **** 2 4 4 6 // ***** 1 5 5 6 // ****** 0 6 6 6 // // For a triangle of size 6 (width == 6), we can see that the number of // spaces and *s add up to width on each row. So, if we're currently printing // a character that's in a col that's <= (width - row), then it should be a space; // otherwise is should be a *. // for (int row = 1; row <= width; row++) { for (int col = 1; col <= width; col++) { if (col <= width - row) { System.out.print(" "); }else { System.out.print("*"); } } System.out.println(); } */ /* // 6b) Here's another way to do this same problem. The relationship // between whether we print a space or a * is the same. // But, for each row, we might want to print all the spaces we need, // and then print all the *s: // for (int row = 1; row <= width; row++) { //first print this row's spaces for (int space = 1; space <= width - row; space++) { System.out.print(" "); } //now print this row's *s for (int asterisk = 1; asterisk <= row; asterisk++) { System.out.print("*"); } System.out.println(); } */ } }