무엇을 만드나
격자를 그리려면 줄을 하나씩 찍어야 합니다.
주어진 문제
큰 종이를 가로 W칸, 세로 H칸으로 자르려고 합니다. 자를 자리를 표시한 격자 모양을 화면에 그려 주는 프로그램을 만듭니다.
가로 4칸, 세로 3칸이면 이렇게
+---+---+---+---+ | | | | | +---+---+---+---+ | | | | | +---+---+---+---+ | | | | | +---+---+---+---+
그림처럼 보이지만 화면은 위에서 아래로 한 줄씩 찍힐 뿐입니다. 그러니 이 문제는 「어떤 줄을 몇 번 찍을 것인가」로 바꿔 놓아야 풀립니다. 모양을 줄의 반복으로 바꾸고 나면 나머지는 그 줄을 찍는 일입니다.
| 단계 | 여기서 답할 질문 |
|---|---|
| 1 요구 분석 | 무엇을 입력받고 어떤 기호로 그릴 것인가 |
| 2 설계 | 몇 종류의 줄이 각각 몇 번 나오는가 |
| 3 구현 | 한 줄을 어떻게 만들고 반복을 어디서 끊을 것인가 |
| 4 테스트 | 칸이 하나뿐일 때도 모양이 맞는가 |
먼저 개발 문서 양식을 내려받으세요
읽기만 하지 말고 직접 채워 보세요. 단계마다 자기 답을 적어 두면 그 기록이 요구 사항 명세서이자 설계서가 됩니다. 답을 보기 전에 먼저 적어 봅니다.
요구 분석과 설계는 언어와 상관없습니다. 두 양식의 앞부분은 같고, 구현을 적는 자리만 언어에 맞춰 다릅니다. 수업에서 쓰는 언어에 맞는 것을 받으면 됩니다. 이 강의노트의 코드 예시는 파이썬으로 되어 있습니다.
1단계 · 무엇을 만들 것인가
모양을 말로 정확히 적어 두어야 합니다.
되물어야 할 것들
- 한 칸의 크기는? 가로로 몇 글자, 세로로 몇 줄인가요
- 어떤 기호를 쓰나요? 모서리와 가로선과 세로선을 각각 무엇으로
- 0칸이 들어오면? 아무것도 안 그리나요
- 얼마나 큰 값까지? 화면을 넘어가면 어떻게 하나요
정리한 요구 사항
- 가로 칸 수와 세로 칸 수를 한 줄에 공백으로 띄어 정수로 입력받는다.
- 모서리는 +, 가로선은 -, 세로선은 |로 그린다.
- 한 칸의 가로 폭은 세 글자, 세로 높이는 한 줄로 한다.
- 칸 안쪽은 공백 세 칸으로 비워 둔다.
- 격자의 맨 위와 맨 아래에도 경계선이 있어야 한다.
- 가로와 세로 모두 1 이상이 들어온다고 본다.
3번과 4번을 안 적으면 그림이 어긋납니다
가로선이 세 글자인데 칸 안쪽을 한 칸만 비우면 위아래 선이 서로 어긋나 격자로 보이지 않습니다. 눈으로 보면 바로 알지만 말로 적어 두지 않으면 틀리기 쉬운 종류의 요구 사항입니다. 「보기 좋게」 같은 말로는 이것을 못 정합니다.
요구 사항 5번을 「칸마다 위에 경계선을 하나씩」이라고만 적으면 어디가 빠질까요? 가로 4칸, 세로 3칸 그림에서 세어 보세요.
2단계 · 두 종류의 줄이 번갈아 나온다
줄을 세어 보면 규칙이 보입니다.
| 토막 | 무엇을 정하는가 |
|---|---|
| 입력 | 가로 칸 수와 세로 칸 수, 정수 두 개 |
| 처리 | 두 종류의 줄을 만들어 정해진 횟수만큼 번갈아 찍는다 |
| 출력 | 여러 줄 — 경계선과 칸 줄이 번갈아 나온다 |
줄은 두 종류뿐이다
| 종류 | 어떻게 만드나 (가로 4칸일 때) | 몇 번 나오나 |
|---|---|---|
| 경계선 | +---를 가로 칸 수만큼 이어 붙이고 끝에 + 하나 | 세로 칸 수 + 1번 |
| 칸 줄 | |와 공백 세 칸을 가로 칸 수만큼 이어 붙이고 끝에 | 하나 | 세로 칸 수만큼 |
두 줄 다 「같은 조각을 여러 번 + 마지막에 하나」라는 같은 모양입니다. 칸이 넷이면 조각이 넷이고 마감이 하나 — 울타리 기둥이 칸보다 하나 많은 것과 같습니다.
경계선이 하나 더 많습니다
세로 3칸이면 칸 줄은 3개인데 경계선은 4개입니다. 칸 사이마다 하나씩에 맨 위와 맨 아래까지 있기 때문입니다. 그래서 「경계선 → 칸 줄」을 세로 칸 수만큼 반복하면 마지막 경계선 하나가 모자랍니다. 반복 밖에서 한 번 더 찍어야 합니다.
푸는 순서
- 가로 칸 수와 세로 칸 수를 입력받는다.
- 세로 칸 수만큼 반복한다.
- 경계선을 한 줄 찍는다.
- 칸 줄을 한 줄 찍는다.
- 반복이 끝나면 경계선을 한 줄 더 찍는다.
가로 4칸의 경계선에는 +가 몇 개 들어갈까요? 그리고 그 수가 4와 어떤 관계인지 말해 보세요.
3단계 · 파이썬으로 옮기기
같은 조각을 여러 번 이어 붙이는 방법이 있습니다.
먼저 스스로 적어 본 뒤에 코드를 보세요. 설계가 짧아 코드도 짧습니다.
종이.기본.py
# 가로 칸 수와 세로 칸 수를 입력받는다
w, h = map(int, input().split())
for _ in range(h):
print("+---" * w + "+") # 경계선
print("| " * w + "|") # 칸 안쪽
# 마지막 경계선은 반복 밖에서 한 번 더 찍는다
print("+---" * w + "+")문자열에 곱하기를 하면 반복됩니다
수끼리 곱하면 계산이 되지만 문자열에 정수를 곱하면 그만큼 이어 붙습니다. 그래서 조각 하나를 칸 수만큼 곱하고 끝에 마감을 더하면 한 줄이 완성됩니다. 반복문을 하나 더 쓰지 않아도 되는 것이 이 방법의 이점입니다.
반복이 도는 값을 쓰지 않는 경우
반복이 도는 숫자를 번호로 쓰는 경우가 많습니다. 여기서는 몇 번째인지가 필요 없습니다 — 그저 세로 칸 수만큼 반복하면 됩니다. 그래서 이름을 지어 주지 않고 밑줄 하나로 두었습니다. 「이 값은 안 쓴다」는 뜻을 읽는 사람에게 알려 주는 관례입니다.
마지막 경계선을 찍는 줄을 반복 안으로 들여쓰면 가로 4칸 세로 3칸에서 몇 줄이 나올까요? 모양은 어떻게 될까요?
4단계 · 넣어 보고 확인하기
줄 수를 세어 보면 대부분의 실수가 잡힙니다.
모양이 나오는 프로그램은 눈으로 보면 맞아 보이기 쉽습니다. 줄 수와 글자 수를 세어 확인하는 편이 안전합니다.
| 넣은 값 | 나와야 할 줄 수 | 무엇을 보려는 값인가 |
|---|---|---|
| 4 3 | 7줄 | 경계선 4 + 칸 줄 3 — 기본 예시 |
| 1 1 | 3줄 | 가장 작은 격자 — 네모 하나 |
| 5 1 | 3줄 | 가로로만 긴 경우 |
| 1 5 | 11줄 | 세로로만 긴 경우 |
| 10 2 | 5줄, 한 줄에 41글자 | 글자 수까지 세어 보는 경우 |
결과가 어긋났다면 여기부터 봅니다
- 맨 아래 선이 없다 — 반복 밖의 마지막 경계선이 빠졌습니다
- 경계선이 두 줄씩 붙어 나온다 — 마지막 경계선이 반복 안에 들어갔습니다
- 오른쪽 끝이 열려 있다 — 줄 끝의 마감 기호를 안 붙였습니다
- 위아래 선이 어긋난다 — 칸 안쪽 공백이 세 칸이 아닙니다
- 경계선 한 줄만 나온다 — 세로 칸 수가 0으로 들어갔거나 반복 범위가 틀렸습니다
가로 10칸일 때 한 줄이 41글자인 이유를 설명해 보세요. 조각 하나가 몇 글자이고 마감이 몇 글자인가요?
더 해 보기
모양을 바꾸려면 무엇을 고쳐야 할까요?
칸 크기를 입력받는다
칸의 가로 폭을 3으로 고정한 것을 풀어 봅니다. 폭이 바뀌면 가로선과 칸 안쪽 공백이 함께 바뀌어야 합니다. 둘 중 하나만 고치면 격자가 어긋납니다.
칸에 번호를 넣는다
칸 안쪽을 비우는 대신 1부터 차례로 번호를 넣어 봅니다. 칸 줄을 곱하기 하나로 만들 수 없게 되므로 반복이 하나 더 필요해집니다.
0칸을 막는다
요구 사항 6번을 풀어 0이나 음수가 들어오면 알리도록 합니다. 이 프로그램은 0을 넣어도 멈추지 않습니다. 그래서 더 조심해야 합니다.
맨 위와 맨 아래 선만 다르게
맨 위와 맨 아래 경계선만 다른 기호로 그려 봅니다. 맨 아래 선은 이미 반복 밖에서 따로 찍고 있지만, 맨 위 선은 반복 안에서 찍히므로 첫 회차를 따로 구분해야 합니다.
「0을 넣어도 멈추지 않는다」고 했습니다. 가로 0칸 세로 0칸을 넣으면 무엇이 나올까요? 그리고 그것이 왜 위험할까요?