Write a program that prints a number of concentric squares of user-specified size to the screen.
Concepts: nested loops and conditionals.
Textbook: Chapter 5 (review)
Ask the user to enter an odd integer between 1 and 79. (If the user does not, you do not need to keep prompting them; you may just gracefully exit the program with an error message.)
Then, draw concentric squares that are alternately comprised of '#' and ' ' characters. (See the sample output below for examples.) The outer square should always be of #s and have a width and height equal to the number given by the user. This means the center character may be a ' ' or '#' depending on the size of the square. Use one or more loops to draw the square(s).
D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 10 Size must be an odd integer between 1 and 79. Please try again. D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 1 # D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 3 ### # # ### D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 5 ##### # # # # # # # ##### D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 7 ####### # # # ### # # # # # # ### # # # ####### D:\TA\grading\A13>java ZtomaszeA13 Enter the size of a square to draw (an odd number between 1 and 79): 29 ############################# # # # ######################### # # # # # # # ##################### # # # # # # # # # # # ################# # # # # # # # # # # # # # # # ############# # # # # # # # # # # # # # # # # # # # ######### # # # # # # # # # # # # # # # # # # # # # # # ##### # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ##### # # # # # # # # # # # # # # # # # # # # # # # ######### # # # # # # # # # # # # # # # # # # # ############# # # # # # # # # # # # # # # # ################# # # # # # # # # # # # ##################### # # # # # # # ######################### # # # #############################
Upload your UsernameA13.java
file to Tamarin.
Given a user-specified width:
*** *** ***
* ** *** ****
* ** *** ****
**** *** ** *
**** *** ** *
0 1 2 3 4 .. 11 12 1 1 2 3 4 11 12 2 2 4 6 8 22 24 3 3 6 9 12 33 36 . . . . . . 11 11 22 33 44 .. 121 132 12 12 24 36 48 .. 132 144That is, each entry in the table takes up 3 characters and is right-aligned, with a space between entries on the same line.
Sample solutions: DivisibleByThree.java (#1 and 1B) and PrintingBoxes.java (#2 to 6).
To help you out with this part, here's what I figured out, as well as the process that got me there.
Step 1: First, I started with a sample square large enough to notice the patterns involved (size = 7
):
Now, as you hopefully learned from the sample problems above, when printing squares of text, it is usually useful to use two nested for
loops: one for x
and one for y
. Character (0,0) would be in the upper left corner, with x increasing to the right and y increasing the farther down you go.
However, in this situation, it seemed easier to me to think about the problem if the center character was position (0,0). So the first problem is how to print the square using the following coordinate system:
size
, so we need to figure out the relationship here so we can phrase everything in terms of size
. We are going to print characters in a left-to-right and top-down order. So, instead of x and y (our loop counters) going from 0 to 6 (< size
), we want them each to go from -3 to 3. So how do we get -3 and 3 from size
(which is 7 here)? This seems to be simply:
int halfSize = size / 2;(Finally a chance to use int math intentionally!) Then we can simply iterate both x and y from
-halfSize
to +halfSize
. (If you check this with squares of different sizes--like 1, 5, 9, 11--you should find that this relationship holds. Their halfSizes would be: 0, 2, 4, 5.)
Step 2: Okay, so this lets us print the characters in terms of this coordinate system, but we still need to determine which character to print at each (x,y) character position.
Attempt 1: At first, this seemed to me to be a simple alternating pattern: if x or y is odd, print a #; otherwise, print a space. But this rule doesn't quite work: it would incorrectly print a # at positions like (-2, -1) and (-1, -2).
Attempt 2: Instead, it seems more like the distance from the center would be a better measure: if the distance is odd, print a #; if even, print a space. But this doesn't work once you get aways out from the center. For example: (-3, -3)'s distance = √((-3 * -3) + (-3 * -3)) = √18 = 4 (as an int) = even = space. But that character should be a #. So that didn't work either.
Solution: Instead, we want to simply count how many squares we are from the center, like this:
d = max(|x|, |y|)
. Or, as code:
int distance = Math.max(Math.abs(x), Math.abs(y));
Step 3: Now, we're not done quite yet. In this example (size = 7
), we want to print spaces at an even distance (0, 2, ...) and #s at an odd distance (1, 3, ...). But if you draw out the square for size = 9
, you'll see this is reversed: even distances should be #s and odd distances should be spaces. So what's the relationship here (again, in terms of size
, which is our only parameter from the user)?
Looking through my existing variables, I found a correlation with halfSize
: if halfSize
is odd, then all even-distanced characters (including the center character) should be spaces. Other characters--odd-distanced characters--should be #s.
On the other hand, if halfSize
is even, then even-distanced characters (and the center character) should be #s.
So you can think about this over, here's all three images together:
As always: This is just one way to solve this problem. I am sure there are others.
If these give you trouble, look at the sample solutions (once posted). Make sure you understand how each for loop works. That doesn't mean stare glassy-eyed at it for a minute and then maybe run the program to see it prints some stuff. For those you don't understand, you may need to get out a piece of paper and pretend you are a computer. Pick an example value for width
--like 3 or 4. Then trace through the code of each example like I do on the board in lab: line-by-line, drawing a box for each variable declared and tracking how its value changes and what gets printed to the screen. Once you understand how these examples work, it'll be a lot easier to write your own solution.
Next, get out a piece of paper and plan your algorithm. The process I went through is outlined above, but you're still going to need to understand it. Draw some sample output. Sketch out your code structure without worrying about syntax: where do your for loops go? Which one is x and which one is y? Where do your if statements go? Trace through it manually to see if your logic is correct.
Once you feel you understand the problem, then you can finally open a text editor and start writing code. I'd still recommend taking it step-by-step:
size
from the user. Make sure it is odd and between 1 and 79. Draw a solid box of #s of the correct size.
halfSize
to determine what to print for the current (x, y) character: either a space or a #.
for
loop go?
for (int y = 0; y < width; y++) { for (int x = 0; x < width; x++) { System.out.print("*"); } System.out.println(); }
Assuming width
is a user-specified value, this will print a box of *s of that size. (See example Problem 3 above.) Note that both of these loops start at 0 and go through 1 less than width. So the inner loop prints each row, and the outer loop specifies how many rows to print. Therefore, each character printed will have a unique (x, y) value when printed.
To solve the other sample problems and A13, you can just use a conditional within the inner loop to decide what character to print for the current (x, y). That is, you want to print only one character each time through the inner loop, but that character might a "#" or it might be a " " depending on the current (x,y) position.