Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

손현수) 자동차 경주 시뮬레이션 기능 추가 #1

Open
wants to merge 27 commits into
base: Untaini
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
62e0cd4
docs: update implementation function docs
Untaini Mar 14, 2023
5e38f7e
feat: getCarListFromInput function
Untaini Mar 14, 2023
ecddec2
refactor: change getCarListFromInput function return type
Untaini Mar 15, 2023
c4b9717
refactor: Add InputUtils class
Untaini Mar 15, 2023
1b780d9
feat: getTotalRoundFromInput
Untaini Mar 15, 2023
32e13eb
feat: move and print function in Car class
Untaini Mar 15, 2023
5e45720
feat: get function in Car class
Untaini Mar 15, 2023
cd48ee3
feat: playAllRounds function
Untaini Mar 15, 2023
04615d7
refactor: change incorrect function name
Untaini Mar 15, 2023
06b3c8b
feat: printWinners function
Untaini Mar 15, 2023
65b263b
refactor: change error tag
Untaini Mar 15, 2023
f788aef
refactor: change pickNumberInRange import
Untaini Mar 15, 2023
681039c
style: change newline format and function order
Untaini Mar 15, 2023
be24ffb
feat: add StringValidator class
Untaini Mar 18, 2023
b118782
refactor: add PrintManager class
Untaini Mar 18, 2023
56122be
feat: add StringConvertor class
Untaini Mar 18, 2023
e7f1526
feat: add Round class
Untaini Mar 18, 2023
0324770
feat: add Game class
Untaini Mar 18, 2023
1dabec0
feat: createCar func
Untaini Mar 18, 2023
4b6fc87
refactor: remove unused function
Untaini Mar 18, 2023
8dc465d
refactor: use Game instance and remove unused function
Untaini Mar 18, 2023
1fee1e4
feat: getWinnersString function
Untaini Mar 18, 2023
1d07b2b
refactor: add tool, game package
Untaini Mar 18, 2023
66ed54a
refactor: change canCarName to cannotUseCarName
Untaini Mar 18, 2023
e76735a
refactor: move func from PrintManger to ListConvertor
Untaini Mar 25, 2023
dc2657f
refactor: change var name and func name for deleting type in name
Untaini Mar 25, 2023
63b1b06
refactor: declare that the constructor cannot be called
Untaini Mar 25, 2023
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
9 changes: 9 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h1>구현할 기능 목록</h1>

- ### 사용자로부터 자동차 이름 입력받고 유효성 검사하기
- ### 사용자로부터 시도할 횟수 입력받고 유효성 검사하기
- ### 시도할 횟수만큼 라운드 반복하기
- ### 모든 자동차 전진 또는 정지하기
- ### 자동차의 상태 출력하기
- ### 최종 우승자 찾기
- ### 최종 우승자 출력하기
12 changes: 11 additions & 1 deletion src/main/java/racingcar/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package racingcar;

import racingcar.game.Car;
import racingcar.game.Game;
import racingcar.tool.InputUtils;

import java.util.List;

public class Application {
public static void main(String[] args) {
// TODO 구현 진행
List<Car> cars = InputUtils.getCarListFromInput();
int totalRound = InputUtils.getTotalRoundFromInput();
Game game = new Game(cars, totalRound);

game.start();
}
}
12 changes: 0 additions & 12 deletions src/main/java/racingcar/Car.java

This file was deleted.

51 changes: 51 additions & 0 deletions src/main/java/racingcar/game/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package racingcar.game;

import camp.nextstep.edu.missionutils.Randoms;

import racingcar.tool.StringValidator;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class Car {
private final String name;
private int position = 0;

public Car(String name) {
this.name = name;
}

public static Car createCar(String carName) {
StringValidator.cannotUseCarName(carName);

return new Car(carName);
}

public int getPosition() {
return this.position;
}

public String getName() {
return this.name;
}

public String toString() {
return String.format("%s : %s",this.name, getMovingPositionLine());
}

public void move() {
if (Randoms.pickNumberInRange(0, 9) >= 4) {
this.position += 1;
}
}

private String getMovingPositionLine() {
List<String> movingPositions = Arrays.stream(new String[this.position])
.map(s -> "-")
.collect(Collectors.toList());

return String.join("", movingPositions);
}
}
45 changes: 45 additions & 0 deletions src/main/java/racingcar/game/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package racingcar.game;

import racingcar.tool.PrintManager;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Game {

private final List<Car> cars;
private final int totalRound;

public Game(List<Car> cars, int totalRound) {
this.cars = cars;
this.totalRound = totalRound;
}

public void start() {
Round round = new Round(cars);

PrintManager.printGameResultHead();
while (round.getCurrentRound() <= totalRound) {
round.play();
}

List<Car> winningCars = findWinningCars();
PrintManager.printWinningCarsName(winningCars);
}

private List<Car> findWinningCars() {
if (cars.size() == 0) {
return Collections.emptyList();
}

int maxPosition = cars.stream()
.map(Car::getPosition)
.max(Integer::compareTo)
.get();

return cars.stream()
.filter(car -> car.getPosition() == maxPosition)
.collect(Collectors.toList());
}
}
30 changes: 30 additions & 0 deletions src/main/java/racingcar/game/Round.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package racingcar.game;

import racingcar.tool.PrintManager;

import java.util.List;

