Skip to content
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,4 @@ jun : -----
- **기능을 구현하기 전 `docs/README.md`에 구현할 기능 목록을 정리**해 추가합니다.
- **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가합니다.
- [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고하여 커밋 메시지를 작성합니다.

22 changes: 22 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## 구현할 기능 목록
1. **자동차 이름 입력**
- 쉼표(`,`)로 구분된 자동차 이름을 입력
- 각 이름은 5자 이하로 제한 -> 넘으면 ValueError
- 중복된 이름은 제거

2. **시도 횟수 입력**
- 사용자로부터 경주 시도 횟수를 입력
- 입력값이 1 이상이어야 한다. -> 넘으면 ValueError
- 숫자가 아닌 값을 입력하면 -> ValueError

3. **자동차 경주 진행** (move_cars 함수로 구현)
- 각 자동차는 무작위 숫자를 받아 4 이상이면 한 칸 이동
- 이동 결과를 출력

4. **경주 상태 출력** (print_race 함수로 구현)
- 각 자동차의 현재 위치를 화면에 출력
- 자동차 이름 오른쪽에 이동한 거리를 `-`로 표시

5. **우승자 결정** (get_winners 함수로 구현)
- 가장 멀리 이동한 자동차를 우승자로 선정
- 여러 명이 동점일 경우, 공동 우승자로 처리
192 changes: 184 additions & 8 deletions src/racingcar/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,188 @@
<<<<<<< HEAD
"""자동차 경주 게임 메인 스크립트"""
=======
""" 자동차 경주 게임 메인 스크립트 """
>>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa

import random


<<<<<<< HEAD
# 상수 정의
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:
=======
def move_cars(car_positions):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

PEP8 스타일 가이드를 준수해야 합니다.

다음과 같은 스타일 문제를 수정해 주세요:

  • 함수 정의 사이에 빈 줄 2개가 필요합니다
  • 29번 줄이 최대 길이(79자)를 초과합니다
  • 45번 줄에 불필요한 공백이 있습니다
  • 변수 N은 snake_case 명명 규칙을 따라야 합니다
-def move_cars(car_positions):
+
+
+def move_cars(car_positions):

-def print_race(car_positions):
+
+
+def print_race(car_positions):

-def main():
+
+
+def main():

-    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()
+    ))

-    N = int(input("시도할 횟수는 몇 회인가요? "))
+    num_attempts = int(input("시도할 횟수는 몇 회인가요? "))

-    for _ in range(N): 
+    for _ in range(num_attempts):

Also applies to: 11-11, 26-26, 29-29, 36-36, 45-45

🧰 Tools
🪛 GitHub Actions: Check PEP8 Style

[error] 5-5: E302 expected 2 blank lines, found 1

"""자동차 이동 로직 (랜덤 숫자가 4 이상이면 이동)"""

for name in car_positions:
if random.randint(1, 9) >= 4:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

숫자상수는, 매직넘버상수로 바꾸고 전방선언 해주는 것이 좋습니다.

>>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa
car_positions[name] += 1


def print_race(car_positions):
"""현재 경주 상태 출력"""

for name, pos in car_positions.items():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pos도 좋지만 position처럼 풀네임으로 작성하는 것도 고민해보세요.

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())
<<<<<<< HEAD
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]
>>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa


def main():
"""
프로그램의 진입점 함수.
여기에서 전체 프로그램 로직을 시작합니다.
"""
# 프로그램의 메인 로직을 여기에 구현
print("프로그램이 시작되었습니다.")
"""메인 함수"""

<<<<<<< HEAD
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("시도할 횟수는 몇 회인가요? ")) # 시도 횟수 입력
=======
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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

숫자상수는, 매직넘버상수로 바꾸고 전방선언 해주는 것이 좋습니다.

raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!")
Comment on lines +78 to +86
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

입력 검증 로직을 별도 함수로 분리하세요.

현재 main 함수가 너무 많은 책임을 가지고 있습니다. 입력 검증 로직을 분리하면 코드의 가독성과 재사용성이 향상됩니다.

