개발/Java

자바 반복문(for문)을 활용한 별 찍기 예제 2가지

냐냐_ 2021. 3. 19. 10:29

자바 반복문 공부할 때 꼭 한번쯤 해 본다는 그 예제!

별 찍기.

 

출처 : YouTube TechDiffuse

 

자바 공부 초반에, 수업 중 for문을 엄청 빠르게 배웠었는데

그게 너무 이해가 안 가서 힘들었던 기억이 난다.

(제가 문과라서요... 라고 하기엔 다른 문과 친구들은 곧잘 이해했었음)

 

근데 지금은 눈 감고도 반복문 돌릴 수 있는 거 보면,

그냥 이 개념이 나에게 생소했던 듯 하다.

 

당시 새벽까지 찍고 또 찍어냈던 수많은 별들을 추억하며-

나처럼, '무슨 말인지 알겠는데 모르겠다' 싶은 이들을 위해

좀더 쉽게 차근차근 별 찍기 과정을 기록해 본다.

순한 맛 하나, 매콤한 맛 하나 두 가지로 풀이!

 

 

 

 

 

이중 for문을 사용한 별 찍기 - 순한 맛

 

 

줄을 바꾸면서 별표만 하나씩 늘려 가는 예제이다.

얘가 어떻게 반복문인지를 뜯어 보면,

 

 

크게 봐서는, 무언가가 5번 반복되면서 5줄짜리 결과물을 만들어내고 있다.

그럼 일단 이렇게 짤 수 있다.

 

// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
    


    
} // 1번 for문 닫음 

 

 

 

 

 

그리고 작게 봐서는,

별 X 1 / 별 X 2 / 별 X 3 / 별 X 4 / 별 X 5, 이렇게 별 하나가 반복되고 있다.

 

익숙하지 않을 때는 이렇게 단순한 별나무도 식을 짜기 쉽지 않으니,

엑셀이나 노트의 힘을 빌어 정리를 하면 눈에 잘 들어온다.

위 예제는 별도의 공백이 없이 별만 반복되므로 두 개만 파악하자!

 

(i) 몇 번째 줄? (j) 별 몇 개?
1 1
2 2
.
.
.
.
.
.
5 5

 

감사하게도 참 간단하다!

i = j 가 아닌가!

규칙을 발견했으니 반복문을 설계해 본다.

 

// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
    
    // 2. 별표의 변화 : 1-2-3-4-5
    for (int k=0; k< i+1; k++) {
        System.out.print("*");
    }
    
//별표가 원하는 갯수만큼 찍히고 나면 줄바꿈을 해야 한다.
    System.out.println();
    
} // 1번 for문 닫음 

 

주의할 점 : 별표가 반복될 땐 줄바꿈 없이 반복되므로 print'ln' 아님.

대신 별표 반복이 끝난 후 줄을 바꿔줘야 하니 줄바꿈용 println 하나 넣기!

 

 

 

 

 

Q. 별표도 1-2-3-4-5개 순으로 늘어나니까,

i반복문과 똑같이 k<5 로 범위를 잡으면 안 되나요?

A. 안 됩니다. 그럼 모든 줄에 별이 5개씩 찍히니까요!

i의 값이 바뀌면 k도 그 값에 맞추어서 바뀌도록 해야 해요!

 - 첫번째 줄일 땐 한 개, 두번째 줄일 땐 두 개, 이렇게 :)

 

줄 번호 별의 개수 별의 범위
1번 줄 i=0 별 1개 k=0 k<1
2번 줄 i=1 별 2개 k=0, k=1 k<2
3번 줄 i=2 별 3개 k=0, k=1, k=2 k<3
.
.
.
5번 줄 i=4 별 5개 k=0, k=1, k=2, k=3, k=4 k<5

 

어려울 땐 이렇게 풀어서 생각하면 됨!

i값과 k범위만 떼어놓고 보면,

0일때 1, 1일때 2, ... , 4일때 5의 규칙이 보인다.

 

for (int k=0; k< i+1; k++) {}

 

그래서 별표를 위한 반복문 k에서, k의 범위식이 k+1이 된 것이다!

 

별표 예제의 핵심은, 자바에 빙의해서

한 줄 한 줄씩 코드 순서대로 따라가며 값을 확인해 보는 것이다.

 

 

 

 

 

이중 for문을 사용한 별 찍기 - 매콤한 맛

매운 맛이 아니라 매콤한 맛이라고 명명한 이유는

작정하고 어려우려면 훨씬 어려운 예제들도 있어서.

 

 

그치만 이 예제를 찍을 수 있으면 충분한 것 같아서 우선은 요 녀석을 골랐다!

얘 역시 무언가가 5줄 반복되는 예제이기 때문에

 

// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
    


    
} // 1번 for문 닫음 

 

여기까지는 똑같다.

그런데...

 

 

이 예제에서는 별표가 1, 2, 3, 4, 5가 아닌

1, 3, 5, 7, 9로 2개씩 증가하며

무엇보다 '공백'이라는 빌런이 등장한다. (노란 색 블럭)

모든 줄은 [공백] + [별표] 순서대로 등장한다.

공백과 별표는 포함관계가 아니라 그냥 전-후 관계로 반복시켜주면 되겠다.

 

공백이 들어간 예제 계산이 헷갈릴 때는, 오른쪽 그림처럼

엑셀에 별표를 그리고 공백을 색칠한 뒤 시작하면 좀 쉽다.

 

