- 프롤로그
- 개발 첫걸음
- 파이썬 기초
- 파이썬 중급
- 파이썬 고급
- 내장 함수 톺아보기
- 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
- 변수의 범위 – 이름 검색의 범위
- 파이썬 심화
- 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
- 데코레이터 – 함수의 기능을 강화하기
- 프로퍼티
- 제너레이터
- async와 await
- 객체로서의 클래스 – 클래스를 동적으로 정의하기
- 파이썬 프로젝트 실습
- 원카드 게임 만들기 (1)
- 원카드 게임 만들기 (2)
- 원카드 게임 만들기 (3) (작성중)
- 턴제 자동 전투 게임 만들기 (작성중)
- 실전 (파이썬 외적인 것들)
- 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
- 유니코드 – 컴퓨터에서 문자를 표기하는 방법
- html, css, 인터넷 – 자동화 첫 걸음 내딛기
- 네트워크 – 인터넷으로 통신하는 방법
- 문서 – 문맥을 읽어보기
때릴 수록 강력해지는 공격력
계속해서 새로운 개념을 배워나가고 있습니다. 이번 시간에는 반복문을 알아볼 겁니다. 역시나 예제로 시작합시다. 반복문의 필요성을 깨우쳐야 배울 힘이 나겠지요.
- 슈퍼파워 게임회사는 플레이어가 훈련할 수 있는 샌드백을 만들고 있습니다.
- 플레이어의 처음 공격력은 1밖에 되지 않지만 샌드백을 한 번 때릴 때마다 공격력이 1씩 증가합니다.
- 샌드백은 공격받을 때마다 때린 사람의 공격력만큼 내구도가 낮아집니다.
- 샌드백이 내구도가 0이 되면 샌드백은 부서집니다. (부서질 때에도 공격력은 성장합니다)
- 샌드백의 내구도를 임의로 설정해보고 나서, 플레이어가 최종적으로 공격력이 몇인지 궁금합니다.
좋습니다. 샌드백의 내구도를 durability
, 플레이어의 공격력을 attack
이라 명명하고 코드를 짜 봅시다.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
durability -= attack
attack += 1
if durability <= 0:
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
else:
durability -= attack
attack += 1
if durability <= 0:
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
else:
durability -= attack
attack += 1
if durability <= 0:
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
else:
durability -= attack
attack += 1
if durability <= 0:
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
else:
durability -= attack
attack += 1
if durability <= 0:
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
----- 1번째 실행 -----
샌드백의 내구도를 입력하세요 >> 13
샌드백이 부서졌습니다! 최종 힘은 6입니다.
----- 2번째 실행 -----
샌드백의 내구도를 입력하세요 >> 17
위 코드는 조건문을 이용하여 계속해서 durability
를 attack
만큼 차감시키고 attack
을 1
씩 증가시키고 있습니다. durability
은 최대 5번 차감될 수 있습니다. 왜냐하면 durability -= attack
부분이 5번 밖에 등장하지 않으니까요. 그래서 플레이어 또한 5번 밖에 성장하지 못합니다. 내구도가 13
이라면 5회의 성장 안에 샌드백을 부술 수 있지만 내구도가 17
이라면 성장 횟수가 부족하여 샌드백을 부수지 못합니다. (샌드백이 부숴졌다는 메세지가 뜨지 않습니다.)
오, 선생님!
durability
의 피해 값은 딱봐도 등차수열의 합이라서durability = attack * (attack + 1) / 2
의 식을 풀어, 이차방정식을 만들어 양의 해를 구하기만 하면 끝날 문제 아닌가요?어… 네 그렇게 생각 할 수도 있겠지만 매번 공식을 이용해 문제를 해결한다면, 상황이 바뀌었을 때 해당 공식을 매번 수정해야 하는 불편함이 있습니다. 지금은 직접 코드로 시뮬레이션한다고 생각하시면 좋을 듯 합니다.
여하튼 계속해서 반복하기에는 무리가 있습니다. 복사 붙여넣기는 만능이 아니지요. 만약 10000
과 같은, 아주 큰 내구도를 집어넣는다면 도대체 얼마나 많이 복붙해야 할지 가늠도 오지 않습니다.
이러한 상황속에서 반복문은 빛나는 동아줄이 되어 우리를 구원해줄 수 있습니다.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
while durability > 0: ##a_1##
durability -= attack
attack += 1
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
----- 1번째 실행 -----
샌드백의 내구도를 입력하세요 >> 28
샌드백이 부서졌습니다! 최종 공격력은 8입니다.
----- 2번째 실행 -----
샌드백의 내구도를 입력하세요 >> 28371
샌드백이 부서졌습니다! 최종 공격력은 239입니다.
이게 무슨 일이죠? 코드의 양이 완전히 줄어들었습니다. 더군다나 28
은 물론이고 28371
같은 아주 높은 숫자도 문제 없이 실행한다는 사실을 확인할 수 있습니다. 이만 팔천의 샌드백을 죽어라 때리고 때려서 공격력이 239
까지 성장했다니! 그 사실을 바로 알 수 있다니. 정말 놀라울 따름입니다.
a_1(1.) 코드 설명
while durability > 0:
이 행이 이번 시간의 핵심입니다. while
이라는 새로운 키워드가 등장하였고, 그 바로 뒤에는 비교 연산자가 들어간 식이 들어갑니다. 행의 끝에 콜론(:
)을 통해 새로운 블록을 시작한다고 말하는 것까지, 어찌 조건문과 굉장히 비슷하게 생겼습니다.
while
의 동작 원리를 알려드리겠습니다. 뒤따르는 조건이 True
라면, 뒤따르는 블록을 실행합니다. 다시 돌아와 조건을 체크합니다. True
라면 블록을 실행합니다. 다시 조건 체크 후 블록을 실행합니다. 계속, 무한 반복합니다. 조건이 False
가 되어야 블록을 건너뛰고 다음으로 넘어갑니다.
이 while
의 조건은 durability > 0
입니다. durability
변수이고 계속 우리가 차감시켜주고 있기 때문에 값이 계속해서 변합니다.
다음 코드는 바로 위 코드와 같지만, while
내부에 print
함수 하나를 추가하여 루프가 돌고 있는 시점에서 값이 어떻게 변화하는지 실시간으로 확인할 수 있도록 했습니다. 코드를 실행하여 결과를 확인해보세요.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
while durability > 0:
print("현재 공격력은 " + str(attack) + " 이며, 샌드백의 내구도는 " + str(durability) + " 입니다." )
durability -= attack
attack += 1
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
입력을 28371
로 해보겠습니다.
(중략)
현재 공격력은 226 이며, 샌드백의 내구도는 2946 입니다.
현재 공격력은 227 이며, 샌드백의 내구도는 2720 입니다.
현재 공격력은 228 이며, 샌드백의 내구도는 2493 입니다.
현재 공격력은 229 이며, 샌드백의 내구도는 2265 입니다.
현재 공격력은 230 이며, 샌드백의 내구도는 2036 입니다.
현재 공격력은 231 이며, 샌드백의 내구도는 1806 입니다.
현재 공격력은 232 이며, 샌드백의 내구도는 1575 입니다.
현재 공격력은 233 이며, 샌드백의 내구도는 1343 입니다.
현재 공격력은 234 이며, 샌드백의 내구도는 1110 입니다.
현재 공격력은 235 이며, 샌드백의 내구도는 876 입니다.
현재 공격력은 236 이며, 샌드백의 내구도는 641 입니다.
현재 공격력은 237 이며, 샌드백의 내구도는 405 입니다.
현재 공격력은 238 이며, 샌드백의 내구도는 168 입니다.
샌드백이 부서졌습니다! 최종 공격력은 239입니다.
컴퓨터가 공식을 이용하거나 편법을 쓰지 않았다는 사실을 우리는 알 수 있습니다. 정말 순수하게 공격력을 1씩 올려가며 내구도를 닳게 하고 샌드백을 부서뜨립니다.
break
while
은 조건을 검사해봤을 때 False
가 나오는 순간 바로 반복문을 빠져나옵니다. 그렇다면 반복문을 빠져나올 방법은 조건에서 False
가 나오도록 유도하는 방법 뿐일까요? 다행스럽게도 반복문을 빠져나올 수 있는 방법은 한 가지 더 있습니다. 바로 break
를 이용하는 것입니다. 다음 예문을 참조해주세요.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
while True:
print("현재 공격력은 " + str(attack) + " 이며, 샌드백의 내구도는 " + str(durability) + " 입니다." )
durability -= attack
attack += 1
if durability <= 0:
break
print("샌드백이 부서졌습니다! 최종 공격력은 " + str(attack) + "입니다.")
break
는 그냥 단독으로 break
라고 씁니다. 파이썬 인터프리터가 break
를 맞닥뜨리게 된다면, 그 즉시 while
블록 바깥으로 빠져나옵니다. while
조건과 상관없이, while
문의 한복판에 있더라도 예외없이 동작합니다.
while True:
라는 뜻은, 이 while
블록을 영원히 반복하면서 실행시킬 것이라는 뜻입니다. True
값은 영원히 True
이므로 조건은 영원히 참이 되어 영원히 실행되게 되겠지요. 하지만 while
블록 내부에서 break
를 사용한다면 이 루프문을 빠져나갈 수 있는 열쇠가 되어 프로그램의 흐름을 제어할 수 있게 됩니다.
개념 정리
개념 정리의 시간입니다. 정리할 개념은 생각보다 많이 없습니다.
while
은 조건이True
이면while
블록을 실행한다. 실행을 끝마치고 조건 검사부터 무한 반복한다.while
문의 조건이 한번이라도False
가 되면 반복을 종료한다.break
를 통해while
문 중간에 즉시 중단할 수 있다.while
내부에print
함수를 추가하여 반복이 진행되고 있는 시점에서 값이 어떻게 변화하는지 실시간으로 확인할 수 있다.
else
이제껏 잘 써왔던 예문을 살짝 수정하고자 합니다. 다음 예시는 공격력이 100
까지 되었다면 단련이 충분하다 판단하고, 그만두면서 남은 내구도를 출력합니다. 그리고 100
이 되기 전에 샌드백이 부셔졌다면 샌드백이 부서졌다고 출력합니다. 또한 둘 중 어느 경우라도 최종 공격력을 출력합니다.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
while durability > 0:
print("공격력: " + str(attack) + ", 내구도: " + str(durability))
durability -= attack
attack += 1
if attack >= 100:
print("충분히 단련했습니다. 남은 내구도는 " + str(durability) + "입니다.")
break
else: ##b_1##
print("샌드백이 부서졌습니다!")
print("최종 공격력은 " + str(attack) + "입니다.")
8000
을 입력했습니다.
(중략)
공격력: 97, 내구도: 3344
공격력: 98, 내구도: 3247
공격력: 99, 내구도: 3149
충분히 단련했습니다. 남은 내구도는 3050입니다.
최종 공격력은 100입니다.
300
을 입력했습니다.
(중략)
공격력: 22, 내구도: 69
공격력: 23, 내구도: 47
공격력: 24, 내구도: 24
샌드백이 부서졌습니다!
최종 공격력은 25입니다.
b_1(1.) 코드 설명
else
가 등장했습니다. else
는 앞서 조건문에서 등장한 바 있습니다. 하지만 이 else
는 if
와 짝지어지지 않고 while
과 짝지어졌습니다. 이게 뜻하는 바는 무엇일까요?
while
과 짝지어진 else
는 if
와 비슷하게 작동되는데요, while
에 붙어 있는 조건식을 검사할 때, 이 값이 False
가 나온다면 여기 else
블록을 실행하도록 합니다. 즉 조건에 의해 루프문을 빠져나왔을 때 else
블록이 실행되는 것이죠.
여기서 유의해야 할 점은 break
를 통해 루프문을 빠져나왔을 때에는 이 else
블록이 실행되지 않는다는 점 입니다. else
는 while
에 붙어 있는 조건이 거짓일 때에만 실행되지, break
와는 전혀 인연이 없다는 점을 꼭 명심해주세요.
보통의 다른 프로그래밍 언어에서는 else
는 if
와 같은 조건문에나 있지 while
문 같은 반복문에는 잘 없습니다. 반복문에서 else
를 사용할 수 있다는 점은 파이썬만의 특징이라고 볼 수 있습니다. 반복문에 붙어있는 else
를 통해 break
로 빠져나왔는지 그렇지 않은지 곧바로 체크할 수 있기 때문에 종종 쓰이곤 합니다.
위 프로그램에 대한 흐름도를 그리면 다음과 같습니다.
샌드백 최종 코드에 대한 순서도
continue
반복문 중에서 우리가 또 쓸 수 있는 용법이 있습니다. 뭐이리 많냐구요? 아니에요, 조금만 프로그래밍에 익숙해진다면 이런 기능을 찾게 될 거예요.
continue
는 반복문 안에서 사용할 수 있는데요, 파이썬 인터프리터가 continue
를 만나게 되면 즉시 다음 루프로 넘어갑니다. break
는 실행되자마자 즉시 반복문 자체를 종료하는데, 기능이 조금 다르지요? 아래 예제는 위 예제와 기능상으로는 똑같습니다. 하지만 흐름은 조금 다르다는 걸 알게 될 거예요.
durability = int(input("샌드백의 내구도를 입력하세요 >> "))
attack = 1
while durability > 0:
print("공격력: " + str(attack) + ", 내구도: " + str(durability))
durability -= attack
attack += 1
if attack < 100:
continue
print("충분히 단련했습니다. 남은 내구도는 " + str(durability) + "입니다.")
break
else:
print("샌드백이 부서졌습니다!")
print("최종 공격력은 " + str(attack) + "입니다.")
8000
을 입력했습니다.
(중략)
공격력: 97, 내구도: 3344
공격력: 98, 내구도: 3247
공격력: 99, 내구도: 3149
충분히 단련했습니다. 남은 내구도는 3050입니다.
최종 공격력은 100입니다.
사실 위의 예제는 continue
의 용법을 단지 설명하기 위해 인의적으로 집어넣었습니다. continue
는 루프에서 어떤 조건에 맞지 않으면 더이상 이번 루프에서는 할 일이 없어서 다음번 루프로 넘기고자 할 때 유용합니다.
위 코드를 흐름도로 그리면 다음과 같습니다. 기존의 흐름과는 굉장히 유사합니다.
continue
가 들어간 코드의 흐름
여담
이러한 순서놀이를 왜 하는 건지 이해가 되지 않는 분들도 있으실 겁니다. 이후에는 사실 for
반복문이라는, 더 직관적이고 간편한 방법도 있지요. 하지만 동작 원리를 바탕으로 실제 동작 과정을 머릿속으로 상상하는 추론력을 기르셔야 합니다. 그 방법은 while
이 참 좋다고 생각합니다. 간단한 원리이지만 아주 깊은 생각을 해야 실제 동작을 상상해낼 수 있기 때문입니다. 앞으로는 더 편한 함수, 더 편한 모듈을 사용해나가며 한결 수월하게 문제를 해결해나갈 것입니다만, 이러한 추론력이 뒷받침 되어주어야, 가지고 있는 도구를 비로소 효율적으로 활용할 수 있게 될 것입니다.
연습 문제
- 반복문은 왜 사용하는가?
while
의 조건이 무엇일때while
블록이 실행되는가?while
중간에서 즉시 루프를 마치려면 어떻게 해야 하는가?- 반복문이 진행중일 때 그 상황을 알고 싶다면 어떻게 해야 하는가?
- 언제
break
를 사용하는가? while
과 짝지어진else
는 무슨 역할인가?while
과 짝지어진else
는 언제 실행되지 않는가?continue
의 기능은 무엇인가?
프로그래밍 문제
반복문을 설계하는 방법을 익힌 후 본격적으로 프로그래밍 문제를 풀어보도록 하겠습니다.
- 프롤로그
- 개발 첫걸음
- 파이썬 기초
- 파이썬 중급
- 파이썬 고급
- 내장 함수 톺아보기
- 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
- 변수의 범위 – 이름 검색의 범위
- 파이썬 심화
- 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
- 데코레이터 – 함수의 기능을 강화하기
- 프로퍼티
- 제너레이터
- async와 await
- 객체로서의 클래스 – 클래스를 동적으로 정의하기
- 파이썬 프로젝트 실습
- 원카드 게임 만들기 (1)
- 원카드 게임 만들기 (2)
- 원카드 게임 만들기 (3) (작성중)
- 턴제 자동 전투 게임 만들기 (작성중)
- 실전 (파이썬 외적인 것들)
- 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
- 유니코드 – 컴퓨터에서 문자를 표기하는 방법
- html, css, 인터넷 – 자동화 첫 걸음 내딛기
- 네트워크 – 인터넷으로 통신하는 방법
- 문서 – 문맥을 읽어보기
One thought on “파이썬 강좌 – 반복문 ~ 비슷한 작업을 반복하기”