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

3단계 - 사다리(게임 실행) #2034

Open
wants to merge 8 commits into
base: hvoiunq
Choose a base branch
from
23 changes: 23 additions & 0 deletions STEP3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## STEP3 기능 요구사항
* 사다리 실행 결과를 출력해야 한다.
* 개인별 이름을 입력하면 개인별 결과를 출력하고, "all"을 입력하면 전체 참여자의 실행 결과를 출력한다.

## 프로그래밍 요구사항
자바 8의 스트림과 람다를 적용해 프로그래밍한다.
규칙 6: 모든 엔티티를 작게 유지한다.
규칙 7: 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다. (= 2개까지만 허용)

## STEP2 보완사항
* [X] Ladder 생성, List<Boolean> -> 이전상태와 현재상태를 가지고 있는 객체

## Step3 기능분해
* [X] 실행 결과를 입력할 수 있다.
* [X] 참가자보다 적게 입력하는 경우 Exception 발생
* [X] 참가자는 현재 위치를 가지고 있는다.
* [X] 참가자가 여러명인 경우 자동으로 현재 위치를 가지고 있는다.
* [X] 참가자가 위치한 라인의 이전상태가 true면 뒤로 이동한다.
* [X] 제일 왼쪽에 위치한 참가자가 한칸 더 왼쪽으로 이동하는 경우 Exception 발생
* [X] 참가자가 위치한 라인의 현재상태가 true면 앞으로 이동한다.
* [X] 제일 오른쪽에 위치한 참가자가 한칸 더 오른쪽으로 이동하는 경우 Exception 발생
* [X] 특정 참가자의 이름을 입력하는 경우 현재 위치의 실행결과를 보여준다.
* [X] 전체 결과를 보는 경우 각 참가자의 모든 실행결과를 보여준다.
4 changes: 4 additions & 0 deletions src/main/java/nextstep/ladder/domain/Ladder.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public List<Line> getLines() {
return lines;
}

public Line getLineByHeight(int height) {
return lines.get(height);
}