줄 번호
별의 개수 공백의 개수
1번 줄 i=0 별 1개 4칸
2번 줄 i=1 별 3개 3칸
3번 줄 i=2 별 5개 2칸
4번 줄 i=3 별 7개 1칸
5번 줄 i=4 별 9개 0칸

 

확실히... 어려워졌다.....!

공백이 등장한 것도 짜증나는데 왜 거꾸로 줄어들고 난리.

하지만 역시 한 줄씩 찬찬히 뜯어보면 할 수 있다.

 

위의 순한 맛 예제를 통해서,

별, 공백 반복문(안쪽 for문들)은 줄 반복문(바깥 for문)과 따로 놀지 않고

바깥 for문의 i값이 변할 때 같이 범위가 변해주어야 한다는 것을 배웠으니

그것만 잊지 않으면 된다.

 

임의로 별 반복문은 j, 공백 반복문은 k라는 변수를 쓴다고 전제하자.

 

 

 

 

 

먼저 별부터 풀어보면,

 

줄 번호
별의 개수
1번 줄 i=0 별 1개
2번 줄 i=1 별 3개
3번 줄 i=2 별 5개
4번 줄 i=3 별 7개
5번 줄 i=4 별 9개

 

(i값이) 0일때 (j값은) 1,

1일때 3,

2일때 5,

3일때 7,

4일때 9

이 규칙을 찾아야 한다.

 

이럴 땐 대부분 i에 공차인 2를 곱해 준 다음에

더하든 빼든 해서 범위를 맞춰주면 된다.

0은 곱셈에서 도움이 안 되니까 제끼고 생각해 보면

 

1 * 2   + 1 = 3

2 * 2   + 1 = 5

3 * 2   + 1 = 7

 

찾았다!

i * 2   + 1 = j 이다. (0일 때도 적용된다. 4일 때도 된다.)

 

 

 

 

 

// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
    
    // 2. 공백의 변화 : 4-3-2-1-0
	
    

    }
    
    // 3. 별표의 변화 : 1-3-5-7-9
    for (int k=0; k< 2*i +1; k++) {
        System.out.print("*");
    }
    
//공백과 별표가 한 차례씩 찍히고 나면 줄바꿈을 해야 한다.
    System.out.println();
    
} // 1번 for문 닫음 

 

 - 순한 맛 예제와 마찬가지로, *이 반복될 땐 줄바꿈이 일어나면 안 된다.

 

 

 

 

 

그럼 이제 공백만 찾아주면 되는데...

 

 

줄 번호
공백의 개수
1번 줄 i=0 4칸
2번 줄 i=1 3칸
3번 줄 i=2 2칸
4번 줄 i=3 1칸
5번 줄 i=4 0칸

 

공백 반복문 k도, 별표 반복문 j와 마찬가지로

i값의 영향을 받아 범위가 결정되어야 한다는 것을 기억하고 규칙을 찾자

 

(i값이) 0일때 (k값은) 4,

1일때 3,

2일때 2,

3일때 1,

4일때 0

 

공차는 -1이다. 2나 3이 아니니까 곱셈을 할 필요는 없고

이렇게 값이 늘지 않고 줄어들 때는 i에도 음수를 붙여서 규칙을 찾으면 된다.

 

4 - 0 = 4

4 - 1 = 3

4 - 2 = 2

 

찾았다!

4 - i = k 이다.

i가 0일 때도, i가 4일 때도 적용된다.

 

그런데 여기서 잠깐,

우리가 반복문 범위를 설정할 때를 다시 떠올려본다.

만약, 3번 돌리고 싶은 반복문이 있다면

 

for (int m=0; m<3; m++){}
for (int m=1; m<=3; m++){}

 

이렇게 두 가지 방법이 있지 않은가!

(m을 0~2로 돌리거나 / m을 1~3으로 돌리거나)

 

위에서 찾은 4-i=k 를 우리가 쓰려는 j반복문에 적용시켜서

 

for (int j=0; j<4-i ; j++)

이렇게 표시하게 되면, j값의 범위는

i=0 일 때 j<4 (의 최대값은 3)

i=4일 때 j<0 이 되어서 (반복문 돌지 않음)

우리의 의도와 달라진다.

그러므로,

 

for (int j=0; j<=4-i ; j++) {}
for (int j=0; j<5-i ; j++) {}

4-i보다 "작거나 같다" 고 설정하거나,

맘 편히 5-i보다 "작다" 고 설정하면 된다.

 

이중 for문을 활용한 별표 예제를 짤 때 또 다른 팁!

i가 최소일 때의 시뮬레이션과 i가 최대일 때의 시뮬레이션으로

반드시 안쪽 for문의 범위가 맞는지 확인하자.

 

 

 

 

 

// 1. 총 몇 줄 돌리나? 5줄!
for (int i=0; i<5; i++) {
    
    // 2. 공백의 변화 : 4-3-2-1-0
    for (int j=0; j<5-i ; j++) {
        System.out.print(" "); 
    }
    
    // 3. 별표의 변화 : 1-3-5-7-9
    for (int k=0; k< 2*i +1; k++) {
        System.out.print("*");
    }
    
//공백과 별표가 한 차례씩 찍히고 나면 줄바꿈을 해야 한다.
    System.out.println();
    
} // 1번 for문 닫음 

 

한 단계씩 차근차근 적느라 조금 길어졌지만

이해하고 나면 명료하다.

이렇게 두 개의 별표 예제 완성!