From a5b1569ae7d8c9a57cb14f977467973a8536b0d3 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 28 Mar 2021 16:11:55 +0900 Subject: [PATCH 1/8] Add java basics.md --- java basics.md | 228 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 java basics.md diff --git a/java basics.md b/java basics.md new file mode 100644 index 00000000..aef044c1 --- /dev/null +++ b/java basics.md @@ -0,0 +1,228 @@ +# java basics + +## CQRS + +### CQRS란? + +CQRS는 Command and Query Responsibility Segregation(명령과 조회의 책임 분리)을 나타낸다. 이름처럼 시스템에서 명령을 처리하는 책임과 조회를 처리하는 책임을 분리하는 것이 +CQRS의 핵심이다. + +- 명령: 시스템의 상태를 변경하는 작업 +- 조회: 시스템의 상태를 반환하는 작업 + +모든 연산이 명령과 조회로 쉽게 양분되진 않는다. 개념적으로 어렵거나 동시성 등 기술적인 문제도 있다. + +### 단순한 CQRS 적용 + +#### stereotypical 아키텍쳐 + +CQRS가 적용돼있지 않은 다계층 아키텍쳐 + +```java + +``` + +## 디미터 법칙 + +객체 간 관계를 설정할 때 객체 간의 결합도를 효과적으로 낮출 수 있는 유용한 지침 중 하나로 꼽힌다. + +객체 지향 생활 체조 원칙 중, 한 줄에 점을 하나만 찍는다.로 요약되기도 한다. + +### Don't talk to strangers + +디미터 법칙의 핵심은 객체 구조의 경로를 따라 멀리 떨어져 있는 낯선 객체에 메시지를 보내는 설계는 피하라는 것이다. + +바꿔 말해서 객체는 내부적으로 보유하고 있거나 메시지를 통해 확보한 정보만 가지고 의사 결정을 내려야 하고 다른 객체를 탐색해 뭔가를 일어나게 해서는 안 된다. + +이러한 핵심적인 내용 때문에 디미터 법칙은 Don’t Talk to Strangers(낯선 이에게 말하지 마라)라고도 불리고 한 객체가 알아야 하는 다른 객체를 최소한으로 유지하라는 의미로 Principle of +least knowledge(최소 지식 원칙)라고도 불린다. + +```java +public class Post { + private final List comments; + + public Post(List comments) { + this.comments = comments; + } + + public List getComments() { + return comments; + } +} +``` + +```java +public class Board { + private final List posts; + + public Board(List posts) { + this.posts = posts; + } + + public void addComment(int postId, String content) { + posts.get(postId).getComments().add(new Comment(content)); + } + ... +} +``` + +바로 위에 있는 Board객체의 addComment메서드를 살펴보자. Board객체의 인스턴스 변수 posts에서 getter를 거듭해 멀리 떨어져 있는 낯선 객체 Comment를 추가하는 코드이다. + +이처럼 getter가 줄줄이 이어지는 코드 형태가 디미터 법칙을 위반한 전형적인 코드 형태이다. + +왜 낯선 객체에 메시지를 보내는 설계를 피해야 할까? 즉 디미터 법칙을 위반했을 때의 문제점은 무엇일까? + +앞서 살펴봤던 Post객체에서 만약 인스턴스 변수가 List comments에서 Comments라는 일급컬렉션 객체로 수정된다면 어떻게 될까? + +```java +public class Post { + private final Comments comments; + + public Post(Comments comments) { + this.comments = comments; + } + + public Comments getComments() { + return comments; + } +} +``` + +getter를 통해 Post객체의 List comments를 사용하던 Board 객체의 addComment 메서드가 깨지게 된다. + +```java +public class Board { + private final List posts; + + public Board(List posts) { + this.posts = posts; + } + + //에러 발생 + public void addComment(int postId, String content) { + posts.get(postId).getComments().add(new Comment(content)); + } + ... +} +``` + +이처럼 Board객체의 addComment메서드 내에서 Post객체도 알고 Comment객체도 알고 있다면 Board객체는 Post객체의 변화에도 영향을 받고 Comment객체의 변화에도 영향을 받는다. + +이러한 설계가 프로젝트 내에 즐비하다면 하나에 변화에 수많은 클래스들이 무너질 가능성이 있다. 즉 객체 간 결합도가 높아지고 객체 구조의 변화에 쉽게 무너진다. 변화에 유연히 대처하지 못하는 것이다. + +### 규칙화 + +디미터 법칙은 **노출 범위를 제한하기 위해 객체의 모든 메소드는 다음에 해당하는 메소드만을 호출해야 한다.**고 말한다. + +- 객체 자신의 메소드들 +- 메소드의 파라미터로 넘어온 객체들의 메소드들 +- 메소드 내부에서 생성, 초기화된 객체의 메소드들 +- 인스턴스 변수로 가지고 있는 객체가 소유한 메소드들 + +```java +class Demeter { + private Member member; + + public myMethod(OtherObject other) { + // ... + } + + public okLawOfDemeter(Paramemter param) { + myMethod(); // 1. 객체 자신의 메서드 + param.paramMethod(); // 2. 메서드의 파라미터로 넘어온 객체들의 메서드 + Local local = new Local(); + local.localMethod(); // 3. 메서드 내부에서 생성, 초기화된 객체의 메서드 + member.memberMethod(); // 4. 인스턴스 변수로 가지고 있는 객체가 소유한 메서드 + } +} +``` + +위의 규칙을 지켜서 최대한 노출 범위를 제한하면 좀 더 에러가 적고, 변화에 유연히 대처할 수 있는 클래스를 만들 수 있다. + +### 주의사항 + +- 자료구조라면 디미터 법칙을 거론할 필요가 없다. + +객체라면 내부 구조를 숨겨야 하므로 디미터 법칙을 지켜야 한다. + +하지만 자료구조라면 당연히 내부 구조를 노출해야 하므로 디미터 법칙이 적용되지 않는다. + +- 하나의 '.'을 강제하는 규칙이 아니다. + +디미터 법칙은 객체 지향 생활 체조 원칙 중 한 줄에 점을 하나만 찍는다.로 요약되기도 한다. + +```java +IntStream.of(1,15,3,20).filter(x->x>10).count(); +``` + +하지만 위 코드는 디미터 법칙과 객체 지향 생활 체조 원칙을 위반한 코드가 아니다. + +디미터 법칙은 결합도와 관련된 법칙이고 결합도가 문제 되는 것은 객체의 내부 구조가 외부로 노출되는 경우이다. 위 코드는 IntStream의 내부 구조가 노출되지 않았다. 단지 IntStream을 다른 +IntStream으로 변환할 뿐, 객체를 둘러싸고 있는 캡슐은 유지한다. + +한 줄에 하나 이상의 점을 찍는 모든 케이스가 객체 지향 생활 체조 원칙 및 디미터 법칙을 위반하는 것은 아니다. 객체 내부 구현에 대한 어떤 정보도 외부로 노출하지 않는다면 괜찮다. + +## 일급 컬렉션 + +일급 컬렉션이란 단어는 객체지향 생활제초 파트에서 언급되었다. + +> 규칙 8: 일급 콜렉션 사용 +이 규칙의 적용은 간단하다. +콜렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다. +각 콜렉션은 그 자체로 포장돼 있으므로 이제 콜렉션과 관련된 동작은 근거지가 마련된셈이다. +필터가 이 새 클래스의 일부가 됨을 알 수 있다. +필터는 또한 스스로 함수 객체가 될 수 있다. +또한 새 클래스는 두 그룹을 같이 묶는다든가 그룹의 각 원소에 규칙을 적용하는 등의 동작을 처리할 수 있다. +이는 인스턴스 변수에 대한 규칙의 확실한 확장이지만 그 자체를 위해서도 중요하다. +콜렉션은 실로 매우 유용한 원시 타입이다. +많은 동작이 있지만 후임 프로그래머나 유지보수 담당자에 의미적 의도나 단초는 거의 없다. - 소트웍스 앤솔로지 객체지향 생활체조편 + + +```java +Map map = new HashMap<>(); +map.put("1", "A"); +map.put("2", "B"); +map.put("3", "C"); +``` + +위의 코드를 아래와 같이 wrapping 하는 것을 이야기 한다. +```java +public class GameRanking { + + private Map ranks; + + public GameRanking(Map ranks) { + this.ranks = ranks; + } +} +``` + +collection을 wrapping 하면서, 그 외 다른 멤버 변수가 없는 상태를 일급 컬렉션이라 한다. + +wrapping을 통해 얻는 이점은 아래와 같다. + +- 비지니스에 종속적인 자료구조 +- collection의 불변성을 보장 +- 상태와 행위를 한 곳에서 관리 +- 이름이 있는 컬렉션 + + +### 비지니스에 종속적인 자료구조 + + + + + + + + + + + + + +# Reference + +- [CQRS](https://justhackem.wordpress.com/2016/09/17/what-is-cqrs/) +- [디미터 법칙](https://woowacourse.github.io/javable/post/2020-06-02-law-of-demeter/) +- [일급 컬렉션](https://jojoldu.tistory.com/412) \ No newline at end of file From 05ced1e4103a95d477ff12b7fb64ad9270266510 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 28 Mar 2021 16:17:03 +0900 Subject: [PATCH 2/8] Apply .gitignore --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9ce54cc6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.idea/ +*.iml +out/ +gradle/ +.gradle/ +*.gradle +*.bat +gradlew From fd2e0516720c83ab007352f5fd0914770acb6066 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 28 Mar 2021 16:27:08 +0900 Subject: [PATCH 3/8] feat: Initialize service --- .../src/main/java/racingcar/Application.java | 10 +++++++ racingcar/src/main/java/racingcar/Car.java | 12 +++++++++ .../src/main/java/utils/RandomUtils.java | 26 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 racingcar/src/main/java/racingcar/Application.java create mode 100644 racingcar/src/main/java/racingcar/Car.java create mode 100644 racingcar/src/main/java/utils/RandomUtils.java diff --git a/racingcar/src/main/java/racingcar/Application.java b/racingcar/src/main/java/racingcar/Application.java new file mode 100644 index 00000000..dfca8f98 --- /dev/null +++ b/racingcar/src/main/java/racingcar/Application.java @@ -0,0 +1,10 @@ +package racingcar; + +import java.util.Scanner; + +public class Application { + public static void main(String[] args) { + final Scanner scanner = new Scanner(System.in); + // TODO 구현 진행 + } +} \ No newline at end of file diff --git a/racingcar/src/main/java/racingcar/Car.java b/racingcar/src/main/java/racingcar/Car.java new file mode 100644 index 00000000..bd4b12e0 --- /dev/null +++ b/racingcar/src/main/java/racingcar/Car.java @@ -0,0 +1,12 @@ +package racingcar; + +public class Car { + private final String name; + private int position = 0; + + public Car(String name) { + this.name = name; + } + + // 추가 기능 구현 +} \ No newline at end of file diff --git a/racingcar/src/main/java/utils/RandomUtils.java b/racingcar/src/main/java/utils/RandomUtils.java new file mode 100644 index 00000000..567e0092 --- /dev/null +++ b/racingcar/src/main/java/utils/RandomUtils.java @@ -0,0 +1,26 @@ +package utils; + +import java.util.Random; + +public class RandomUtils { + private static final Random RANDOM = new Random(); + + private RandomUtils() { + } + + public static int nextInt(final int startInclusive, final int endInclusive) { + if (startInclusive > endInclusive) { + throw new IllegalArgumentException(); + } + + if (startInclusive < 0) { + throw new IllegalArgumentException(); + } + + if (startInclusive == endInclusive) { + return startInclusive; + + return startInclusive + RANDOM.nextInt(endInclusive - startInclusive + 1); + } + } +} \ No newline at end of file From b8395833899af3f4051bf781f5829c6245d43c40 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 28 Mar 2021 20:35:44 +0900 Subject: [PATCH 4/8] style: Add input name, cycle --- racingcar/src/main/java/racingcar/Application.java | 9 +++++++++ racingcar/src/main/java/racingcar/GameController.java | 5 +++++ 2 files changed, 14 insertions(+) create mode 100644 racingcar/src/main/java/racingcar/GameController.java diff --git a/racingcar/src/main/java/racingcar/Application.java b/racingcar/src/main/java/racingcar/Application.java index dfca8f98..93b17d0b 100644 --- a/racingcar/src/main/java/racingcar/Application.java +++ b/racingcar/src/main/java/racingcar/Application.java @@ -3,8 +3,17 @@ import java.util.Scanner; public class Application { + public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); // TODO 구현 진행 + String carName; + int cycle; + + carName = scanner.next(); + cycle = scanner.nextInt(); + String[] carNames = carName.split(","); + + } } \ No newline at end of file diff --git a/racingcar/src/main/java/racingcar/GameController.java b/racingcar/src/main/java/racingcar/GameController.java new file mode 100644 index 00000000..0497cf5a --- /dev/null +++ b/racingcar/src/main/java/racingcar/GameController.java @@ -0,0 +1,5 @@ +package racingcar; + +public class GameController { + +} From afccd0c3bd130845104b9da12618b37fbc9d8c45 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 4 Apr 2021 03:18:36 +0900 Subject: [PATCH 5/8] feat: Add name error catcher when name is longer than 5 words, or there were same names. --- .../src/main/java/racingcar/Application.java | 11 ++++- .../src/main/java/utils/ErrorCatcher.java | 13 ++++++ racingcar/src/main/java/utils/Validator.java | 43 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 racingcar/src/main/java/utils/ErrorCatcher.java create mode 100644 racingcar/src/main/java/utils/Validator.java diff --git a/racingcar/src/main/java/racingcar/Application.java b/racingcar/src/main/java/racingcar/Application.java index 93b17d0b..d9f264c1 100644 --- a/racingcar/src/main/java/racingcar/Application.java +++ b/racingcar/src/main/java/racingcar/Application.java @@ -1,6 +1,7 @@ package racingcar; import java.util.Scanner; +import utils.Validator; public class Application { @@ -9,11 +10,19 @@ public static void main(String[] args) { // TODO 구현 진행 String carName; int cycle; + int[] nameCheck = {0, 0}; + int[] nameCheckCmp = {0, 0}; carName = scanner.next(); cycle = scanner.nextInt(); String[] carNames = carName.split(","); - + nameCheck = Validator.validateName(carNames); + + if (nameCheck.equals(nameCheckCmp)) { + GameController gameController = new GameController(); + gameController.startGame(); + } + } } \ No newline at end of file diff --git a/racingcar/src/main/java/utils/ErrorCatcher.java b/racingcar/src/main/java/utils/ErrorCatcher.java new file mode 100644 index 00000000..15f5e1a1 --- /dev/null +++ b/racingcar/src/main/java/utils/ErrorCatcher.java @@ -0,0 +1,13 @@ +package utils; + +public class ErrorCatcher { + public static void CatchNameError(int[] nameErrors) { + if (nameErrors[0] == 1) { + System.out.println("[ERROR] 중복된 이름이 있습니다."); + } + + if (nameErrors[1] == 1) { + System.out.println("[ERROR] 이름의 길이가 부적절합니다."); + } + } +} diff --git a/racingcar/src/main/java/utils/Validator.java b/racingcar/src/main/java/utils/Validator.java new file mode 100644 index 00000000..9ceca2ab --- /dev/null +++ b/racingcar/src/main/java/utils/Validator.java @@ -0,0 +1,43 @@ +package utils; + +import java.util.HashMap; +import java.util.Map; + +public class Validator { + public static int[] validateName(String[] carNames) { + int[] validationResult = {0, 0}; + + // index 0에 이름 중복 검사 결과 + // index 1에 이름 길이 검사 결과 + validationResult[0] = isNameOnly(carNames); + + for (int i = 0; i < carNames.length; i++) { + String name = carNames[i]; + + if (isNameLong(name)) { + validationResult[1] = 1; + break; + } + } + return validationResult; + } + + public static boolean isNameLong(String name) { + if (name.length() > 5) { + return true; + } + return false; + } + + public static int isNameOnly(String[] carNames) { + Map nameCount = new HashMap(); + + for (int i = 0; i < carNames.length; i++) { + if (nameCount.containsKey(carNames[i])) { + return 1; + } + nameCount.put(carNames[i], "이것은 존재한."); + } + return 0; + } +} From d8844f26da8c113eef9ac2f8a317b3a992a78264 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 4 Apr 2021 06:56:54 +0900 Subject: [PATCH 6/8] feat: Add game starter --- racingcar/src/main/java/View/OutputView.java | 26 +++++++++++++++++++ .../src/main/java/racingcar/Application.java | 14 ++++++---- racingcar/src/main/java/racingcar/Car.java | 19 +++++++++++++- .../main/java/racingcar/GameController.java | 26 +++++++++++++++++++ .../src/main/java/utils/ErrorCatcher.java | 6 ++++- .../src/main/java/utils/RandomUtils.java | 6 ++--- racingcar/src/main/java/utils/Validator.java | 4 +++ 7 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 racingcar/src/main/java/View/OutputView.java diff --git a/racingcar/src/main/java/View/OutputView.java b/racingcar/src/main/java/View/OutputView.java new file mode 100644 index 00000000..424f4dfc --- /dev/null +++ b/racingcar/src/main/java/View/OutputView.java @@ -0,0 +1,26 @@ +package View; + +import racingcar.Car; +import java.util.List; + +public class OutputView { + public static final String bar = "-"; + + public static void printResultTitle() { + System.out.println("\n실행 결과"); + } + + public static void printResultPosition(List cars) { + for (Car car : cars) { + printCarPosition(car); + } + } + + public static void printCarPosition(Car car) { + System.out.println(car.getName() + " : "); + for (int i = 0; i < car.getPosition(); i++) { + System.out.println(bar); + } + System.out.println(); + } +} diff --git a/racingcar/src/main/java/racingcar/Application.java b/racingcar/src/main/java/racingcar/Application.java index d9f264c1..93f238e0 100644 --- a/racingcar/src/main/java/racingcar/Application.java +++ b/racingcar/src/main/java/racingcar/Application.java @@ -1,28 +1,32 @@ package racingcar; import java.util.Scanner; + import utils.Validator; +import utils.ErrorCatcher; public class Application { public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); // TODO 구현 진행 - String carName; + String[] carNames; int cycle; int[] nameCheck = {0, 0}; int[] nameCheckCmp = {0, 0}; - carName = scanner.next(); + System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); + carNames = scanner.nextLine().split(","); + System.out.println("시도할 회수는 몇회인가요?"); cycle = scanner.nextInt(); - String[] carNames = carName.split(","); + //String[] carNames = carName.split(","); nameCheck = Validator.validateName(carNames); + ErrorCatcher.catchNameError(nameCheck); if (nameCheck.equals(nameCheckCmp)) { GameController gameController = new GameController(); - gameController.startGame(); + gameController.startGame(carNames, cycle); } - } } \ No newline at end of file diff --git a/racingcar/src/main/java/racingcar/Car.java b/racingcar/src/main/java/racingcar/Car.java index bd4b12e0..12293a9a 100644 --- a/racingcar/src/main/java/racingcar/Car.java +++ b/racingcar/src/main/java/racingcar/Car.java @@ -1,6 +1,11 @@ package racingcar; +import utils.RandomUtils; + public class Car { + private static final int START_INCLUSIVE = 0; + private static final int END_INCLUSIVE = 9; + private static final int MOVE_THRESHOLD = 4; private final String name; private int position = 0; @@ -8,5 +13,17 @@ public Car(String name) { this.name = name; } - // 추가 기능 구현 + public void go() { + if (RandomUtils.nextInt(START_INCLUSIVE, END_INCLUSIVE) > MOVE_THRESHOLD) { + position++; + } + } + + public String getName() { + return name; + } + + public int getPosition() { + return position; + } } \ No newline at end of file diff --git a/racingcar/src/main/java/racingcar/GameController.java b/racingcar/src/main/java/racingcar/GameController.java index 0497cf5a..8e9940ba 100644 --- a/racingcar/src/main/java/racingcar/GameController.java +++ b/racingcar/src/main/java/racingcar/GameController.java @@ -1,5 +1,31 @@ package racingcar; +import View.OutputView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class GameController { + public void startGame(String[] carNames, int cycle) { + List cars = null; + for (int i = 0; i < carNames.length; i++) { + cars.add(new Car(carNames[i])); + } + + OutputView.printResultTitle(); + + for (int i = 0; i < cycle; i++) { + OutputView.printResultPosition(moveCar(cars)); + System.out.println(); + } + } + + public List moveCar(List cars) { + for (Car car : cars) { + car.go(); + } + return cars; + } } diff --git a/racingcar/src/main/java/utils/ErrorCatcher.java b/racingcar/src/main/java/utils/ErrorCatcher.java index 15f5e1a1..93b16c6d 100644 --- a/racingcar/src/main/java/utils/ErrorCatcher.java +++ b/racingcar/src/main/java/utils/ErrorCatcher.java @@ -1,7 +1,11 @@ package utils; public class ErrorCatcher { - public static void CatchNameError(int[] nameErrors) { + private ErrorCatcher() { + + } + + public static void catchNameError(int[] nameErrors) { if (nameErrors[0] == 1) { System.out.println("[ERROR] 중복된 이름이 있습니다."); } diff --git a/racingcar/src/main/java/utils/RandomUtils.java b/racingcar/src/main/java/utils/RandomUtils.java index 567e0092..1866e729 100644 --- a/racingcar/src/main/java/utils/RandomUtils.java +++ b/racingcar/src/main/java/utils/RandomUtils.java @@ -10,7 +10,7 @@ private RandomUtils() { public static int nextInt(final int startInclusive, final int endInclusive) { if (startInclusive > endInclusive) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("[ERROR] 랜덤값이 잘못되었습니다."); } if (startInclusive < 0) { @@ -19,8 +19,8 @@ public static int nextInt(final int startInclusive, final int endInclusive) { if (startInclusive == endInclusive) { return startInclusive; - - return startInclusive + RANDOM.nextInt(endInclusive - startInclusive + 1); } + + return startInclusive + RANDOM.nextInt(endInclusive - startInclusive + 1); } } \ No newline at end of file diff --git a/racingcar/src/main/java/utils/Validator.java b/racingcar/src/main/java/utils/Validator.java index 9ceca2ab..6f18abbc 100644 --- a/racingcar/src/main/java/utils/Validator.java +++ b/racingcar/src/main/java/utils/Validator.java @@ -4,6 +4,10 @@ import java.util.Map; public class Validator { + private Validator() { + + } + public static int[] validateName(String[] carNames) { int[] validationResult = {0, 0}; From 992f4f81d320a21dde83c194da652c6beaa53e53 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 4 Apr 2021 08:05:13 +0900 Subject: [PATCH 7/8] fix: Fix issue where didn't show racing progress --- racingcar/src/main/java/View/OutputView.java | 5 +++-- .../src/main/java/racingcar/Application.java | 6 ++---- racingcar/src/main/java/racingcar/Car.java | 8 ++++---- .../src/main/java/racingcar/GameController.java | 17 +++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/racingcar/src/main/java/View/OutputView.java b/racingcar/src/main/java/View/OutputView.java index 424f4dfc..c371e1a7 100644 --- a/racingcar/src/main/java/View/OutputView.java +++ b/racingcar/src/main/java/View/OutputView.java @@ -17,9 +17,10 @@ public static void printResultPosition(List cars) { } public static void printCarPosition(Car car) { - System.out.println(car.getName() + " : "); + System.out.print(car.getName() + " : "); + for (int i = 0; i < car.getPosition(); i++) { - System.out.println(bar); + System.out.print(bar); } System.out.println(); } diff --git a/racingcar/src/main/java/racingcar/Application.java b/racingcar/src/main/java/racingcar/Application.java index 93f238e0..3d24fc52 100644 --- a/racingcar/src/main/java/racingcar/Application.java +++ b/racingcar/src/main/java/racingcar/Application.java @@ -9,9 +9,8 @@ public class Application { public static void main(String[] args) { final Scanner scanner = new Scanner(System.in); - // TODO 구현 진행 String[] carNames; - int cycle; + int cycle = 0; int[] nameCheck = {0, 0}; int[] nameCheckCmp = {0, 0}; @@ -19,12 +18,11 @@ public static void main(String[] args) { carNames = scanner.nextLine().split(","); System.out.println("시도할 회수는 몇회인가요?"); cycle = scanner.nextInt(); - //String[] carNames = carName.split(","); nameCheck = Validator.validateName(carNames); ErrorCatcher.catchNameError(nameCheck); - if (nameCheck.equals(nameCheckCmp)) { + if (nameCheck[0] == nameCheckCmp[0] && nameCheck[1] == nameCheckCmp[1]) { GameController gameController = new GameController(); gameController.startGame(carNames, cycle); } diff --git a/racingcar/src/main/java/racingcar/Car.java b/racingcar/src/main/java/racingcar/Car.java index 12293a9a..21d6dae7 100644 --- a/racingcar/src/main/java/racingcar/Car.java +++ b/racingcar/src/main/java/racingcar/Car.java @@ -13,17 +13,17 @@ public Car(String name) { this.name = name; } - public void go() { - if (RandomUtils.nextInt(START_INCLUSIVE, END_INCLUSIVE) > MOVE_THRESHOLD) { + public void move() { + if (RandomUtils.nextInt(START_INCLUSIVE, END_INCLUSIVE) >= MOVE_THRESHOLD) { position++; } } public String getName() { - return name; + return this.name; } public int getPosition() { - return position; + return this.position; } } \ No newline at end of file diff --git a/racingcar/src/main/java/racingcar/GameController.java b/racingcar/src/main/java/racingcar/GameController.java index 8e9940ba..e9605a32 100644 --- a/racingcar/src/main/java/racingcar/GameController.java +++ b/racingcar/src/main/java/racingcar/GameController.java @@ -2,29 +2,30 @@ import View.OutputView; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class GameController { + private List cars; public void startGame(String[] carNames, int cycle) { - List cars = null; - for (int i = 0; i < carNames.length; i++) { - cars.add(new Car(carNames[i])); - } + cars = Arrays.asList(carNames) + .stream() + .map(Car::new) + .collect(Collectors.toList()); OutputView.printResultTitle(); for (int i = 0; i < cycle; i++) { - OutputView.printResultPosition(moveCar(cars)); + OutputView.printResultPosition(moveCar()); System.out.println(); } } - public List moveCar(List cars) { + public List moveCar() { for (Car car : cars) { - car.go(); + car.move(); } return cars; } From cb00b88e9e785a381904e451800fe1a8c5346a31 Mon Sep 17 00:00:00 2001 From: BLINK-ONCE Date: Sun, 4 Apr 2021 08:29:51 +0900 Subject: [PATCH 8/8] feat: Add print winner --- racingcar/src/main/java/View/OutputView.java | 11 ++++++++ .../main/java/racingcar/GameController.java | 9 ++++++- racingcar/src/main/java/racingcar/Winner.java | 25 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 racingcar/src/main/java/racingcar/Winner.java diff --git a/racingcar/src/main/java/View/OutputView.java b/racingcar/src/main/java/View/OutputView.java index c371e1a7..64d8b011 100644 --- a/racingcar/src/main/java/View/OutputView.java +++ b/racingcar/src/main/java/View/OutputView.java @@ -2,9 +2,11 @@ import racingcar.Car; import java.util.List; +import racingcar.Winner; public class OutputView { public static final String bar = "-"; + public static int maxReach; public static void printResultTitle() { System.out.println("\n실행 결과"); @@ -23,5 +25,14 @@ public static void printCarPosition(Car car) { System.out.print(bar); } System.out.println(); + + if (maxReach < car.getPosition()) { + maxReach = car.getPosition(); + } + } + + public static void printWinner(Winner winner) { + System.out.println("최종 우승자"); + System.out.print(winner.getWinnersName()); } } diff --git a/racingcar/src/main/java/racingcar/GameController.java b/racingcar/src/main/java/racingcar/GameController.java index e9605a32..a63bc997 100644 --- a/racingcar/src/main/java/racingcar/GameController.java +++ b/racingcar/src/main/java/racingcar/GameController.java @@ -14,13 +14,13 @@ public void startGame(String[] carNames, int cycle) { .stream() .map(Car::new) .collect(Collectors.toList()); - OutputView.printResultTitle(); for (int i = 0; i < cycle; i++) { OutputView.printResultPosition(moveCar()); System.out.println(); } + OutputView.printWinner(winner()); } public List moveCar() { @@ -29,4 +29,11 @@ public List moveCar() { } return cars; } + + public Winner winner() { + return new Winner(cars ,cars.stream() + .mapToInt(Car::getPosition) + .max() + .getAsInt()); + } } diff --git a/racingcar/src/main/java/racingcar/Winner.java b/racingcar/src/main/java/racingcar/Winner.java new file mode 100644 index 00000000..11c9b763 --- /dev/null +++ b/racingcar/src/main/java/racingcar/Winner.java @@ -0,0 +1,25 @@ +package racingcar; + +import java.util.ArrayList; +import java.util.List; + +public class Winner { + private List cars; + private int maxPosition; + + public Winner(List cars, int maxPosition) { + this.cars = cars; + this.maxPosition = maxPosition; + } + + public List getWinnersName() { + List winnerName = new ArrayList<>(); + + for (int i = 0; i < cars.size(); i++) { + if (cars.get(i).getPosition() == maxPosition) { + winnerName.add(cars.get(i).getName()); + } + } + return winnerName; + } +}