From 85d28df83daa9ba9e9c9ca856e478ed0c395bb56 Mon Sep 17 00:00:00 2001 From: so528 Date: Thu, 6 Feb 2025 17:33:40 +0900 Subject: [PATCH 01/14] =?UTF-8?q?[=EC=9E=90=EB=8F=99=EC=B0=A8=20=EA=B2=BD?= =?UTF-8?q?=EC=A3=BC]=EC=86=8C=ED=98=84=EC=9A=B0=20=EA=B3=BC=EC=A0=9C=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 43 ++++++++++++++++++++++++++++++------ tests/racingcar/test_main.py | 2 +- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 4128547..fe9440d 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,12 +1,41 @@ def main(): - """ - 프로그램의 진입점 함수. - 여기에서 전체 프로그램 로직을 시작합니다. - """ - # 프로그램의 메인 로직을 여기에 구현 - print("프로그램이 시작되었습니다.") + import random + car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") + car_names = list(set(name.strip() for name in car_names if name.strip())) + car_dict = {} + for name in car_names: + name = name.strip() + if len(name) > 5: + raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") + + car_dict[name] = 0 + + try: + N = int(input("시도할 횟수는 몇 회인가요? ")) + if N <= 0: + raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!") + except ValueError: + print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") + return + + carPos = {name: 0 for name in car_dict} + + for _ in range(N): + for name in car_dict: + rand_num = random.randint(1, 9) + if rand_num >= 4: + carPos[name] += 1 + + for name in carPos: + print(f"{name} : {'-' * carPos[name] if carPos[name] > 0 else ' '}") + print() # 줄바꿈 추가 + + print() # 최종 출력과 구분을 위해 개행 추가 + maxPos = max(carPos.values()) + winners = [name for name, pos in carPos.items() if pos == maxPos] + + print(f"최종 우승자 : {', '.join(winners)}") if __name__ == "__main__": - # 프로그램이 직접 실행될 때만 main() 함수를 호출 main() diff --git a/tests/racingcar/test_main.py b/tests/racingcar/test_main.py index 2bb91be..4c4efcc 100644 --- a/tests/racingcar/test_main.py +++ b/tests/racingcar/test_main.py @@ -19,7 +19,7 @@ def test_전진_및_정지(capsys): main() # 프로그램 실행 # 출력값을 캡처한 후 검증 - 캡처된_출력 = capsys.readouterr() + 캡처된_출력 = capsys.readouterr().out assert all(예상_출력 in 캡처된_출력 for 예상_출력 in ["pobi : -", "woni : ", "최종 우승자 : pobi"]) From f2a2b88541e5ab4f2a273c2fc98b2ba23e4b65e9 Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 13:13:46 +0900 Subject: [PATCH 02/14] =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=82=AC=ED=95=AD?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 48 ++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index fe9440d..9b76244 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,16 +1,31 @@ +import random + +def move_cars(car_positions): + """자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)""" + for name in car_positions: + if random.randint(1, 9) >= 4: + car_positions[name] += 1 + +def print_race(car_positions): + """현재 경주 상태 출력""" + for name, pos in car_positions.items(): + print(f"{name} : {'-' * pos if pos > 0 else ' '}") + print() + +def get_winners(car_positions): + """최종 우승자 결정""" + max_pos = max(car_positions.values()) + return [name for name, pos in car_positions.items() if pos == max_pos] + def main(): - import random + """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(set(name.strip() for name in car_names if name.strip())) - car_dict = {} + car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) # 중복 제거 (순서 유지) for name in car_names: - name = name.strip() if len(name) > 5: raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") - car_dict[name] = 0 - try: N = int(input("시도할 횟수는 몇 회인가요? ")) if N <= 0: @@ -19,23 +34,14 @@ def main(): print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") return - carPos = {name: 0 for name in car_dict} - - for _ in range(N): - for name in car_dict: - rand_num = random.randint(1, 9) - if rand_num >= 4: - carPos[name] += 1 - - for name in carPos: - print(f"{name} : {'-' * carPos[name] if carPos[name] > 0 else ' '}") - print() # 줄바꿈 추가 + car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - print() # 최종 출력과 구분을 위해 개행 추가 - maxPos = max(carPos.values()) - winners = [name for name, pos in carPos.items() if pos == maxPos] + for _ in range(N): + move_cars(car_positions) # 자동차 이동 + print_race(car_positions) # 현재 상태 출력 - print(f"최종 우승자 : {', '.join(winners)}") + winners = get_winners(car_positions) # 우승자 결정 + print(f"\n최종 우승자 : {', '.join(winners)}") if __name__ == "__main__": main() From a252e0f597fb28930665050553f501dd3189f404 Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 15:58:40 +0900 Subject: [PATCH 03/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 ++++++++++++++++++++++++ src/racingcar/main.py | 13 ++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8af4ef..a9c14e5 100644 --- a/README.md +++ b/README.md @@ -208,3 +208,27 @@ jun : ----- - **기능을 구현하기 전 `docs/README.md`에 구현할 기능 목록을 정리**해 추가합니다. - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가합니다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고하여 커밋 메시지를 작성합니다. + + +## 구현할 기능 목록 +1. **자동차 이름 입력** + - 쉼표(`,`)로 구분된 자동차 이름을 입력 + - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError + - 중복된 이름은 제거 + +2. **시도 횟수 입력** + - 사용자로부터 경주 시도 횟수를 입력 + - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError + - 숫자가 아닌 값을 입력하면 -> ValueError + +3. **자동차 경주 진행** (move_cars 함수로 구현) + - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 + - 이동 결과를 출력 + +4. **경주 상태 출력** (print_race 함수로 구현) + - 각 자동차의 현재 위치를 화면에 출력 + - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 + +5. **우승자 결정** (get_winners 함수로 구현) + - 가장 멀리 이동한 자동차를 우승자로 선정 + - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 9b76244..28e15ab 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,3 +1,5 @@ +""" 자동차 경주 게임 메인 스크립트 """ + import random def move_cars(car_positions): @@ -9,9 +11,13 @@ def move_cars(car_positions): def print_race(car_positions): """현재 경주 상태 출력""" for name, pos in car_positions.items(): - print(f"{name} : {'-' * pos if pos > 0 else ' '}") + if pos > 0: + print(f"{name} : {'-' * pos}") + else: + print(f"{name} : {' '}") print() + def get_winners(car_positions): """최종 우승자 결정""" max_pos = max(car_positions.values()) @@ -20,7 +26,7 @@ def get_winners(car_positions): def main(): """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) # 중복 제거 (순서 유지) + car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) for name in car_names: if len(name) > 5: @@ -36,12 +42,13 @@ def main(): car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - for _ in range(N): + for _ in range(N): move_cars(car_positions) # 자동차 이동 print_race(car_positions) # 현재 상태 출력 winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") + if __name__ == "__main__": main() From 175d1a0b4a93bf9e0784f5679b8c1c1f56d414cc Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 16:05:06 +0900 Subject: [PATCH 04/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=952?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 28e15ab..01460c2 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -2,29 +2,36 @@ import random + def move_cars(car_positions): """자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)""" + for name in car_positions: if random.randint(1, 9) >= 4: car_positions[name] += 1 + def print_race(car_positions): """현재 경주 상태 출력""" + for name, pos in car_positions.items(): if pos > 0: print(f"{name} : {'-' * pos}") else: - print(f"{name} : {' '}") + print(f"{name} : {' '}") # Trailing whitespace 제거 print() def get_winners(car_positions): """최종 우승자 결정""" + max_pos = max(car_positions.values()) return [name for name, pos in car_positions.items() if pos == max_pos] + def main(): """메인 함수""" + car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) @@ -49,6 +56,5 @@ def main(): winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") - if __name__ == "__main__": main() From 0e0930ae9dca2ff95601fb0215c0ddbf58b968b5 Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:01:19 +0900 Subject: [PATCH 05/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=953?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ----------------------- docs/README.md | 22 ++++++++++++++++++++++ src/racingcar/main.py | 15 +++++++++------ 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index a9c14e5..2c4947c 100644 --- a/README.md +++ b/README.md @@ -209,26 +209,3 @@ jun : ----- - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가합니다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고하여 커밋 메시지를 작성합니다. - -## 구현할 기능 목록 -1. **자동차 이름 입력** - - 쉼표(`,`)로 구분된 자동차 이름을 입력 - - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError - - 중복된 이름은 제거 - -2. **시도 횟수 입력** - - 사용자로부터 경주 시도 횟수를 입력 - - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError - - 숫자가 아닌 값을 입력하면 -> ValueError - -3. **자동차 경주 진행** (move_cars 함수로 구현) - - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 - - 이동 결과를 출력 - -4. **경주 상태 출력** (print_race 함수로 구현) - - 각 자동차의 현재 위치를 화면에 출력 - - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 - -5. **우승자 결정** (get_winners 함수로 구현) - - 가장 멀리 이동한 자동차를 우승자로 선정 - - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index e69de29..b3dc5d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,22 @@ +## 구현할 기능 목록 +1. **자동차 이름 입력** + - 쉼표(`,`)로 구분된 자동차 이름을 입력 + - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError + - 중복된 이름은 제거 + +2. **시도 횟수 입력** + - 사용자로부터 경주 시도 횟수를 입력 + - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError + - 숫자가 아닌 값을 입력하면 -> ValueError + +3. **자동차 경주 진행** (move_cars 함수로 구현) + - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 + - 이동 결과를 출력 + +4. **경주 상태 출력** (print_race 함수로 구현) + - 각 자동차의 현재 위치를 화면에 출력 + - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 + +5. **우승자 결정** (get_winners 함수로 구현) + - 가장 멀리 이동한 자동차를 우승자로 선정 + - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 01460c2..64b0b6e 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -18,7 +18,7 @@ def print_race(car_positions): if pos > 0: print(f"{name} : {'-' * pos}") else: - print(f"{name} : {' '}") # Trailing whitespace 제거 + print(f"{name} : {' '.rstrip()}") # Trailing whitespace 제거 print() @@ -32,16 +32,18 @@ def get_winners(car_positions): def main(): """메인 함수""" - car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) + car_names = input("경주할 자동차 이름을 입력하세요." + "(이름은 쉼표로 구분): ").split(",") + car_names = list(dict.fromkeys(name.strip() for name in car_names + if name.strip())) for name in car_names: if len(name) > 5: raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") try: - N = int(input("시도할 횟수는 몇 회인가요? ")) - if N <= 0: + num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 변수명 수정 + if num_attempts <= 0: raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!") except ValueError: print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") @@ -49,12 +51,13 @@ def main(): car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - for _ in range(N): + for _ in range(num_attempts): # 변수명 수정 move_cars(car_positions) # 자동차 이동 print_race(car_positions) # 현재 상태 출력 winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") + if __name__ == "__main__": main() From 70e122e214db8046441ed43ca8d007041f740b9b Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:09:26 +0900 Subject: [PATCH 06/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=954?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 64b0b6e..eb7babd 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -33,9 +33,9 @@ def main(): """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요." - "(이름은 쉼표로 구분): ").split(",") + "(이름은 쉼표로 구분): ").split(",") car_names = list(dict.fromkeys(name.strip() for name in car_names - if name.strip())) + if name.strip())) # 들여쓰기 수정 for name in car_names: if len(name) > 5: From a8f68ff7178f271a24793fe592b609c29719c4aa Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:21:07 +0900 Subject: [PATCH 07/14] =?UTF-8?q?=EC=B5=9C=EC=A2=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index eb7babd..ada9b57 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -34,8 +34,9 @@ def main(): car_names = input("경주할 자동차 이름을 입력하세요." "(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names - if name.strip())) # 들여쓰기 수정 + car_names = list(dict.fromkeys( + name.strip() for name in car_names if name.strip() + )) # ✅ 올바른 들여쓰기 수정 for name in car_names: if len(name) > 5: From 4ae58d82ac387b3bbff1c4f54689dcad6f0133fd Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 13:13:46 +0900 Subject: [PATCH 08/14] refactor1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 자동차 이동 로직을 함수로 분리 - 현재 경주 상태 출력 로직 함수로 분리 - 우승자 결정 로직 함수로 분리 - 중복제거를 위해 list 대신 dict.fromkeys()를 활용 - 전반적 가독성 개선 --- src/racingcar/main.py | 48 ++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index fe9440d..9b76244 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,16 +1,31 @@ +import random + +def move_cars(car_positions): + """자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)""" + for name in car_positions: + if random.randint(1, 9) >= 4: + car_positions[name] += 1 + +def print_race(car_positions): + """현재 경주 상태 출력""" + for name, pos in car_positions.items(): + print(f"{name} : {'-' * pos if pos > 0 else ' '}") + print() + +def get_winners(car_positions): + """최종 우승자 결정""" + max_pos = max(car_positions.values()) + return [name for name, pos in car_positions.items() if pos == max_pos] + def main(): - import random + """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(set(name.strip() for name in car_names if name.strip())) - car_dict = {} + car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) # 중복 제거 (순서 유지) for name in car_names: - name = name.strip() if len(name) > 5: raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") - car_dict[name] = 0 - try: N = int(input("시도할 횟수는 몇 회인가요? ")) if N <= 0: @@ -19,23 +34,14 @@ def main(): print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") return - carPos = {name: 0 for name in car_dict} - - for _ in range(N): - for name in car_dict: - rand_num = random.randint(1, 9) - if rand_num >= 4: - carPos[name] += 1 - - for name in carPos: - print(f"{name} : {'-' * carPos[name] if carPos[name] > 0 else ' '}") - print() # 줄바꿈 추가 + car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - print() # 최종 출력과 구분을 위해 개행 추가 - maxPos = max(carPos.values()) - winners = [name for name, pos in carPos.items() if pos == maxPos] + for _ in range(N): + move_cars(car_positions) # 자동차 이동 + print_race(car_positions) # 현재 상태 출력 - print(f"최종 우승자 : {', '.join(winners)}") + winners = get_winners(car_positions) # 우승자 결정 + print(f"\n최종 우승자 : {', '.join(winners)}") if __name__ == "__main__": main() From 468f74fc820e7a86247a91e7bce35aaa5d880ed5 Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 15:58:40 +0900 Subject: [PATCH 09/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 ++++++++++++++++++++++++ src/racingcar/main.py | 13 ++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8af4ef..a9c14e5 100644 --- a/README.md +++ b/README.md @@ -208,3 +208,27 @@ jun : ----- - **기능을 구현하기 전 `docs/README.md`에 구현할 기능 목록을 정리**해 추가합니다. - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가합니다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고하여 커밋 메시지를 작성합니다. + + +## 구현할 기능 목록 +1. **자동차 이름 입력** + - 쉼표(`,`)로 구분된 자동차 이름을 입력 + - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError + - 중복된 이름은 제거 + +2. **시도 횟수 입력** + - 사용자로부터 경주 시도 횟수를 입력 + - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError + - 숫자가 아닌 값을 입력하면 -> ValueError + +3. **자동차 경주 진행** (move_cars 함수로 구현) + - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 + - 이동 결과를 출력 + +4. **경주 상태 출력** (print_race 함수로 구현) + - 각 자동차의 현재 위치를 화면에 출력 + - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 + +5. **우승자 결정** (get_winners 함수로 구현) + - 가장 멀리 이동한 자동차를 우승자로 선정 + - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 9b76244..28e15ab 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,3 +1,5 @@ +""" 자동차 경주 게임 메인 스크립트 """ + import random def move_cars(car_positions): @@ -9,9 +11,13 @@ def move_cars(car_positions): def print_race(car_positions): """현재 경주 상태 출력""" for name, pos in car_positions.items(): - print(f"{name} : {'-' * pos if pos > 0 else ' '}") + if pos > 0: + print(f"{name} : {'-' * pos}") + else: + print(f"{name} : {' '}") print() + def get_winners(car_positions): """최종 우승자 결정""" max_pos = max(car_positions.values()) @@ -20,7 +26,7 @@ def get_winners(car_positions): def main(): """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) # 중복 제거 (순서 유지) + car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) for name in car_names: if len(name) > 5: @@ -36,12 +42,13 @@ def main(): car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - for _ in range(N): + for _ in range(N): move_cars(car_positions) # 자동차 이동 print_race(car_positions) # 현재 상태 출력 winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") + if __name__ == "__main__": main() From 20341e2352365e3cd7096dcd993cf4b8e89297ed Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 16:05:06 +0900 Subject: [PATCH 10/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=952?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 28e15ab..01460c2 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -2,29 +2,36 @@ import random + def move_cars(car_positions): """자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)""" + for name in car_positions: if random.randint(1, 9) >= 4: car_positions[name] += 1 + def print_race(car_positions): """현재 경주 상태 출력""" + for name, pos in car_positions.items(): if pos > 0: print(f"{name} : {'-' * pos}") else: - print(f"{name} : {' '}") + print(f"{name} : {' '}") # Trailing whitespace 제거 print() def get_winners(car_positions): """최종 우승자 결정""" + max_pos = max(car_positions.values()) return [name for name, pos in car_positions.items() if pos == max_pos] + def main(): """메인 함수""" + car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) @@ -49,6 +56,5 @@ def main(): winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") - if __name__ == "__main__": main() From c3928cf037bfdaef8d0374bdc6e12da20c2a783c Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:01:19 +0900 Subject: [PATCH 11/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=953?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ----------------------- docs/README.md | 22 ++++++++++++++++++++++ src/racingcar/main.py | 15 +++++++++------ 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index a9c14e5..2c4947c 100644 --- a/README.md +++ b/README.md @@ -209,26 +209,3 @@ jun : ----- - **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가합니다. - [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고하여 커밋 메시지를 작성합니다. - -## 구현할 기능 목록 -1. **자동차 이름 입력** - - 쉼표(`,`)로 구분된 자동차 이름을 입력 - - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError - - 중복된 이름은 제거 - -2. **시도 횟수 입력** - - 사용자로부터 경주 시도 횟수를 입력 - - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError - - 숫자가 아닌 값을 입력하면 -> ValueError - -3. **자동차 경주 진행** (move_cars 함수로 구현) - - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 - - 이동 결과를 출력 - -4. **경주 상태 출력** (print_race 함수로 구현) - - 각 자동차의 현재 위치를 화면에 출력 - - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 - -5. **우승자 결정** (get_winners 함수로 구현) - - 가장 멀리 이동한 자동차를 우승자로 선정 - - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index e69de29..b3dc5d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,22 @@ +## 구현할 기능 목록 +1. **자동차 이름 입력** + - 쉼표(`,`)로 구분된 자동차 이름을 입력 + - 각 이름은 5자 이하로 제한 -> 넘으면 ValueError + - 중복된 이름은 제거 + +2. **시도 횟수 입력** + - 사용자로부터 경주 시도 횟수를 입력 + - 입력값이 1 이상이어야 한다. -> 넘으면 ValueError + - 숫자가 아닌 값을 입력하면 -> ValueError + +3. **자동차 경주 진행** (move_cars 함수로 구현) + - 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동 + - 이동 결과를 출력 + +4. **경주 상태 출력** (print_race 함수로 구현) + - 각 자동차의 현재 위치를 화면에 출력 + - 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시 + +5. **우승자 결정** (get_winners 함수로 구현) + - 가장 멀리 이동한 자동차를 우승자로 선정 + - 여러 명이 동점일 경우, 공동 우승자로 처리 \ No newline at end of file diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 01460c2..64b0b6e 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -18,7 +18,7 @@ def print_race(car_positions): if pos > 0: print(f"{name} : {'-' * pos}") else: - print(f"{name} : {' '}") # Trailing whitespace 제거 + print(f"{name} : {' '.rstrip()}") # Trailing whitespace 제거 print() @@ -32,16 +32,18 @@ def get_winners(car_positions): def main(): """메인 함수""" - car_names = input("경주할 자동차 이름을 입력하세요.(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names if name.strip())) + car_names = input("경주할 자동차 이름을 입력하세요." + "(이름은 쉼표로 구분): ").split(",") + car_names = list(dict.fromkeys(name.strip() for name in car_names + if name.strip())) for name in car_names: if len(name) > 5: raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") try: - N = int(input("시도할 횟수는 몇 회인가요? ")) - if N <= 0: + num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 변수명 수정 + if num_attempts <= 0: raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!") except ValueError: print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") @@ -49,12 +51,13 @@ def main(): car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - for _ in range(N): + for _ in range(num_attempts): # 변수명 수정 move_cars(car_positions) # 자동차 이동 print_race(car_positions) # 현재 상태 출력 winners = get_winners(car_positions) # 우승자 결정 print(f"\n최종 우승자 : {', '.join(winners)}") + if __name__ == "__main__": main() From c76e56f344024ccdfeba6b2ea55fa9f4567c686c Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:09:26 +0900 Subject: [PATCH 12/14] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=B9=B4?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=954?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index 64b0b6e..eb7babd 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -33,9 +33,9 @@ def main(): """메인 함수""" car_names = input("경주할 자동차 이름을 입력하세요." - "(이름은 쉼표로 구분): ").split(",") + "(이름은 쉼표로 구분): ").split(",") car_names = list(dict.fromkeys(name.strip() for name in car_names - if name.strip())) + if name.strip())) # 들여쓰기 수정 for name in car_names: if len(name) > 5: From d37e97a89b8436409619af8d683660979e937d16 Mon Sep 17 00:00:00 2001 From: so528 Date: Fri, 7 Feb 2025 21:21:07 +0900 Subject: [PATCH 13/14] =?UTF-8?q?=EC=B5=9C=EC=A2=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/racingcar/main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index eb7babd..ada9b57 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -34,8 +34,9 @@ def main(): car_names = input("경주할 자동차 이름을 입력하세요." "(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys(name.strip() for name in car_names - if name.strip())) # 들여쓰기 수정 + car_names = list(dict.fromkeys( + name.strip() for name in car_names if name.strip() + )) # ✅ 올바른 들여쓰기 수정 for name in car_names: if len(name) > 5: From e3ce741e1818aa46436e439ccf3f6c9555f57b07 Mon Sep 17 00:00:00 2001 From: so528 Date: Thu, 13 Feb 2025 02:12:24 +0900 Subject: [PATCH 14/14] refactoring --- src/racingcar/main.py | 117 ++++++++++++++++++++++++++++++++----- tests/study/test_string.py | 2 +- 2 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/racingcar/main.py b/src/racingcar/main.py index ada9b57..af595dc 100644 --- a/src/racingcar/main.py +++ b/src/racingcar/main.py @@ -1,13 +1,96 @@ -""" 자동차 경주 게임 메인 스크립트 """ +"""자동차 경주 게임 메인 스크립트""" import random +# 상수 정의 +MOVE_THRESHOLD = 4 # 자동차가 전진할 최소 랜덤 값 +MIN_RAND = 1 # 랜덤 숫자의 최소값 +MAX_RAND = 9 # 랜덤 숫자의 최대값 +MAX_NAME_LENGTH = 5 # 자동차 이름 최대 길이 + + +def move_cars(car_positions): + """자동차 이동 로직 (랜덤 숫자가 MOVE_THRESHOLD 이상이면 이동)""" + + for name in car_positions: + if random.randint(MIN_RAND, MAX_RAND) >= MOVE_THRESHOLD: + car_positions[name] += 1 + + +def print_race(car_positions): + """현재 경주 상태 출력""" + + for name, pos in car_positions.items(): + if pos > 0: + print(f"{name} : {'-' * pos}") + else: + print(f"{name} : {' '.rstrip()}") # Trailing whitespace 제거 + print() + + +def get_winners(car_positions): + """최종 우승자 결정""" + + max_pos = max(car_positions.values()) + return [ + name for name, pos in car_positions.items() if pos == max_pos + ] # ✅ 긴 줄 개행 처리 + + +def main(): + """메인 함수""" + + car_names = input("경주할 자동차 이름을 입력하세요. (이름은 쉼표로 구분): ").split( + "," + ) # ✅ 긴 문자열 개행 처리 + + car_names = list( + dict.fromkeys(name.strip() for name in car_names if name.strip()) + ) # ✅ 중복 제거 및 공백 제거 (가독성 향상) + + for name in car_names: + if len(name) > MAX_NAME_LENGTH: + raise ValueError( + f"⚠ 자동차 이름은 {MAX_NAME_LENGTH}자 이하만 가능합니다!" + ) # ✅ 긴 문자열 개행 처리 + + try: + num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 시도 횟수 입력 + if num_attempts <= 0: + raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!") + except ValueError: + print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.") + return + + car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 + + for _ in range(num_attempts): + move_cars(car_positions) # 자동차 이동 + print_race(car_positions) # 현재 상태 출력 + + winners = get_winners(car_positions) # 우승자 결정 + print(f"\n최종 우승자 : {', '.join(winners)}") + + +if __name__ == "__main__": + main() # ✅ 마지막 빈 줄 제거 (W391 해결) 현재 코드에서 """자동차 경주 게임 메인 스크립트""" + +import random + + +# 상수 정의 +MOVE_THRESHOLD = 4 # 자동차가 전진할 최소 랜덤 값 +MIN_RAND = 1 # 랜덤 숫자의 최소값 +MAX_RAND = 9 # 랜덤 숫자의 최대값 +MAX_NAME_LENGTH = 5 # 자동차 이름 최대 길이 + + def move_cars(car_positions): - """자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)""" + """자동차 이동 로직 (랜덤 숫자가 MOVE_THRESHOLD 이상이면 이동)""" for name in car_positions: - if random.randint(1, 9) >= 4: + if random.randint(MIN_RAND, MAX_RAND) >= MOVE_THRESHOLD: car_positions[name] += 1 @@ -26,24 +109,30 @@ def get_winners(car_positions): """최종 우승자 결정""" max_pos = max(car_positions.values()) - return [name for name, pos in car_positions.items() if pos == max_pos] + return [ + name for name, pos in car_positions.items() if pos == max_pos + ] # ✅ 긴 줄 개행 처리 def main(): """메인 함수""" - car_names = input("경주할 자동차 이름을 입력하세요." - "(이름은 쉼표로 구분): ").split(",") - car_names = list(dict.fromkeys( - name.strip() for name in car_names if name.strip() - )) # ✅ 올바른 들여쓰기 수정 + car_names = input("경주할 자동차 이름을 입력하세요. (이름은 쉼표로 구분): ").split( + "," + ) # ✅ 긴 문자열 개행 처리 + + car_names = list( + dict.fromkeys(name.strip() for name in car_names if name.strip()) + ) # ✅ 중복 제거 및 공백 제거 (가독성 향상) for name in car_names: - if len(name) > 5: - raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!") + if len(name) > MAX_NAME_LENGTH: + raise ValueError( + f"⚠ 자동차 이름은 {MAX_NAME_LENGTH}자 이하만 가능합니다!" + ) # ✅ 긴 문자열 개행 처리 try: - num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 변수명 수정 + num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 시도 횟수 입력 if num_attempts <= 0: raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!") except ValueError: @@ -52,7 +141,7 @@ def main(): car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화 - for _ in range(num_attempts): # 변수명 수정 + for _ in range(num_attempts): move_cars(car_positions) # 자동차 이동 print_race(car_positions) # 현재 상태 출력 @@ -61,4 +150,4 @@ def main(): if __name__ == "__main__": - main() + main() # ✅ 마지막 빈 줄 제거 (W391 해결) \ No newline at end of file diff --git a/tests/study/test_string.py b/tests/study/test_string.py index 2c36044..bf446a7 100644 --- a/tests/study/test_string.py +++ b/tests/study/test_string.py @@ -60,4 +60,4 @@ def test_charAt_메서드_위치_잘못된_경우_예외(): # 문자열 범위를 벗어나는 위치에 접근할 때 예외가 발생하는지 확인 with pytest.raises(IndexError, match="string index out of range"): - _ = input_str[5] + _ = input_str[5] \ No newline at end of file