바깥은 행, 안쪽은 열이다
Esc

    바깥은 행, 안쪽은 열이다

    –C#기초

    반복문 안에도 코드를 넣을 수 있으니, 반복문 안에 반복문을 넣을 수도 있습니다. 새로운 문법이 아닙니다. 지금까지 배운 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)을 예로 들면 이렇습니다.

    i=1 i=2 i=3 i=4 i=5 공백 4 · 별 1 공백 3 · 별 2 공백 2 · 별 3 공백 1 · 별 4 공백 0 · 별 5 공백 = N - i 별 = i
    줄 번호 i 로 개수를 나타내는 식만 찾으면 된다.

    식을 찾았으면 코드는 그대로 옮겨 적으면 됩니다. 공백을 찍는 반복문 하나, 별을 찍는 반복문 하나를 나란히 둡니다.

    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 은 줄을 바꿉니다. 줄바꿈 위치가 행을 만듭니다.
    • 별찍기는 코드 문제가 아니라 줄 번호로 개수를 나타내는 식을 찾는 문제입니다.