챕터 3: 제어 구조
“프로그램의 흐름을 제어하는 것은 코딩의 핵심이다” - 조건문과 반복문으로 더욱 지능적이고 효율적인 프로그램을 만들어봅시다.
학습 목표
- 조건문을 활용하여 프로그램의 분기를 제어할 수 있다
- 반복문을 사용하여 효율적인 코드를 작성할 수 있다
- 중첩 구조와 복합 조건을 이해할 수 있다
- break, continue, else 등의 제어문을 적절히 활용할 수 있다
핵심 개념(이론)
1) 제어 구조의 목적은 “분기”가 아니라 “의도 표현”이다
조건문/반복문은 실행 흐름을 바꾸기 위한 도구지만, 실무에서는 의도를 읽기 쉽게 표현하는 것이 더 중요합니다.
복잡한 분기는 코드가 아니라 요구사항이 복잡하다는 신호일 수 있습니다.
2) 반복문의 핵심: “상태 변화”를 최소화하라
버그의 많은 부분은 반복문 내부의 상태가 여러 군데서 바뀌며 생깁니다.
가능하면 상태 변화를 한 곳으로 모으고, for/내장 함수로 의도를 드러내는 편이 안전합니다.
3) break/continue/else는 ‘제어 흐름 계약’이다
break는 “중단 조건을 찾으면 즉시 종료”라는 계약을 만들고, else는 “끝까지 break 없이 돌았다”는 사실을 표현합니다.
이 의미를 모르면 for-else가 오히려 혼란을 줍니다.
4) 중첩은 비용이다: 복잡도는 ‘줄 수’가 아니라 ‘경로 수’다
if/for 중첩이 늘어날수록 가능한 실행 경로가 폭발하고 테스트가 어려워집니다.
중첩이 깊다면 함수 분리, 조기 반환(guard), 데이터 구조 변경을 먼저 고려하세요.
선택 기준(Decision Guide)
- 반복은
while보다 for가 기본(종료 조건을 명확히). - 분기가 많아지면 “조건을 데이터로” 바꾸는 전략(딕셔너리 매핑 등)을 고려.
흔한 오해/주의점
else는 “if의 else”만 있는 게 아니라, 반복문에도 붙을 수 있습니다.- 무한 루프는 나쁜 것이 아니라, 종료 조건/timeout이 없을 때 위험합니다.
요약
- 제어 구조는 의도를 표현하는 도구이며, 중첩은 복잡도를 폭발시킨다.
break/continue/else의 의미를 계약으로 이해하고 사용한다.
조건문 (Conditional Statements)
if 문 기본 구조
flowchart TD
startNode["시작"] --> cond{"조건 검사"}
cond -->|"True"| thenBlock["실행 블록"]
cond -->|"False"| skipBlock["건너뛰기"]
thenBlock --> nextCode["다음 코드"]
skipBlock --> nextCode
기본 if 문:
1
2
3
4
5
6
7
8
9
10
11
12
| # 기본 if 문
age = 18
if age >= 18:
print("성인입니다.")
print("투표할 수 있습니다.")
# 조건이 거짓일 때는 아무것도 실행되지 않음
score = 70
if score >= 90:
print("A 등급") # 실행되지 않음
print("프로그램 계속 진행")
|
if-else 문:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 두 가지 경우 처리
temperature = 25
if temperature > 30:
print("더워요! 에어컨을 켜세요.")
else:
print("시원해요! 창문을 여세요.")
# 숫자의 홀짝 판별
number = 7
if number % 2 == 0:
print(f"{number}는 짝수입니다.")
else:
print(f"{number}는 홀수입니다.")
|
if-elif-else 체인
flowchart TD
startNode["시작"] --> cond1{"첫 번째 조건"}
cond1 -->|"True"| block1["블록 1 실행"]
cond1 -->|"False"| cond2{"두 번째 조건"}
cond2 -->|"True"| block2["블록 2 실행"]
cond2 -->|"False"| cond3{"세 번째 조건"}
cond3 -->|"True"| block3["블록 3 실행"]
cond3 -->|"False"| elseBlock["else 블록 실행"]
block1 --> nextCode["다음 코드"]
block2 --> nextCode
block3 --> nextCode
elseBlock --> nextCode
학점 계산 예제:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| score = 87
if score >= 90:
grade = "A"
print("우수한 성적입니다!")
elif score >= 80:
grade = "B"
print("좋은 성적입니다!")
elif score >= 70:
grade = "C"
print("보통 성적입니다.")
elif score >= 60:
grade = "D"
print("조금 더 노력하세요.")
else:
grade = "F"
print("재수강이 필요합니다.")
print(f"당신의 학점은 {grade}입니다.")
|
복합 조건 처리:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # 여러 조건을 조합
age = 25
has_license = True
experience_years = 3
if age >= 18 and has_license:
if experience_years >= 2:
print("렌터카 이용이 가능합니다.")
else:
print("경력이 부족합니다. 보험료가 추가됩니다.")
elif age >= 18:
print("운전면허를 먼저 취득하세요.")
else:
print("성인이 되면 다시 신청하세요.")
# 범위 검사
temperature = 25
humidity = 60
if 20 <= temperature <= 26 and 40 <= humidity <= 60:
print("쾌적한 환경입니다.")
elif temperature < 20:
print("춥습니다. 난방을 켜세요.")
elif temperature > 26:
print("덥습니다. 냉방을 켜세요.")
elif humidity < 40:
print("건조합니다. 가습기를 켜세요.")
elif humidity > 60:
print("습합니다. 제습기를 켜세요.")
|
조건부 표현식 (삼항 연산자)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # 기본 문법: 값1 if 조건 else 값2
age = 20
status = "성인" if age >= 18 else "미성년자"
print(f"나이 {age}세는 {status}입니다.")
# 함수 호출에서 활용
def get_discount_rate(is_member, age):
return 0.2 if is_member else (0.1 if age >= 65 else 0.05)
discount = get_discount_rate(True, 30)
print(f"할인율: {discount * 100}%")
# 리스트 컴프리헨션과 함께
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_odd = ["짝수" if n % 2 == 0 else "홀수" for n in numbers]
print(even_odd)
# 중첩된 조건부 표현식 (권장하지 않음)
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))
print(f"점수 {score}: {grade}등급")
|
반복문 (Loops)
for 문
flowchart TD
startNode["시작"] --> prep["시퀀스 준비"]
prep --> hasNext{"다음 항목 있음?"}
hasNext -->|"Yes"| assign["항목을 변수에 할당"]
assign --> loopBlock["반복 블록 실행"]
loopBlock --> hasNext
hasNext -->|"No"| endLoop["반복 종료"]
endLoop --> nextCode["다음 코드"]
기본 for 문:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # 리스트 순회
fruits = ["사과", "바나나", "체리", "포도"]
for fruit in fruits:
print(f"과일: {fruit}")
# 문자열 순회
word = "Python"
for char in word:
print(f"글자: {char}")
# range() 함수 활용
print("1부터 5까지:")
for i in range(1, 6):
print(f"숫자: {i}")
print("0부터 9까지 (짝수만):")
for i in range(0, 10, 2):
print(f"짝수: {i}")
print("10부터 1까지 (역순):")
for i in range(10, 0, -1):
print(f"카운트다운: {i}")
|
for 문 고급 활용:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # enumerate() - 인덱스와 값 동시 접근
students = ["Alice", "Bob", "Charlie", "Diana"]
for index, name in enumerate(students):
print(f"{index + 1}번째 학생: {name}")
# enumerate() 시작 값 지정
for rank, name in enumerate(students, start=1):
print(f"{rank}등: {name}")
# zip() - 여러 시퀀스 병렬 처리
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
ages = [20, 22, 21]
for name, score, age in zip(names, scores, ages):
print(f"{name} ({age}세): {score}점")
# 딕셔너리 순회
student_info = {"Alice": 85, "Bob": 92, "Charlie": 78}
# 키만 순회
for name in student_info:
print(f"학생: {name}")
# 값만 순회
for score in student_info.values():
print(f"점수: {score}")
# 키와 값 동시 순회
for name, score in student_info.items():
print(f"{name}: {score}점")
|
중첩 for 문:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| # 구구단 출력
print("=== 구구단 ===")
for i in range(2, 10):
print(f"\n{i}단:")
for j in range(1, 10):
result = i * j
print(f"{i} × {j} = {result}")
# 2차원 리스트 처리
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print("행렬 출력:")
for row in matrix:
for element in row:
print(f"{element:3d}", end=" ")
print() # 줄바꿈
# 좌표계 순회
print("\n좌표계:")
for x in range(3):
for y in range(3):
print(f"({x}, {y})", end=" ")
print()
|
while 문
flowchart TD
startNode["시작"] --> condCheck["조건 검사"]
condCheck -->|"True"| loopBlock["반복 블록 실행"]
loopBlock --> recheck["조건 재검사"]
recheck -->|"True"| loopBlock
recheck -->|"False"| endLoop["반복 종료"]
condCheck -->|"False"| endLoop
endLoop --> nextCode["다음 코드"]
기본 while 문:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 카운터 기반 반복
count = 1
while count <= 5:
print(f"카운트: {count}")
count += 1 # 조건 변경 필수!
print("반복 완료")
# 사용자 입력 기반 반복
password = ""
while password != "1234":
password = input("비밀번호를 입력하세요: ")
if password != "1234":
print("틀렸습니다. 다시 시도하세요.")
print("로그인 성공!")
# 조건 기반 계산
number = 100
while number > 1:
print(f"현재 수: {number}")
number //= 2 # 2로 나누기
print(f"최종 결과: {number}")
|
while 문 실제 활용:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
| # 숫자 맞추기 게임
import random
target = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("1부터 100 사이의 숫자를 맞춰보세요!")
print(f"기회는 {max_attempts}번입니다.")
while attempts < max_attempts:
try:
guess = int(input(f"\n{attempts + 1}번째 시도: "))
attempts += 1
if guess == target:
print(f"🎉 정답! {attempts}번 만에 맞췄습니다!")
break
elif guess < target:
print("더 큰 수입니다.")
else:
print("더 작은 수입니다.")
remaining = max_attempts - attempts
if remaining > 0:
print(f"남은 기회: {remaining}번")
except ValueError:
print("올바른 숫자를 입력하세요.")
attempts -= 1 # 잘못된 입력은 기회 차감 안함
if attempts >= max_attempts and guess != target:
print(f"💥 실패! 정답은 {target}이었습니다.")
# 메뉴 시스템
def show_menu():
print("\n=== 계산기 메뉴 ===")
print("1. 더하기")
print("2. 빼기")
print("3. 곱하기")
print("4. 나누기")
print("0. 종료")
running = True
while running:
show_menu()
choice = input("\n선택하세요: ").strip()
if choice == "0":
print("프로그램을 종료합니다.")
running = False
elif choice in ["1", "2", "3", "4"]:
try:
a = float(input("첫 번째 수: "))
b = float(input("두 번째 수: "))
if choice == "1":
result = a + b
print(f"결과: {a} + {b} = {result}")
elif choice == "2":
result = a - b
print(f"결과: {a} - {b} = {result}")
elif choice == "3":
result = a * b
print(f"결과: {a} × {b} = {result}")
elif choice == "4":
if b != 0:
result = a / b
print(f"결과: {a} ÷ {b} = {result}")
else:
print("0으로 나눌 수 없습니다.")
except ValueError:
print("올바른 숫자를 입력하세요.")
else:
print("올바른 메뉴를 선택하세요.")
|
제어 키워드
break와 continue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| # break - 반복문 완전 탈출
print("=== break 예제 ===")
for i in range(1, 11):
if i == 6:
print("6에서 중단!")
break
print(f"숫자: {i}")
print("반복문 종료\n")
# continue - 현재 반복 건너뛰기
print("=== continue 예제 ===")
for i in range(1, 11):
if i % 2 == 0: # 짝수 건너뛰기
continue
print(f"홀수: {i}")
print("반복문 종료\n")
# while문에서 break와 continue
print("=== while문 break/continue ===")
count = 0
while count < 10:
count += 1
if count == 5:
print("5는 건너뜁니다")
continue
if count == 8:
print("8에서 중단합니다")
break
print(f"카운트: {count}")
|
else 절과 함께 사용하는 break
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| # for문의 else: break 없이 정상 완료 시 실행
print("=== for-else 구문 ===")
# 정상 완료 예제
for i in range(5):
print(f"숫자: {i}")
else:
print("반복문이 정상적으로 완료되었습니다.")
print()
# break로 중단된 경우
search_number = 7
numbers = [1, 3, 5, 7, 9]
for num in numbers:
print(f"확인 중: {num}")
if num == search_number:
print(f"찾았습니다: {search_number}")
break
else:
print(f"{search_number}를 찾지 못했습니다.")
# while문의 else
print("\n=== while-else 구문 ===")
password_attempts = 0
max_attempts = 3
while password_attempts < max_attempts:
password = input(f"비밀번호 입력 ({password_attempts + 1}/{max_attempts}): ")
password_attempts += 1
if password == "1234":
print("로그인 성공!")
break
else:
print("로그인 실패: 최대 시도 횟수를 초과했습니다.")
|
pass 문
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # pass - 아무것도 하지 않는 구문 (자리표시자)
def todo_function():
pass # 나중에 구현 예정
class FutureClass:
pass # 나중에 구현 예정
# 조건문에서 pass
score = 85
if score >= 90:
print("A등급")
elif score >= 80:
pass # B등급 처리는 나중에 구현
else:
print("C등급 이하")
# 예외 처리에서 pass
try:
risky_operation = 1 / 0
except ZeroDivisionError:
pass # 에러를 무시하고 계속 진행
|
고급 제어 구조
enumerate()로 인덱스와 값 함께 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 기본 enumerate 사용
fruits = ["apple", "banana", "cherry", "date"]
print("=== enumerate 기본 사용 ===")
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 시작 번호 지정
print("\n=== enumerate 시작 번호 지정 ===")
for rank, fruit in enumerate(fruits, start=1):
print(f"{rank}등: {fruit}")
# 조건부 처리와 함께
print("\n=== 조건부 enumerate ===")
scores = [85, 92, 78, 96, 88]
for i, score in enumerate(scores):
grade = "A" if score >= 90 else "B" if score >= 80 else "C"
print(f"학생 {i+1}: {score}점 ({grade}등급)")
|
zip()으로 여러 시퀀스 병렬 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # 기본 zip 사용
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["Seoul", "Busan", "Incheon"]
print("=== zip 기본 사용 ===")
for name, age, city in zip(names, ages, cities):
print(f"{name} ({age}세) - {city}")
# 길이가 다른 시퀀스
print("\n=== 길이가 다른 시퀀스 ===")
numbers1 = [1, 2, 3, 4, 5]
numbers2 = [10, 20, 30] # 더 짧음
for n1, n2 in zip(numbers1, numbers2):
print(f"{n1} + {n2} = {n1 + n2}")
# 짧은 시퀀스에 맞춰 3번만 실행됨
# zip을 이용한 사전 생성
keys = ["name", "age", "city"]
values = ["Diana", 28, "Daegu"]
person_dict = dict(zip(keys, values))
print(f"\n생성된 사전: {person_dict}")
# zip을 이용한 리스트 전치 (transpose)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = list(zip(*matrix))
print(f"\n원본 행렬: {matrix}")
print(f"전치 행렬: {transposed}")
|
reversed()와 sorted()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| # reversed() - 역순 순회
numbers = [1, 2, 3, 4, 5]
print("=== reversed() 사용 ===")
for num in reversed(numbers):
print(f"역순: {num}")
# 문자열 역순
text = "Python"
for char in reversed(text):
print(char, end="")
print() # 줄바꿈
# sorted() - 정렬된 순회 (원본 변경 없음)
print("\n=== sorted() 사용 ===")
scores = [85, 92, 78, 96, 88]
print("오름차순:")
for score in sorted(scores):
print(score, end=" ")
print()
print("내림차순:")
for score in sorted(scores, reverse=True):
print(score, end=" ")
print()
print(f"원본 리스트: {scores}") # 변경되지 않음
# 복잡한 정렬
students = [
("Alice", 85),
("Bob", 92),
("Charlie", 78),
("Diana", 96)
]
print("\n점수순 정렬 (높은 점수부터):")
for name, score in sorted(students, key=lambda x: x[1], reverse=True):
print(f"{name}: {score}")
|
조건부 반복: any()와 all()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # any()와 all() 활용
numbers = [2, 4, 6, 8, 10]
# 모든 수가 짝수인지 확인
if all(num % 2 == 0 for num in numbers):
print("모든 수가 짝수입니다.")
# 하나라도 10보다 큰 수가 있는지 확인
if any(num > 10 for num in numbers):
print("10보다 큰 수가 있습니다.")
# 조건을 만족하는 첫 번째 항목 찾기
names = ["Alice", "Bob", "Charlie", "Anna"]
for name in names:
if name.startswith("A"):
print(f"A로 시작하는 첫 번째 이름: {name}")
break
else:
print("A로 시작하는 이름을 찾지 못했습니다.")
# 조건을 만족하는 모든 항목 찾기
print("\nA로 시작하는 모든 이름:")
a_names = [name for name in names if name.startswith("A")]
for name in a_names:
print(f"- {name}")
|
반복문 최적화: 컴프리헨션과 제너레이터 표현식
명시적인 for 반복으로 리스트를 채우는 코드는 의도(무엇을 만드는가)보다 절차(어떻게 채우는가)를 먼저 드러낸다. 컴프리헨션은 결과의 형태를 먼저 보여주므로 짧은 변환/필터링 로직에서는 가독성과 속도 모두에서 유리하지만, 로직이 복잡해지면 오히려 일반 반복문이 더 읽기 쉽다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # 리스트 컴프리헨션 (더 빠르고 간결)
# 기존 방식
squares = []
for i in range(10):
squares.append(i ** 2)
print("제곱수 (기존):", squares)
# 리스트 컴프리헨션
squares = [i ** 2 for i in range(10)]
print("제곱수 (컴프리헨션):", squares)
# 조건부 컴프리헨션
even_squares = [i ** 2 for i in range(10) if i % 2 == 0]
print("짝수의 제곱:", even_squares)
# 딕셔너리 컴프리헨션
square_dict = {i: i ** 2 for i in range(5)}
print("제곱 딕셔너리:", square_dict)
# 집합 컴프리헨션
unique_lengths = {len(word) for word in ["hello", "world", "python", "code"]}
print("고유 길이들:", unique_lengths)
# 제너레이터 표현식 (메모리 절약, 값을 한 번에 만들지 않고 필요할 때 하나씩 계산)
sum_squares = sum(i ** 2 for i in range(1000000))
print(f"백만개 수의 제곱합: {sum_squares}")
|
컴프리헨션과 제너레이터 표현식은 5장(자료구조)에서 성능 특성까지 더 깊이 다룬다. 여기서는 반복문을 대체할 수 있는 선택지로 감을 잡는 정도면 충분하다.
중첩 반복문과 실전 예제
구구단 마스터
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| def multiplication_table():
"""구구단 출력 및 문제 생성"""
print("=== 구구단 마스터 ===")
print("1. 전체 구구단 보기")
print("2. 특정 단 보기")
print("3. 구구단 문제 풀기")
choice = input("선택하세요 (1-3): ")
if choice == "1":
# 전체 구구단
for i in range(2, 10):
print(f"\n=== {i}단 ===")
for j in range(1, 10):
print(f"{i} × {j} = {i * j:2d}")
elif choice == "2":
# 특정 단
try:
dan = int(input("몇 단을 보시겠습니까? (2-9): "))
if 2 <= dan <= 9:
print(f"\n=== {dan}단 ===")
for j in range(1, 10):
print(f"{dan} × {j} = {dan * j}")
else:
print("2-9 사이의 숫자를 입력하세요.")
except ValueError:
print("올바른 숫자를 입력하세요.")
elif choice == "3":
# 구구단 문제 풀기
import random
correct = 0
total = 5
print(f"\n구구단 문제 {total}개를 풀어보세요!")
for i in range(total):
a = random.randint(2, 9)
b = random.randint(1, 9)
answer = a * b
try:
user_answer = int(input(f"\n문제 {i+1}: {a} × {b} = "))
if user_answer == answer:
print("✅ 정답!")
correct += 1
else:
print(f"❌ 틀렸습니다. 정답은 {answer}입니다.")
except ValueError:
print(f"❌ 숫자를 입력하세요. 정답은 {answer}입니다.")
print(f"\n결과: {correct}/{total} 정답 ({correct/total*100:.1f}%)")
if correct == total:
print("🎉 모든 문제를 맞췄습니다!")
elif correct >= total * 0.8:
print("👍 잘했습니다!")
else:
print("💪 더 연습해보세요!")
# 실행
multiplication_table()
|
숫자 맞추기 게임
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
| def number_guessing_game():
"""숫자 맞추기 게임"""
import random
print("=== 숫자 맞추기 게임 ===")
print("1부터 100 사이의 숫자를 맞춰보세요!")
# 난이도 선택
print("\n난이도를 선택하세요:")
print("1. 쉬움 (10번 기회)")
print("2. 보통 (7번 기회)")
print("3. 어려움 (5번 기회)")
difficulty = input("선택 (1-3): ")
if difficulty == "1":
max_attempts = 10
level = "쉬움"
elif difficulty == "2":
max_attempts = 7
level = "보통"
elif difficulty == "3":
max_attempts = 5
level = "어려움"
else:
max_attempts = 7
level = "보통"
print("기본 난이도(보통)로 설정합니다.")
target = random.randint(1, 100)
attempts = 0
guessed_numbers = []
print(f"\n난이도: {level} (최대 {max_attempts}번 시도)")
print("게임 시작!")
while attempts < max_attempts:
try:
guess = int(input(f"\n시도 {attempts + 1}/{max_attempts}: "))
if guess < 1 or guess > 100:
print("1부터 100 사이의 숫자를 입력하세요.")
continue
if guess in guessed_numbers:
print("이미 시도한 숫자입니다.")
continue
attempts += 1
guessed_numbers.append(guess)
if guess == target:
print(f"🎉 정답! {attempts}번 만에 맞췄습니다!")
# 성과 평가
if attempts <= max_attempts // 3:
print("🏆 대단합니다! 매우 빠르게 맞췄네요!")
elif attempts <= max_attempts // 2:
print("👍 좋습니다! 빠르게 맞췄네요!")
else:
print("😊 축하합니다!")
break
elif guess < target:
print("⬆️ 더 큰 수입니다.")
# 힌트 제공
if target - guess >= 30:
print("💡 힌트: 많이 작습니다!")
elif target - guess >= 10:
print("💡 힌트: 좀 더 큰 수입니다.")
else: # guess > target
print("⬇️ 더 작은 수입니다.")
# 힌트 제공
if guess - target >= 30:
print("💡 힌트: 많이 큽니다!")
elif guess - target >= 10:
print("💡 힌트: 좀 더 작은 수입니다.")
# 시도한 숫자들 표시
guessed_numbers.sort()
print(f"시도한 숫자들: {guessed_numbers}")
remaining = max_attempts - attempts
if remaining > 0:
print(f"남은 기회: {remaining}번")
except ValueError:
print("올바른 숫자를 입력하세요.")
# 게임 종료
if attempts >= max_attempts and guess != target:
print(f"\n💥 실패! 정답은 {target}이었습니다.")
print("다시 도전해보세요!")
# 재시작 여부
play_again = input("\n다시 플레이하시겠습니까? (y/n): ").lower()
if play_again == 'y':
number_guessing_game()
else:
print("게임을 종료합니다. 즐거우셨나요? 😊")
# 게임 실행
number_guessing_game()
|
학점 관리 시스템
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
| def grade_management_system():
"""학점 관리 시스템"""
students = {}
while True:
print("\n=== 학점 관리 시스템 ===")
print("1. 학생 추가")
print("2. 점수 입력")
print("3. 성적 조회")
print("4. 전체 통계")
print("5. 학점 분포")
print("0. 종료")
choice = input("\n선택하세요: ").strip()
if choice == "0":
print("프로그램을 종료합니다.")
break
elif choice == "1":
# 학생 추가
name = input("학생 이름: ").strip()
if name:
if name not in students:
students[name] = {}
print(f"✅ {name} 학생이 추가되었습니다.")
else:
print(f"⚠️ {name} 학생은 이미 등록되어 있습니다.")
else:
print("올바른 이름을 입력하세요.")
elif choice == "2":
# 점수 입력
if not students:
print("먼저 학생을 추가하세요.")
continue
print(f"등록된 학생: {list(students.keys())}")
name = input("학생 이름: ").strip()
if name not in students:
print("등록되지 않은 학생입니다.")
continue
subject = input("과목명: ").strip()
if not subject:
print("과목명을 입력하세요.")
continue
try:
score = float(input("점수 (0-100): "))
if 0 <= score <= 100:
students[name][subject] = score
print(f"✅ {name} 학생의 {subject} 점수 {score}점이 등록되었습니다.")
else:
print("점수는 0-100 사이여야 합니다.")
except ValueError:
print("올바른 점수를 입력하세요.")
elif choice == "3":
# 성적 조회
if not students:
print("등록된 학생이 없습니다.")
continue
print(f"등록된 학생: {list(students.keys())}")
name = input("학생 이름 (전체 보기: all): ").strip()
if name.lower() == "all":
# 전체 학생 성적
for student_name, scores in students.items():
print(f"\n📋 {student_name} 학생:")
if scores:
total = sum(scores.values())
average = total / len(scores)
print(f"과목별 점수:")
for subject, score in scores.items():
grade = get_letter_grade(score)
print(f" - {subject}: {score}점 ({grade})")
print(f"평균: {average:.1f}점 ({get_letter_grade(average)})")
else:
print(" 등록된 점수가 없습니다.")
elif name in students:
# 특정 학생 성적
scores = students[name]
print(f"\n📋 {name} 학생 성적:")
if scores:
total = sum(scores.values())
average = total / len(scores)
print(f"과목별 점수:")
for subject, score in scores.items():
grade = get_letter_grade(score)
print(f" - {subject}: {score}점 ({grade})")
print(f"총 {len(scores)}과목")
print(f"총점: {total}점")
print(f"평균: {average:.1f}점 ({get_letter_grade(average)})")
# 과목별 순위 (만약 여러 학생이 같은 과목을 들었다면)
print(f"\n📊 과목별 상대 순위:")
for subject, score in scores.items():
rank = calculate_rank(students, subject, score)
print(f" - {subject}: {len(rank)}명 중 {rank.index(score) + 1}등")
else:
print("등록된 점수가 없습니다.")
else:
print("등록되지 않은 학생입니다.")
elif choice == "4":
# 전체 통계
if not students:
print("등록된 학생이 없습니다.")
continue
all_scores = []
subject_scores = {}
for name, scores in students.items():
for subject, score in scores.items():
all_scores.append(score)
if subject not in subject_scores:
subject_scores[subject] = []
subject_scores[subject].append(score)
if all_scores:
print(f"\n📊 전체 통계:")
print(f"총 학생 수: {len(students)}명")
print(f"총 점수 기록: {len(all_scores)}개")
print(f"전체 평균: {sum(all_scores)/len(all_scores):.1f}점")
print(f"최고 점수: {max(all_scores)}점")
print(f"최저 점수: {min(all_scores)}점")
print(f"\n📚 과목별 통계:")
for subject, scores in subject_scores.items():
avg = sum(scores) / len(scores)
print(f" - {subject}: 평균 {avg:.1f}점 ({len(scores)}명)")
else:
print("등록된 점수가 없습니다.")
elif choice == "5":
# 학점 분포
if not students:
print("등록된 학생이 없습니다.")
continue
grade_count = {"A": 0, "B": 0, "C": 0, "D": 0, "F": 0}
total_scores = 0
for name, scores in students.items():
if scores:
average = sum(scores.values()) / len(scores)
grade = get_letter_grade(average)
grade_count[grade] += 1
total_scores += 1
if total_scores > 0:
print(f"\n📈 학점 분포 ({total_scores}명):")
for grade in ["A", "B", "C", "D", "F"]:
count = grade_count[grade]
percentage = count / total_scores * 100
bar = "█" * int(percentage / 5) # 5%당 하나의 블록
print(f" {grade}: {count:2d}명 ({percentage:4.1f}%) {bar}")
else:
print("성적 데이터가 없습니다.")
else:
print("올바른 메뉴를 선택하세요.")
def get_letter_grade(score):
"""점수를 학점으로 변환"""
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"
def calculate_rank(students, subject, target_score):
"""특정 과목에서의 점수 순위 계산"""
scores = []
for name, student_scores in students.items():
if subject in student_scores:
scores.append(student_scores[subject])
scores.sort(reverse=True)
return scores
# 시스템 실행
grade_management_system()
|
체크리스트
조건문
반복문
제어 키워드
고급 기능
다음 단계
🎉 축하합니다! 파이썬 제어 구조를 마스터했습니다.
이제 04. 함수로 넘어가서 코드의 재사용성을 높이는 함수 정의와 활용을 학습해봅시다.
💡 팁:
- 조건문은 간단하고 읽기 쉽게 작성하세요
- 반복문에서는 항상 종료 조건을 명확히 하세요
- break와 continue는 적절히 사용하여 코드를 간결하게 만드세요
- 복잡한 로직은 함수로 분리하여 가독성을 높이세요