바깥은 행, 안쪽은 열이다
반복문 안에도 코드를 넣을 수 있으니, 반복문 안에 반복문을 넣을 수도 있습니다.
새로운 문법이 아닙니다. 지금까지 배운 for 를 그대로 겹쳐 놓은 것입니다.
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 3; j++)
{
Console.Write("*");
}
Console.WriteLine();
}
바깥이 한 번 돌 때마다 안쪽은 처음부터 끝까지 전부 돕니다.
아파트를 생각하면 됩니다. 한 층의 모든 집을 다 돌고 나서야 다음 층으로 올라갑니다. 바깥이 층, 안쪽이 호수입니다.
총 실행 횟수는 바깥 횟수 × 안쪽 횟수입니다. 위 코드는 별을 아홉 번 찍습니다.
Write 와 WriteLine 이 행을 만든다
여기서 처음 보는 것이 Console.Write 입니다.
| 하는 일 | |
|---|---|
Console.Write("*") |
찍고 그 자리에 멈춘다. 다음 것이 옆에 붙는다 |
Console.WriteLine() |
줄을 바꾼다 |
안쪽 반복문이 Write 로 별을 옆으로 이어 찍고,
안쪽이 끝난 뒤 바깥에서 WriteLine() 으로 줄을 바꿉니다.
줄바꿈을 어디에 두느냐가 행을 만듭니다.
WriteLine() 을 안쪽 반복문 안에 넣으면 별 하나마다 줄이 바뀌어서
세로로 한 줄씩 아홉 줄이 나옵니다. 위치 하나로 모양이 완전히 달라집니다.
안쪽은 매번 1부터 다시 센다
안쪽 조건에 i 를 넣으면 줄마다 개수가 달라집니다.
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= i; j++) // 조건에 i 가 들어갔습니다
{
Console.Write("*");
}
Console.WriteLine();
}
j 가 1부터 다시 시작하는 것이 중요합니다.
int j = 1 은 안쪽 for 의 시작 칸이고, 시작 칸은 그 반복문에 들어갈 때마다 실행됩니다.
바깥이 한 바퀴 돌 때마다 안쪽 반복문에 새로 들어가는 것이니 j 도 새로 1이 됩니다.
달력과 같습니다. 달이 바뀌면 날짜는 다시 1일부터입니다.
| 바깥 i | 안쪽 j 가 도는 값 | 별 개수 | 출력 |
|---|---|---|---|
| 1 | 1 | 1 | * |
| 2 | 1, 2 | 2 | ** |
| 3 | 1, 2, 3 | 3 | *** |
| 4 | 1, 2, 3, 4 | 4 | **** |
| 5 | 1, 2, 3, 4, 5 | 5 | ***** |
별찍기가 뭔가
방금 만든 삼각형이 이른바 별찍기 입니다. 이중 반복문 연습으로 거의 항상 나오는 문제라 이름이 붙었습니다.
하는 일은 단순합니다. 별(*)과 공백만 써서 정해진 모양을 콘솔에 출력합니다.
줄 수 N 을 주면 그 크기에 맞게 나와야 합니다.
N = 5 일 때 자주 나오는 모양들입니다.
직각 삼각형 (방금 만든 것)
*
**
***
****
*****
오른쪽 정렬
*
**
***
****
*****
피라미드
*
***
*****
*******
*********
모양만 보면 셋이 전혀 다른 문제 같습니다. 실제로는 뼈대가 똑같습니다. 바깥 반복문이 줄을 세고, 안쪽 반복문이 그 줄에 찍을 것을 셉니다. 방금 본 그 구조 그대로입니다.
이 문제가 연습으로 쓰이는 이유가 있습니다.
- 바깥이 행, 안쪽이 열이라는 것이 눈에 그대로 보입니다.
- 틀리면 모양이 바로 깨지니 결과를 확인하기 쉽습니다.
- 줄마다 개수가 달라지므로 안쪽 조건을 바깥 변수로 쓰는 연습이 됩니다.
여기서 어려운 것은 문법이 아닙니다. 문법은 지금까지 본 for 가 전부입니다.
어려운 것은 몇 개를 찍을지를 줄 번호로 나타내는 것입니다.
별찍기는 규칙을 먼저 찾는 문제다
그래서 별찍기 문제를 만나면 코드부터 쓰고 싶어지는데, 그러면 잘 안 됩니다. 코드는 규칙을 찾고 나서 기계적으로 나옵니다.
먼저 격자를 그리고 i 번째 줄에 공백 몇 개, 별 몇 개인지만 셉니다.
오른쪽 정렬 삼각형(N = 5)을 예로 들면 이렇습니다.
식을 찾았으면 코드는 그대로 옮겨 적으면 됩니다. 공백을 찍는 반복문 하나, 별을 찍는 반복문 하나를 나란히 둡니다.
for (int i = 1; i <= N; i++)
{
for (int s = 0; s < N - i; s++) // 공백 = N - i
{
Console.Write(" ");
}
for (int j = 0; j < i; j++) // 별 = i
{
Console.Write("*");
}
Console.WriteLine();
}
안쪽 반복문이 두 개라도 이중 반복문입니다. 안쪽끼리는 형제이지 겹친 것이 아닙니다.
네 가지 패턴이 전부 같은 문제다
별찍기 문제는 모양만 다를 뿐 푸는 방법이 같습니다. 격자를 그리고 표를 채우면 끝입니다.
| 문제 | 공백 개수 | 별 개수 | 메모 |
|---|---|---|---|
| 역직각 삼각형 | 0 | N - i + 1 |
줄이 갈수록 별이 줄어든다 |
| 오른쪽 정렬 | N - i |
i |
공백을 먼저 찍는다 |
| 피라미드 | N - i |
2 * i - 1 |
별이 홀수 개로 늘어난다 |
| 다이아몬드 | N - i |
2 * i - 1 |
피라미드 뒤에 역피라미드 N - 1 줄 |
피라미드에서 별이 2 * i - 1 인 이유는 좌우로 하나씩 늘어나기 때문입니다.
1, 3, 5, 7, 9. 홀수만 나옵니다.
다이아몬드는 새 문제가 아닙니다. 피라미드를 찍고, 이어서 역피라미드를 찍는 것입니다. 반복문을 두 번 쓰면 됩니다. 처음부터 다이아몬드 공식을 찾으려 하면 어렵고, 둘로 쪼개면 이미 푼 문제 두 개입니다.
정리
- 이중 반복문은 새 문법이 아니라
for안에for를 넣은 것입니다. - 바깥이 한 번 돌 때마다 안쪽은 처음부터 끝까지 전부 돕니다.
- 총 실행 횟수는 바깥 횟수 × 안쪽 횟수입니다.
- 안쪽의 시작 칸은 바깥이 한 바퀴 돌 때마다 다시 실행됩니다.
j는 매번 1부터입니다. - 안쪽 조건에
i를 쓰면 줄마다 개수가 달라져서 삼각형이 됩니다. Write는 옆으로 이어 찍고WriteLine은 줄을 바꿉니다. 줄바꿈 위치가 행을 만듭니다.- 별찍기는 코드 문제가 아니라 줄 번호로 개수를 나타내는 식을 찾는 문제입니다.