Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6a79ac5
feat: Car 구현
Leeguhyung Sep 12, 2026
5abde42
feat: Cars 구현
Leeguhyung Sep 12, 2026
59d96cc
feat: CarMove 구현
Leeguhyung Sep 12, 2026
24cc64d
feat: FindCarWinner 구현
Leeguhyung Sep 12, 2026
f498e9e
feat: RandomNumber 구현
Leeguhyung Sep 12, 2026
a44bfc2
test: 자동차 전진 또는 정지 테스트
Leeguhyung Sep 12, 2026
b604a08
test: 자동차 리스트 저장 테스트
Leeguhyung Sep 12, 2026
650178a
test: 우승자 찾기 테스트
Leeguhyung Sep 12, 2026
d540163
refactor: 값 비교 메서드 이름 compareMax로 변경
Leeguhyung Sep 12, 2026
9e0da6a
docs: README.md 작성
Leeguhyung Sep 12, 2026
7881dc5
refactor: CarMove, FindCarWinner를 Cars로 통합
Leeguhyung Sep 13, 2026
3155ecf
style: 변수 및 파라미터 네이밍 컨벤션 수정
Leeguhyung Sep 13, 2026
c5e9ce9
refactor: addWinnerIfMatch 중복 파라미터 제거
Leeguhyung Sep 13, 2026
ee8ed1d
refactor: 위치 비교 책임을 Car로 이동
Leeguhyung Sep 13, 2026
b4297b3
test: 우승자 찾기 테스트(FindCarWinner)를 수정
Leeguhyung Sep 13, 2026
2b164c6
style : 띄어쓰기 보정
Leeguhyung Sep 13, 2026
ef757a0
refactor: 최댓값 비교에 Math.max 사용
Leeguhyung Sep 14, 2026
f55f832
refactor: movePoint를 moveIfPossible로 이름 변경
Leeguhyung Sep 14, 2026
935b269
refactor: 조건 중 하나인 4를 FORWARD_CONDITION 상수로 추출
Leeguhyung Sep 15, 2026
e5085e0
test: CarsTest 삭제
Leeguhyung Sep 15, 2026
c271a58
feat: carName 받을때 null or blank일 경우 예외처리
Leeguhyung Sep 15, 2026
74af726
refactor: Cars가 자동차 목록을 방어적 복사로 보호하도록 수정
Leeguhyung Sep 15, 2026
6663b91
refactor: findWinner에서 인덱스 대신 Car를 직접 전달(for-each 사용)
Leeguhyung Sep 15, 2026
a4ea09f
refactor: Cars에 있던 경주 진행 책임을 RacingGame으로 분리
Leeguhyung Sep 15, 2026
7e668f3
refactor: RacingGame이 한 라운드씩 경주를 진행하도록 수정
Leeguhyung Sep 16, 2026
32b64c4
feat: Car 생성자에 이름 5자 제한 검증 추가
Leeguhyung Sep 16, 2026
f5d1430
feat: main 메서드 추가하여 콘솔로 자동차 경주를 진행할 수 있게함
Leeguhyung Sep 16, 2026
205e40f
refactor: RandomNumber를 인터페이스로 분리하고 실제 랜덤 로직은 DefaultRandomNumber로 이동
Leeguhyung Sep 16, 2026
44c05e3
refactor: 자동차 이름 배열로 Cars를 생성하는 로직을 Main에서 Cars로 이동
Leeguhyung Sep 16, 2026
6b3d73c
test: 테스트 클래스/메서드 이름을 대상 클래스와 매칭함(1,2 단계 마지막 리뷰 반영사항)
Leeguhyung Sep 16, 2026
53fee69
test: 랜덤 요소가 있는 Cars.move()를 테스트
Leeguhyung Sep 16, 2026
c93f9c9
test: Car 생성자의 이름 null or blank, 5자 초과 검증 테스트 추가
Leeguhyung Sep 17, 2026
21840e4
refactor: RacingGame의 사용하지 않는 raceCount 제거
Leeguhyung Sep 17, 2026
74c4ad6
test: createCarsTest() (자동차 생성 테스트 추가)
Leeguhyung Sep 17, 2026
b752cd4
docs: README.md 진행 상황에 맞게 갱신
Leeguhyung Sep 17, 2026
5cbd68d
refactor: 4단계 힌트에 따라 domain/view 패키지로 분리
Leeguhyung Sep 19, 2026
be705aa
docs: README.md 갱신
Leeguhyung Sep 19, 2026
53feef7
Merge branch 'leeguhyung' into leeguhyung
Leeguhyung Sep 19, 2026
4259c2d
refactor: Car가 시작 위치를 생성자로 받도록 변경
Leeguhyung Sep 19, 2026
3acb21a
test: 우승자 판별 테스트에서 위치를 직접 지정하도록 수정
Leeguhyung Sep 19, 2026
9d2d30a
refactor: 패키지 분리 후 남아있던 racingcar 패키지 삭제
Leeguhyung Sep 19, 2026
95a4239
feat: Cars 생성 시 중복된 자동차 이름 검증 추가
Leeguhyung Sep 20, 2026
6e02d15
test: 같은 이름의 자동차가 있으면 예외가 발생하는지 테스트 추가
Leeguhyung Sep 20, 2026
06d2295
refactor: findWinner를 findWinners로 이름 변경 및 파라미터를 수정하지 않고 값을 반환하도록 변경
Leeguhyung Sep 20, 2026
bd625fd
chore: .gitkeep 삭제
Leeguhyung Sep 20, 2026
53f1ed2
refactor: 우승자 판별 책임을 Cars에서 RacingGame으로 이동
Leeguhyung Sep 23, 2026
61bbf08
test: 우승자 판별 테스트를 CarsTest에서 RacingGameTest로 이동
Leeguhyung Sep 23, 2026
193209a
refactor: Application의 흐름을 별도 컨트롤러로 분리
Leeguhyung Sep 23, 2026
6999405
refactor: 시도 횟수를 RacingGame이 갖도록 이동
Leeguhyung Sep 23, 2026
e92c5d4
test: RacingGame에 tryCount 인자 추가로 인한 수정
Leeguhyung Sep 23, 2026
58c1404
refactor: 최대 위치 계산을 Cars가, 우승 판정을 RacingGame이 맡도록 분리
Leeguhyung Sep 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 34 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
# 자동차 경주
# 자동차 경주 게임 (Car Racing Game)