다음과 같이 분리하는 것을 제안합니다:

+def validate_car_names(names: list[str]) -> None:
+    """자동차 이름 유효성 검사"""
+    if not names:
+        raise ValueError("⚠ 유효한 자동차 이름이 없습니다!")
+    for name in names:
+        if len(name) > 5:
+            raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!")

 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) > 5:
-            raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!")
+    validate_car_names(car_names)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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자 이하만 가능합니다!")
def validate_car_names(names: list[str]) -> None:
"""자동차 이름 유효성 검사"""
if not names:
raise ValueError("⚠ 유효한 자동차 이름이 없습니다!")
for name in names:
if len(name) > 5:
raise ValueError("⚠ 자동차 이름은 5자 이하만 가능합니다!")
def main():
car_names = input("경주할 자동차 이름을 입력하세요."
"(이름은 쉼표로 구분): ").split(",")
car_names = list(dict.fromkeys(
name.strip() for name in car_names if name.strip()
))
validate_car_names(car_names)


try:
num_attempts = int(input("시도할 횟수는 몇 회인가요? ")) # 변수명 수정
>>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa
if num_attempts <= 0:
raise ValueError("⚠ 시도 횟수는 1 이상이어야 합니다!")
except ValueError:
print("⚠ 잘못된 입력입니다. 숫자를 입력하세요.")
return

car_positions = {name: 0 for name in car_names} # 자동차 위치 초기화