@Override
public String toString() {
return "Ladder{" +
Expand Down
49 changes: 13 additions & 36 deletions src/main/java/nextstep/ladder/domain/Line.java
Original file line number Diff line number Diff line change
@@ -1,60 +1,37 @@
package nextstep.ladder.domain;

import nextstep.ladder.utils.RandomLineGenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class Line {
private final List<Boolean> points;
private final ArrayList<LineState> points;

public Line(int countOfParticipant) {
this(generateRandomLine(countOfParticipant));
checkForConsecutiveTrues(this.getPoints());
}

public Line(int countOfParticipant, LineGenerator lineGenerator) {
this(generateRandomLine(countOfParticipant, lineGenerator));
checkForConsecutiveTrues(this.getPoints());
}

private static ArrayList<Boolean> generateRandomLine(int countOfParticipant) {
LineGenerator lineGenerator = new RandomLineGenerator();
ArrayList<Boolean> line = new ArrayList<>();
line.add(false); // 사다리 라인의 맨 왼쪽은 생성될 수 없다.
private static ArrayList<LineState> generateRandomLine(int countOfParticipant) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private static ArrayList<LineState> generateRandomLine(int countOfParticipant) {
private static List<LineState> generateRandomLine(int countOfParticipant) {

가능하면 구현체보다 인터페이스 사용할 것을 추천
인터페이스로 구현하는 것이 왜 좋은지 고민해 보면 좋겠다.

ArrayList<LineState> line = new ArrayList<>();
LineState firstPoint = new LineState(false, false); // 사다리 라인의 맨 왼쪽은 생성될 수 없다.
line.add(firstPoint);
for (int i = 1; i < countOfParticipant; i++) {
boolean shouldGenerateLine = !line.get(i - 1) && lineGenerator.generateLine();
line.add(shouldGenerateLine);
LineState point = LineState.previousOf(line.get(i-1).getCurrent());
line.add(point);
}
return line;
}

private static ArrayList<Boolean> generateRandomLine(int countOfParticipant, LineGenerator lineGenerator) {
ArrayList<Boolean> line = new ArrayList<>();
line.add(false); // 사다리 라인의 맨 왼쪽은 생성될 수 없다.
for (int i = 1; i < countOfParticipant; i++) {
boolean shouldGenerateLine = lineGenerator.generateLine();
line.add(shouldGenerateLine);
}
return line;
public Line(ArrayList<LineState> points) {
this.points = points;
}

private static void checkForConsecutiveTrues(List<Boolean> points) {
IntStream.range(0, points.size() - 1)
.filter(i -> points.get(i) && points.get(i + 1))
.findFirst()
.ifPresent(i -> {
throw new IllegalArgumentException("사다리 라인은 연속으로 겹칠 수 없습니다.");
});
public List<LineState> getPoints() {
return points;
}

public Line(List<Boolean> points) {
this.points = points;
}

public List<Boolean> getPoints() {
return points;
public LineState getPointsByIndex(int index) {
return points.get(index);
}

@Override
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/nextstep/ladder/domain/LineState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package nextstep.ladder.domain;

import nextstep.ladder.utils.RandomLineGenerator;

public class LineState {
private final boolean previous;
private final boolean current;
Comment on lines +6 to +7
Copy link
Contributor

Choose a reason for hiding this comment

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

👍



public static LineState previousOf(boolean previous) {
LineGenerator lineGenerator = new RandomLineGenerator();
return new LineState(previous, !previous && lineGenerator.generateLine());
}

public static LineState previousOf(boolean previous, LineGenerator lineGenerator) {
return new LineState(previous, lineGenerator.generateLine());
}

public LineState(boolean previous, boolean current) {
Copy link
Contributor

Choose a reason for hiding this comment

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

생성자는 클래스 메서드 앞에 위치하는 것이 관례임

checkForConsecutiveTrue(previous, current);
Copy link
Contributor

Choose a reason for hiding this comment

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

extract method를 통해 분리한 private 메서드는 가능하면 바로 아래 위치하도록 구현하는 것을 추천

this.previous = previous;
this.current = current;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

next LineState를 생성하기 위해 다음과 같이 구현하는 것은 어떨까?

    public LineState next() {
        return new LineState(current, lineGenerator.generateLine())
    }

public boolean getPrevious() {
return previous;
}

public boolean getCurrent() {
return current;
}

private void checkForConsecutiveTrue(boolean previous, boolean current) {
if (previous && current) {
throw new IllegalArgumentException("사다리 라인은 연속으로 겹칠 수 없습니다.");
}
}

@Override
public String toString() {
return "LineState{" +
"previous=" + previous +
", current=" + current +
'}';
}
}
38 changes: 34 additions & 4 deletions src/main/java/nextstep/ladder/domain/Participant.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package nextstep.ladder.domain;

import nextstep.ladder.exception.CanNotMoveException;
import nextstep.ladder.exception.CannotRegisterNameException;

public class Participant {

public static final int MIN_NAME_LENGTH = 1;
public static final int MAX_NAME_LENGTH = 5;
private String name;
private final String name;
private int position;


public static Participant nameOf(String name) {
public static Participant nameOf(String name, int position) {
validateNameLength(name.trim());
return new Participant(name.trim());
return new Participant(name.trim(), position);
}

private Participant(String name) {
private Participant(String name, int position) {
this.name = name;
this.position = position;
}

private static void validateNameLength(String name) {
Expand All @@ -27,14 +30,41 @@ private static void validateNameLength(String name) {
}
}

public void moveFront(int participantCount) {
canMoveFront(participantCount);
this.position++;
}

private void canMoveFront(int participantCount) {
if (position == participantCount - 1) {
throw new CanNotMoveException("제일 오른쪽에 위치해, 더 이상 오른쪽으로 이동할 수 없습니다.");
}
}

public void moveBack() {
canMoveBack();
this.position--;
}

private void canMoveBack() {
if (this.position == 0) {
throw new CanNotMoveException("제일 왼쪽에 위치해, 더 이상 왼쪽으로 이동할 수 없습니다.");
}
}

public String getName() {
return name;
}

public int getPosition() {
return position;
}

@Override
public String toString() {
return "Participant{" +
"name='" + name + '\'' +
", position=" + position +
'}';
}
}
22 changes: 21 additions & 1 deletion src/main/java/nextstep/ladder/domain/Participants.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
package nextstep.ladder.domain;

import nextstep.ladder.exception.NotFoundException;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class Participants {
private final List<Participant> players;
private static final AtomicInteger sequence = new AtomicInteger(0);

public Participants(String names) {
this(Arrays.stream(names.split(","))
.map(Participant::nameOf).collect(Collectors.toList()));
.map(name -> Participant.nameOf(name, sequence.getAndIncrement())).collect(Collectors.toList()));
}

public Participants(List<Participant> players) {
this.players = players;
}

public Participant getParticipantByName(String inputName) {
return validateInputName(inputName);
}

private Participant validateInputName(String inputName) {
return players.stream().filter(participant -> participant.getName().equals(inputName.trim()))
.findAny()
.orElseThrow(() -> new NotFoundException("입력하신 이름과 일치하는 참가자가 없습니다."));
}

public Participant getParticipantByPosition(int position) {
return players.stream()
.filter(player -> player.getPosition() == position)
.findAny().orElseThrow(() -> new NotFoundException("해당하는 위치의 참가자가 없습니다."));
}

public List<Participant> getParticipants() {
return Collections.unmodifiableList(players);
}
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/nextstep/ladder/domain/ResultInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nextstep.ladder.domain;

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

public class ResultInfo {

private final List<String> results;

public ResultInfo(String result, int participantCount) {
this(checkResultSize(Arrays.stream(result.split(",")).collect(Collectors.toList()), participantCount));

}

private static List<String> checkResultSize(List<String> result, int participantCount) {
checkResultAndParticipantCount(result, participantCount);
return result;
}

public ResultInfo(List<String> results) {
this.results = results;
}

private static void checkResultAndParticipantCount(List<String> result, int participantCount) {
if (result.size() != participantCount) {
throw new IllegalArgumentException("결과 갯수와 참가자 수와 다릅니다.");
}
}

public List<String> getResults() {
return results;
}

public String getResult(int position) {
return results.get(position);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.ladder.exception;

public class CanNotMoveException extends RuntimeException{
public CanNotMoveException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.ladder.exception;

public class NotFoundException extends RuntimeException{
public NotFoundException(String message) {
super(message);
}
}
Loading