## 설명
- 자동차 전진(4이상) 또는 정지(3이하)
- 자동차 리스트 저장으로 n대의 자동차 경주 가능
- 우승자 찾기 가능
- 랜덤 숫자 생성 가능
## 프로젝트 개요

## 패키지 구조
콘솔에서 실행되는 자동차 경주 게임입니다.
자동차 이름을 입력받아 여러 대의 자동차 객체를 생성하고, 입력한 횟수만큼 라운드를 진행하며 각 자동차가 무작위 값에 따라 전진하거나 멈춥니다. 모든 라운드가 끝나면 가장 멀리 이동한 자동차(들)이 우승자로
선정됩니다.

## 게임 규칙

- 자동차 이름은 쉼표(,)로 구분해서 여러 대를 한 번에 입력받습니다.
- 자동차 이름은 5자를 초과할 수 없습니다.
- 0~9 사이의 랜덤 값을 구해, 4 이상이면 전진하고 3 이하면 멈춥니다.
- 사용자가 입력한 횟수만큼 라운드를 반복하며, 매 라운드마다 각 자동차의 위치를 출력합니다.
- 가장 멀리 이동한 자동차가 우승자이며, 공동 우승자가 나올 수 있습니다.

## 패키지 / 클래스 구조

```
Application.java # 입력/출력을 조립하는 실행 진입점(main 메서드)

domain
├── Car.java # 이름과 위치를 가지며, 4 이상이면 전진
├── Cars.java # n대의 Car를 리스트로 관리, 이름 배열로 Cars를 생성하는 정적 팩토리(createCars) 포함
├── RandomNumber.java # 랜덤 값 생성 인터페이스
├── DefaultRandomNumber.java # RandomNumber의 실제 구현체 (0~9 사이 랜덤 값)
└── RacingGame.java # 한 라운드씩 경주를 진행

view
├── InputView.java # 자동차 이름/시도 횟수 입력받기
└── ResultView.java # 라운드별 진행 상황, 최종 우승자 출력

test/domain
├── CarTest.java # 전진/정지, 이름 검증(null/blank/5자 초과) 테스트
├── CarsTest.java # 이동, 우승자 판별, 이름 배열로 생성하는 로직 테스트
└── FixedRandomNumber.java # 테스트용 고정값 RandomNumber 구현체
```
racingcar
├── Car.java # 이름과 위치를 가지며, 4 이상이면 전진
├── Cars.java # n대의 Car를 리스트로 관리
├── RandomNumber.java # 0~9 사이 랜덤 값 생성
├── CarMove.java # 주어진 라운드 수만큼 자동차들을 이동
└── FindCarWinner.java # 가장 높은 위치의 자동차를 우승으로 판별

