I'm a beginner programmer and taking an intro to Java class. We were assigned to write a program that outputs the letter E made of asterisks with 5 down and 3 across as below:
***
*
***
*
***
The only requirement was to use nested-loops and if statements to get to our result. Below is my code. It works as intended, but I'm having trouble understanding why.
public class LetterE {
public static void main(String args[]) {
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
int row;
int column;
for (row = 1; row <= NUM_DOWN; row++) {
if (row == 1 || row == 3 || row == NUM_DOWN)
for (column = 1; column <= NUM_ACROSS; column++) {
if (column == 1 || column == NUM_ACROSS)
System.out.print("*");
}
System.out.print("*");
System.out.print(" ");
System.out.println();
}
System.exit(0);
}
}
Basically my issue comes with the System.out.print statements. I don't understand the relationship between my loops and the print statements. For example, the first print statement is inside the curly brace and taking it out causes an incorrect output. On top of that, I don't understand what the other print statements outside of that first curly brace are for and why they can't be inside the curly brace.
Any guidance would be greatly appreciated. Trying my hardest to understand how this works, but I've been stuck on it for a while now.
Thank you very very much!
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
int row;
int column;
I assume you know what the above code does, so I won't elaborate on that.
for (row = 1; row <= NUM_DOWN; row++) {
This code mean you want to execute the code inside the curly braces continuously as long as row <= NUM_DOWN
. But before doing that, we assign 1
to row
(this statement is executed only once). Each iteration ( = a full execution of the code inside the curly braces) row++
will be executed.
So we start off with row == 1
, then row == 2
, row == 3
... until row == 6
, at which point row > NUM_DOWN
, because NUM_DOWN == 5
.
If we would put all the values we have gotten for row
in a list, the list would be equal to {1,2,3,4,5,6}
, which contains 6 values. However, because the for
loop is exited when row == 6
, there are only 6 - 1 == 5
iterations.
Moving on:
if (row == 1 || row == 3 || row == NUM_DOWN){
Basically it means: if row == 1
OR row == 3
OR row == 5
, then execute the code inside the curly braces. Otherwise, skip it.
for (column = 1; column <= NUM_ACROSS; column++) {
Basically the same as the other for
loop, but just with different variables.
if (column == 1 || column == NUM_ACROSS)
Also the same as the if
statement above, but again, with different parameters.
System.out.print("*");
This will print the *
character once to the console without a newline ( = enter, basically).
The print statements that will be executed after this one will append another character to the already written characters, so your output will first look like this after the first iteration:
*
Then it will look like this after the third (in the second, column
is equal to 2, so column == 1 || column == NUM_ACROSS
is false and thus the code inside is not executed):
**
Then the loop is exited, and the other print
statement is executed.
***
A space is also appended, but it is not visible because... well, it is a space :P
The println
function is essentialy the same as print
but it also appends the escape sequence \n
. This escape sequence, called a newline, is like hitting enter on your keyboard: it starts a new line.
The next iteration, the code within the first if
statement is skipped entirely, so we jump straight to the second print
function. Now our output looks like this:
***
*
If we repeat the process, we will get:
***
*
***
.
***
*
***
*
.
***
*
***
*
***
Onto "optimizing" the program, because there is actually quite a lot of redundant code here:
int row;
int column;
Just put it inside the for
statements like this:
for (int row = 1; row <= NUM_DOWN; row++) {
It is shorter and a bit more readable ;)
if (row == 1 || row == 3 || row == NUM_DOWN){
This one is a bit odd, because on one hand, declaring NUM_DOWN makes it easier to change the height if you want to, but on the other hand, you have to edit the constants 1
and 3
manually then either way.
Let's go with the somewhat more adaptable way:
if (row == 1 || row == NUM_DOWN / 2 + 1 || row == NUM_DOWN) {
Integers are always rounded down, so 5 / 2 == 2
. The letter may look a bit odd when NUM_DOWN is even, but whatever.
for (int column = 1; column <= NUM_ACROSS; column++)
if (column == 1 || column == NUM_ACROSS)
Well, this is just a strange section of code: we would be better of starting off with column = 2
(2
because we will print another asterisk below) and scrapping the if
statement entirely (the loop will be executed for the values 2
and 3
, so 2 elements total --> 2 asterisks).
System.out.print(" ");
Since we can't read it, we can as well remove it altogether
System.out.println("*");
Again, it is shorter and it pretty much does the same thing.
System.exit(0);
Hmmm... It is not really needed, because your program returns 0 by default anyways.
The final program looks like this:
public class LetterE {
public static void main(String args[]) {
final int NUM_ACROSS = 3;
final int NUM_DOWN = 5;
for (int row = 1; row <= NUM_DOWN; row++) {
if (row == 1 || row == NUM_DOWN / 2 + 1 || row == NUM_DOWN)
for (int column = 2; column <= NUM_ACROSS; column++)
System.out.print("*");
System.out.println("*");
}
}
}