public class Round {
private int currentRound;
private final List<Car> cars;

public Round(List<Car> cars) {
this.currentRound = 1;
this.cars = cars;
}

public int getCurrentRound() {
return this.currentRound;
}

public void play() {
moveAllCars();
PrintManager.printAllCarsStatus(cars);
this.currentRound += 1;
}

private void moveAllCars() {
cars.forEach(Car::move);
}

}
40 changes: 40 additions & 0 deletions src/main/java/racingcar/tool/InputUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package racingcar.tool;

import camp.nextstep.edu.missionutils.Console;

import racingcar.game.Car;

import java.util.List;

public class InputUtils {

private InputUtils() {}

public static List<Car> getCarListFromInput() {
while (true) {
PrintManager.printCarNameInputDescription();

//for to split last comma, ' ' is going to be removed by trim func.
String carNames = Console.readLine() + ' ';
try {
return StringConvertor.convertIntoCars(carNames);
} catch (IllegalArgumentException exception) {
PrintManager.printErrorMessage(exception.getMessage());
}
}
}

public static int getTotalRoundFromInput() {
while (true) {
PrintManager.printTotalRoundInputDescription();

String roundInput = Console.readLine();
try {
return StringConvertor.convertIntoNaturalNumber(roundInput);
} catch (IllegalArgumentException exception) {
PrintManager.printErrorMessage(exception.getMessage());
}
}
}

}
20 changes: 20 additions & 0 deletions src/main/java/racingcar/tool/ListConvertor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racingcar.tool;

import racingcar.game.Car;

import java.util.List;
import java.util.stream.Collectors;

public class ListConvertor {

private ListConvertor() {}

public static String joinCarsName(String delimiter, List<Car> cars) {
List<String> names = cars.stream()
.map(Car::getName)
.collect(Collectors.toList());

return String.join(delimiter, names);
}

}
37 changes: 37 additions & 0 deletions src/main/java/racingcar/tool/PrintManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package racingcar.tool;

import racingcar.game.Car;

import java.util.List;

public class PrintManager {

private PrintManager() {}

public static void printCarNameInputDescription() {
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
}

public static void printTotalRoundInputDescription() {

Choose a reason for hiding this comment

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

printCarNameInputDescription()이나 이 함수 같이 안내 문구만 각각 한 줄씩 따로 함수로 생성한 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

PrintManager는 출력과 관련된 함수들을 정의해둔 클래스입니다. 그래서 출력되는 문자열을 바꾸고 싶을 때는 PrintManager만 수정하면 되게끔 만들었습니다.

System.out.println("시도할 회수는 몇회인가요?");
}
Comment on lines +11 to +17

Choose a reason for hiding this comment

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

SRP를 위해 클래스의 책임이 명확히 구분된 것 같아서 좋습니다! 저도 해봐야겠네요


public static void printAllCarsStatus(List<Car> cars) {
cars.forEach(System.out::println);
System.out.println();
}

public static void printWinningCarsName(List<Car> winningCars) {
String winningCarsName = ListConvertor.joinCarsName(", ", winningCars);

System.out.printf("최종 우승자 : %s", winningCarsName);
}

public static void printGameResultHead() {
System.out.println("\n실행 결과");
}

public static void printErrorMessage(String message) {
System.out.printf("[ERROR] %s\n", message);
}
}
33 changes: 33 additions & 0 deletions src/main/java/racingcar/tool/StringConvertor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package racingcar.tool;

import racingcar.game.Car;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StringConvertor {

private StringConvertor() {}

public static List<Car> convertIntoCars(String carNames) throws IllegalArgumentException {
return Arrays.stream(carNames.split(","))
.map(String::trim)
.map(Car::createCar)
.collect(Collectors.toList());

Choose a reason for hiding this comment

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

함수형 프로그래밍으로 구현하신 것이 정말 인상적인 것 같습니다.
혹시 이 코드에 대한 설명을 조금이나마 부탁드려도 괜찮을까요?

Copy link
Author

Choose a reason for hiding this comment

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

위의 코드를 말로 풀면 다음과 같습니다.

  1. carNames 문자열을 ','으로 나눕니다.
  2. 나눠진 문자열의 양쪽 공백을 삭제합니다.
  3. 각 문자열을 이름으로 가지는 Car 객체를 생성합니다.
  4. 리스트로 만들어 반환합니다.

코드를 해석하는데 조금 도움이 됐으면 좋겠네요 :)

Choose a reason for hiding this comment

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

감사합니다 :)

}

public static Integer convertIntoNaturalNumber(String targetString) throws IllegalArgumentException {
try {
int number = Integer.parseInt(targetString);

if (number < 1) {
throw new NumberFormatException();
}

return number;
} catch (NumberFormatException exception) {
throw new IllegalArgumentException("자연수가 아닌 값은 입력할 수 없습니다.");
}
}
}
14 changes: 14 additions & 0 deletions src/main/java/racingcar/tool/StringValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package racingcar.tool;

public class StringValidator {

private StringValidator() {}

public static void cannotUseCarName(String carName) throws IllegalArgumentException {
if (carName.length() == 0) {
throw new IllegalArgumentException("자동차 이름은 공백일 수 없습니다.");
} else if (carName.length() > 5) {
throw new IllegalArgumentException("자동차 이름은 최대 5자리입니다. 불가능한 이름: " + carName);
}
}
}