test/racingcar
├── CarMovingTest.java # 전진 또는 정지 테스트
├── CarsTest.java # 자동차 목록 저장 테스트
└── FindCarWinnerTest.java # 단독/공동 우승자 테스트
```
Empty file removed src/main/java/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import controller.RacingController;

public class Application {

public static void main(String[] args) {
new RacingController().run();
}

}
38 changes: 38 additions & 0 deletions src/main/java/controller/RacingController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package controller;

import static domain.Cars.createCars;
import static view.InputView.readCarName;
import static view.InputView.readTryCount;
import static view.ResultView.printFinalWinners;
import static view.ResultView.printRound;

import domain.Cars;
import domain.DefaultRandomNumber;
import domain.RacingGame;

public class RacingController {

public void run() {
//자동차 이름 입력받기
String[] carNameArray = readCarName();
//자동차 생성시키기
Cars carsList = createCars(carNameArray);
//시도할 횟수 받기
int tryCount = readTryCount();
System.out.println();
//시도 횟수만큼 경주시키기 (단, 경주할떄마다 값 출력하기)
RacingGame racingGame = new RacingGame(carsList, new DefaultRandomNumber(), tryCount);
raceCars(racingGame, carsList);
//최종 우승자 출력하기
printFinalWinners(racingGame.findWinners());
}

//시도 횟수만큼 경주시키기 (단, 경주할떄마다 값 출력하기)
private void raceCars(RacingGame racingGame, Cars carsList) {
for (int i = 0; i < racingGame.getTryCount(); i++) {
racingGame.carRaceOnce();
//경주할때마다 값 출력하기
printRound(carsList);
}
}
}
15 changes: 12 additions & 3 deletions src/main/java/racingcar/Car.java → src/main/java/domain/Car.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
package racingcar;
package domain;

public class Car {
private static final int FORWARD_CONDITION = 4;
private static final int MAX_CAR_NAME_LENGTH = 5;
private static final int MIN_CAR_POSITION = 0;
//static은 클랫 전체가 공유하는 변수

private final String carName;
//final이 자바스크립트의 const와 유사?
//private는 이제 직접 수정못하게하는? 외부에서 직접 접근 불가하게 하는것?

private int carPosition = 0;
private int carPosition;

public Car(String carName) {
public Car(String carName, int carPosition) {
if (carName == null || carName.isBlank()) {
throw new IllegalArgumentException("자동차 이름은 비어있을 수 없습니다.");
}
if (carName.length() > MAX_CAR_NAME_LENGTH) {
throw new IllegalArgumentException("자동차 이름은 5자를 초과할 수 없습니다.");
}
if (carPosition < MIN_CAR_POSITION) {
throw new IllegalArgumentException("자동차 위치는 0 이상이어야 합니다.");
}
this.carName = carName;
this.carPosition = carPosition;
}

public String getCarName() {
Expand Down
77 changes: 77 additions & 0 deletions src/main/java/domain/Cars.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Cars {

private final List<Car> cars;

public Cars(List<Car> cars) {
validateNoDuplicateNames(cars); //중복이름 예외검증
this.cars = new ArrayList<>(cars);
}

public List<Car> getCars() {
return Collections.unmodifiableList(cars); //외부에서 수정 못하게 막는거
}

public int size() {
return cars.size();
}

public void move(RandomNumber randomNumber) {
for (int i = 0; i < cars.size(); i++) {
int number = randomNumber.getRandomNumber();
cars.get(i).moveIfPossible(number);
}
}

//자동차 생성시키기(위치가 여기가 맞는것같음)
public static Cars createCars(String[] carNameArray) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이런 걸 정적 팩토리 메서드라고 하는데, 이름 배열에서 Cars를 만드는 책임을 Cars자신이 가진 것 좋습니다.

시간이 남으시면 생성자와 어떤 차이가 있는지 한번 찾아보세요. 이름을 붙일 수 있다는 것 말고도 몇 가지가 더 있습니다.

생성자의 특징에 대해 알면 조금 좋을 것 같아요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

네 알겠습니다! 정적 팩토리 메서드와 생성자 차이 확인후 코멘트 추가로 남기겠습니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

이 부분 추가적으로 알려주시면 좋을 거 같아요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

차이점에 대해서 말씀드리겠습니다.
첫 번째, 이름을 붙일 수 있습니다. 생성자는 클래스 이름만 쓸 수 있지만, 정적팩토리메서드는 createCars처럼 무엇을 만드는지 드러낼 수 있습니다.
두 번째, 정적팩토리 메소드에서는 new 처럼 새 객체를 계속해서 선언하지 않아도 됩니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

둘 다 맞습니다. 특히 두 번째는 Integer.valueOf()나 Boolean.valueOf()처럼 미리 만들어둔 객체를 재사용할 수 있죠.

찾아보시느라 고생하셨습니다. 시간 되시면 『이펙티브 자바』 아이템 1을 한번 보세요. 말씀해주신 두 가지 말고도 세 가지가 더 나옵니다. 전부 외우실 필요는 없고 이런 게 있구나 정도로 훑어두시면, 나중에 실제로 그런 상황을 만났을 때 알아보실 거예요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

네 알겠습니다!

List<Car> cars = new ArrayList<>();
for (String name : carNameArray) {
cars.add(new Car(name.trim(), 0));
}
return new Cars(cars);
}

private void validateNoDuplicateNames(List<Car> cars) {
Set<String> duplicateNames = new HashSet<>(); //[학습] Set은 중복을 허용하지 않는 자료구조
for (Car car : cars) {
if (!duplicateNames.add(car.getCarName())) { //false면 중복이니까
throw new IllegalArgumentException("자동차 이름은 중복될 수 없습니다.");
//중복 검증을 하여, 동일한 이름의 자동차가 존재하면 예외를 발생시킵니다.
}
}
}

//계산은 여기서
public int getMaxPosition() {
int maxPosition = 0;
for (Car car : cars) {
maxPosition = Math.max(maxPosition, car.getCarPosition());
}
return maxPosition;
}

// 특정 위치에 있는 자동차들을 반환
public List<Car> carsAt(int position) { // "이 위치에 있는 차들 줘"
List<Car> result = new ArrayList<>();
for (Car car : cars) {
result.addAll(carAt(car, position));
}
return result;
}
//add로 하면 값을 car로 받아야하는데 이때 우승자가 없는경우 반환값을 정하기 어려워 addAll 사용

private List<Car> carAt(Car car, int position) {
if (car.samePosition(position)) {
return List.of(car);
}
return List.of();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package racingcar;
package domain;

import java.util.Random;

public class RandomNumber {
public class DefaultRandomNumber implements RandomNumber {

private final Random randomNumber = new Random(); //굳이 변수선언 안하고 한방에 넣어도 되겠다는 생각?

@Override
public int getRandomNumber() {
return randomNumber.nextInt(10); // 0~9까지 랜덤숫자를 생성하기.
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/domain/RacingGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package domain;

import java.util.List;

public class RacingGame {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

지금 RacingGame은 cars.move()를 한 줄 전달하는 것 말고는 하는 일이 없습니다. 이런 클래스는 두 방향 중 하나를 고르면 좋을 것 같아요.

하나는 역할을 주는 겁니다. 지금 Cars가 우승자 판단까지 하고 있는데, "가장 멀리 간 차가 이긴다"는 자동차들의 성질일까요, 경주의 규칙일까요? 시도 횟수도 경주가 알 만한 정보고요.

다른 하나는 없애는 겁니다. 하는 일 없이 전달만 하는 층이라면 오히려 읽는 사람이 한 단계 더 따라가야 하니까요.

어느 쪽이든 괜찮습니다. 규형님이 고르신 방향과 그 이유가 궁금하네요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

들어보니 말씀하신부분이 맞는 것 같습니다. 그래서 RacingGame에 역할을 주기로 하였습니다.
가장 멀리 간 차가 이긴다는 자동차 목록의 성질이 아니라 경주의 규칙이라고 생각해서, Cars에 있던 findWinners()와 그 내부에서 쓰던 winnerOf(), getMaxPosition()을 RacingGame으로 옮겼습니다. 즉, Cars는 자동차 관리에만 힘쓰고 RacingGame에 우승자 판별까지 넣어서 구분지어놓았습니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

시도횟수도 RacingGame이 알만한 부분이라서 그렇게 코드수정하였습니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

RacingGame이 우승자 판단과 시도 횟수를 갖게 되면서 존재 이유가 생겼네요. 좋습니다.

다만 findWinners()와 getMaxPosition() 둘 다 cars.getCars()로 내부 리스트를 꺼내서 순회하고 있는데요. Cars가 unmodifiableList로 감싸둔 걸 결국 밖에서 풀어서 쓰는 모양이 됐습니다. 자동차들을 들고 있는 건 Cars인데 순회는 RacingGame이 하고 있고요.

"가장 멀리 간 위치가 어디냐"는 자동차들만 답할 수 있는 질문 아닐까요? 그건 Cars에게 물어보고, RacingGame은 "그 위치에 있으면 우승"이라는 규칙만 갖는 건 어떨까요? 계산은 자동차들이, 판단은 경주가 하는 셈이죠.

그렇게 나누면 우승 규칙이 바뀌었을 때 어디를 고칠지도 분명해집니다. "3칸 이상 간 차는 모두 완주"로 바뀐다면 RacingGame만 고치면 되고 Cars는 그대로니까요. 3번 질문에서 말씀드린 "바뀌어야 하는 이유가 몇 개인가"가 여기에 적용되는 자리입니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

듣고보니 맞는 말씀입니다. 반영완료하였습니다.

private final Cars cars;
private final RandomNumber randomNumber;
private final int tryCount;

public RacingGame(Cars cars, RandomNumber randomNumber, int tryCount) {
this.cars = cars;
this.randomNumber = randomNumber;
this.tryCount = tryCount;
}

public void carRaceOnce() {
cars.move(randomNumber);
}

public int getTryCount() {
return tryCount;
}

public List<Car> findWinners() {
int maxPosition = cars.getMaxPosition();
return cars.carsAt(maxPosition);
}
}
5 changes: 5 additions & 0 deletions src/main/java/domain/RandomNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package domain;

public interface RandomNumber {
int getRandomNumber();
}
53 changes: 0 additions & 53 deletions src/main/java/racingcar/Cars.java

This file was deleted.

19 changes: 0 additions & 19 deletions src/main/java/racingcar/RacingGame.java

This file was deleted.

25 changes: 25 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package view;

import java.util.Scanner;

public class InputView {
private static Scanner scanner = new Scanner(System.in);

//자동차 이름 입력받기
//static 쓰면 클래스 전체에서 공유하는거라서, 객체 생성 안하고 바로 쓸수있음
public static String[] readCarName() {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
String carNames = scanner.nextLine();
//쉼표기준으로 잘라서 넣게끔 하는거구나 split()
return carNames.split(",");
}

//자동차 생성시키기는 Cars로 옮겼음

//시도할 횟수 받기
public static int readTryCount() {
System.out.println("시도할 횟수는 몇회인가요?");
return scanner.nextInt();
//nextInt()는 콘솔 입력에서 정수 하나(다음 토큰)를 읽어서 int로 반환하는 메서드임.
}
}
29 changes: 29 additions & 0 deletions src/main/java/view/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package view;

import domain.Car;
import domain.Cars;
import java.util.ArrayList;
import java.util.List;

public class ResultView {

//라운드간 우승자 출력하기
public static void printRound(Cars carsList) {
for (Car car : carsList.getCars()) {
System.out.println(car.getCarName() + " : " + "-".repeat(car.getCarPosition()));
}
System.out.println();
}
//repeat()는 문자열 반복 메서드임. car.getCarPosition()만큼 "-"를 반복해서 출력하는거.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

주석에 학습하신 내용을 정리해두셨네요. 찾아보고 기록하는 습관은 좋습니다.

다만 주석의 용도를 한번 생각해보시면 좋겠어요. repeat()나 String.join()이 무슨 메서드인지는 나중에 이 코드를 읽는 사람에게 필요한 정보일까요? 코드를 보면 알 수 있는 걸 다시 설명하는 주석은 시간이 지나면 잘 안 맞게 되기도 하고요.

보통 주석은 코드만으로는 알 수 없는 것을 적을 때 값어치가 있다고 봅니다. 왜 이렇게 했는지, 왜 이 방법을 쓰지 않았는지 같은 거요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

말씀해주신 부분에 공감합니다. 자바를 처음 배우다 보니 새로 알게 된 메서드(repeat(), String.join() 등)를 바로 기록해두고 싶어서 주석으로 남겼는데, 돌아보니 코드를 읽는 분께 필요한 정보가 아니라 제 학습 메모였던 것 같습니다. 다만 코드를 보면서 바로 복습할 수 있다는 점 때문에 당분간은 학습 메모 주석을 유지하고 싶습니다.(주석에 //[학습] 붙여서 구분 시키겠습니다) 대신 "왜 이렇게 했는지, 왜 이 방법을 쓰지 않았는지"를 적은 주석을 추가하는 습관을 길러보도록 하겠습니다,


//최종 우승자 출력하기
public static void printFinalWinners(List<Car> winners) {
List<String> names = new ArrayList<>();
for (Car car : winners) {
names.add(car.getCarName()); // Car에서 이름만 뽑아서 새 리스트에 담음
}
System.out.println(String.join(", ", names) + "가 최종 우승했습니다.");
}
//String.join(", ", ["neo", "brown"]) → "neo, brown" 이렇게 합쳐주는거임.

}
Empty file removed src/test/java/.gitkeep
Empty file.
Loading