<<<<<<< HEAD
for _ in range(num_attempts):
=======
for _ in range(num_attempts): # 변수명 수정
>>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa
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):
"""자동차 이동 로직 (랜덤 숫자가 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() 함수를 호출
main()
main() # ✅ 마지막 빈 줄 제거 (W391 해결)
Comment on lines +1 to +188
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🚨 병합 충돌을 해결해야 합니다.

파일에 해결되지 않은 병합 충돌이 있습니다:

  • <<<<<<< HEAD, =======, >>>>>>> a8f68ff7178f271a24793fe592b609c29719c4aa 마커가 여러 곳에 남아있습니다.
  • 이로 인해 파이프라인 검사가 실패하고 있습니다.

병합 충돌을 해결하고 다시 커밋해주세요. 병합 시에는 다음 사항을 고려해주세요:

  1. 상수 정의 부분은 HEAD 버전을 선택하는 것이 좋습니다 (매직 넘버 제거).
  2. 들여쓰기는 PEP8 스타일을 따르도록 해주세요.
  3. 중복된 코드 블록을 제거해주세요 (114-188줄이 1-113줄과 중복됨).
🧰 Tools
🪛 Ruff (0.8.2)

1-1: SyntaxError: Expected a statement


1-1: SyntaxError: Expected a statement


1-1: SyntaxError: Expected a statement


1-1: SyntaxError: Expected a statement


3-3: SyntaxError: Expected a statement


3-3: SyntaxError: Expected a statement


3-3: SyntaxError: Expected a statement


3-3: SyntaxError: Expected a statement


3-4: SyntaxError: Expected a statement


5-5: SyntaxError: Expected a statement


5-5: SyntaxError: Expected a statement


5-5: SyntaxError: Expected a statement


5-5: SyntaxError: Expected a statement


10-10: SyntaxError: Expected a statement


10-10: SyntaxError: Expected a statement


10-10: SyntaxError: Expected a statement


10-10: SyntaxError: Expected a statement


22-23: SyntaxError: Expected an indented block after if statement


23-23: SyntaxError: Expected a statement


23-23: SyntaxError: Expected a statement


23-23: SyntaxError: Expected a statement


23-23: SyntaxError: Expected a statement


23-24: SyntaxError: Expected a statement


28-29: SyntaxError: Expected an indented block after if statement


29-29: SyntaxError: Expected a statement


29-29: SyntaxError: Expected a statement


29-29: SyntaxError: Expected a statement


29-29: SyntaxError: Expected a statement


30-30: SyntaxError: Unexpected indentation


33-33: SyntaxError: Expected a statement


48-48: SyntaxError: Expected a statement


48-48: SyntaxError: Expected a statement


48-48: SyntaxError: Expected a statement


48-48: SyntaxError: Expected a statement


49-49: SyntaxError: Unexpected indentation


52-52: SyntaxError: Expected a statement


52-52: SyntaxError: Expected a statement


52-52: SyntaxError: Expected a statement


52-52: SyntaxError: Expected a statement


52-53: SyntaxError: Expected a statement


53-53: SyntaxError: Unexpected indentation


54-54: SyntaxError: Expected a statement


54-54: SyntaxError: Expected a statement


54-54: SyntaxError: Expected a statement


54-54: SyntaxError: Expected a statement


60-60: SyntaxError: Expected a statement


60-60: SyntaxError: Expected a statement


60-60: SyntaxError: Expected a statement


60-60: SyntaxError: Expected a statement


61-61: SyntaxError: Unexpected indentation


77-77: SyntaxError: Expected except or finally after try block


77-77: SyntaxError: Expected a statement


77-77: SyntaxError: Expected a statement


77-77: SyntaxError: Expected a statement


77-78: SyntaxError: Expected a statement


78-78: SyntaxError: Unexpected indentation


90-90: SyntaxError: Expected except or finally after try block


90-90: SyntaxError: Expected a statement


90-90: SyntaxError: Expected a statement


90-90: SyntaxError: Expected a statement


91-91: SyntaxError: Unexpected indentation


93-93: SyntaxError: unindent does not match any outer indentation level


93-94: SyntaxError: Expected an expression


94-94: SyntaxError: Unexpected indentation


97-97: SyntaxError: unindent does not match any outer indentation level


99-99: SyntaxError: Expected a statement


99-99: SyntaxError: Expected a statement


99-99: SyntaxError: Expected a statement


99-99: SyntaxError: Expected a statement


100-100: SyntaxError: Unexpected indentation


100-101: SyntaxError: Expected an indented block after for statement


101-101: SyntaxError: Expected a statement


101-101: SyntaxError: Expected a statement


101-101: SyntaxError: Expected a statement


101-101: SyntaxError: Expected a statement


101-102: SyntaxError: Expected a statement


102-102: SyntaxError: Unexpected indentation


102-103: SyntaxError: Expected an indented block after for statement


103-103: SyntaxError: Expected a statement


103-103: SyntaxError: Expected a statement


103-103: SyntaxError: Expected a statement


103-103: SyntaxError: Expected a statement


104-104: SyntaxError: Unexpected indentation


107-107: SyntaxError: unindent does not match any outer indentation level


108-108: SyntaxError: Unexpected indentation


111-111: SyntaxError: Expected a statement

🪛 GitHub Actions: Check Indentation Depth

[error] 1-1: Parsing failed: 'invalid syntax (racingcar.main, line 1)'

🪛 GitHub Actions: Check No External Libraries

[error] 1-1: SyntaxError: invalid syntax due to merge conflict markers (<<<<<<< HEAD).

🪛 GitHub Actions: Run tests and upload coverage

[error] 1-1: SyntaxError: invalid syntax due to unresolved merge conflict markers.

🪛 GitHub Actions: Check PEP8 Style

[error] 1-1: SyntaxError: invalid syntax

2 changes: 1 addition & 1 deletion tests/racingcar/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_전진_및_정지(capsys):
main() # 프로그램 실행

# 출력값을 캡처한 후 검증
캡처된_출력 = capsys.readouterr()
캡처된_출력 = capsys.readouterr().out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎㅎ 제가 실수한 부분인데 잘 체크하고 고치셨어요!

assert all(예상_출력 in 캡처된_출력 for 예상_출력 in ["pobi : -", "woni : ", "최종 우승자 : pobi"])


Expand Down
2 changes: 1 addition & 1 deletion tests/study/test_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ def test_charAt_메서드_위치_잘못된_경우_예외():

# 문자열 범위를 벗어나는 위치에 접근할 때 예외가 발생하는지 확인
with pytest.raises(IndexError, match="string index out of range"):
_ = input_str[5]
_ = input_str[5]
Loading