Skip to content

Commit f5393b1

Browse files
authored
고생하셨습니다.
🎉 PR 머지 완료! 🎉
1 parent 603ba16 commit f5393b1

26 files changed

+543
-141
lines changed

README.md

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,52 @@
99

1010
## 요구사항
1111

12-
- 사다리는 4x4 크기 고정
13-
- 클래스는 3개 이상의 인스턴스 변수 가질 수 없음.
14-
- 모든 엔티티 작게
12+
- 사다리의 높이와 넓이를 입력받아 생성한다.
13+
- 넓이와 높이는 2 이상 24 이하 여야한다.
14+
- 클래스는 3개 이상의 인스턴스 변수 가질 수 없다.
15+
- 모든 엔티티 작게 유지해야 한다.
1516

1617
## 구현 기능
1718

1819
### 사다리
1920

20-
- 여러 개의 라인을 가지고 있다.
21-
- 전체 구조를 나타낸다.
21+
- 여러 개의 라인을 가진다.
22+
- 전체 사다리 구조를 나타내며, 사다리가 완성될 때까지 여러 번 라인을 생성해 재시도한다.
23+
- 완성된 사다리를 반환하며, 유효하지 않으면 예외를 발생시킨다.
24+
25+
### 라인 생성기
26+
27+
- 포인트 생성기를 사용해 한 줄의 포인트들을 생성한다.
28+
- 인접 포인트 간 연결이 겹치지 않도록 제어한다.
2229

2330
### 라인
2431

25-
- 한 줄을 나타내는 포인트 들을 가진다.
26-
- 연결 상태를 관리하고 연결한다.
32+
- 한 줄을 구성하는 포인트들의 리스트를 가진다.
33+
- 각 포인트의 오른쪽 연결 상태를 관리한다.
34+
35+
### 포인트 생성기
36+
37+
- 랜덤 방식으로 연결 여부를 생성한다.
2738

2839
### 포인트
2940

30-
- 연결 여부를 판단한다.
41+
- 불변 객체로 연결 여부(오른쪽 연결)를 가진다.
42+
- 새로운 연결 상태를 생성하여 반환한다.
3143

3244
## 출력 예시
3345

3446
```text
47+
사다리의 넓이는 몇 인가요?
48+
4
49+
50+
사다리의 높이는 몇 인가요?
51+
5
3552
실행결과
3653
37-
| |-----| |
54+
|-----| |-----|
3855
|-----| |-----|
3956
| |-----| |
40-
|-----| | |
57+
| | | |
58+
| | |-----|
59+
4160
```

src/main/java/LadderApplication.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
import domain.Ladder;
2-
import strategy.PointGenerator;
3-
import strategy.RandomGenerator;
4-
import view.OutputView;
1+
import controller.LadderController;
52

63
public class LadderApplication {
74
public static void main(String[] args) {
8-
int width = 4;
9-
int height = 4;
10-
11-
PointGenerator generator = new RandomGenerator();
12-
Ladder ladder = Ladder.create(width, height, generator);
13-
14-
OutputView.printLadderResultTitle();
15-
OutputView.paintLadder(ladder);
5+
LadderController controller = new LadderController();
6+
controller.play();
167
}
178
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package controller;
2+
3+
import domain.Height;
4+
import domain.Width;
5+
import domain.dto.RequestLadder;
6+
import domain.ladder.Ladder;
7+
import domain.ladder.LadderFactory;
8+
import strategy.LineGenerator;
9+
import strategy.PointGenerator;
10+
import strategy.RandomLineGenerator;
11+
import strategy.RandomPointGenerator;
12+
import view.InputView;
13+
import view.OutputView;
14+
15+
public class LadderController {
16+
17+
public void play() {
18+
RequestLadder requestLadder = inputLadderSettings();
19+
Width width = requestLadder.toWidth();
20+
Height height = requestLadder.toHeight();
21+
22+
LineGenerator lineGenerator = createLineGenerator();
23+
LadderFactory factory = new LadderFactory();
24+
Ladder ladder = factory.draw(width, height, lineGenerator);
25+
26+
drawLadder(ladder);
27+
}
28+
29+
private RequestLadder inputLadderSettings() {
30+
String width = InputView.inputLadderWidth();
31+
String height = InputView.inputLadderHeight();
32+
return new RequestLadder(width, height);
33+
}
34+
35+
private LineGenerator createLineGenerator() {
36+
PointGenerator pointGenerator = new RandomPointGenerator();
37+
return new RandomLineGenerator(pointGenerator);
38+
}
39+
40+
private void drawLadder(final Ladder ladder) {
41+
OutputView.printLadderResultTitle();
42+
OutputView.drawLadder(ladder);
43+
}
44+
}

src/main/java/domain/Height.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package domain;
2+
3+
public record Height(
4+
int value
5+
) {
6+
7+
static final int MIN_LADDER_HEIGHT_SIZE = 2;
8+
static final int MAX_LADDER_HEIGHT_SIZE = 24;
9+
10+
public Height {
11+
validateHeightSize(value);
12+
}
13+
14+
public static Height from(final int value) {
15+
return new Height(value);
16+
}
17+
18+
private void validateHeightSize(final int value) {
19+
if (value < MIN_LADDER_HEIGHT_SIZE || MAX_LADDER_HEIGHT_SIZE < value) {
20+
throw new IllegalArgumentException(
21+
"사다리의 높이는 %s 이상 %s 이하여야 합니다.".formatted(MIN_LADDER_HEIGHT_SIZE, MAX_LADDER_HEIGHT_SIZE));
22+
}
23+
}
24+
}

src/main/java/domain/Ladder.java

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/main/java/domain/Line.java

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,21 @@
11
package domain;
22

3-
import java.util.ArrayList;
4-
import java.util.Collections;
53
import java.util.List;
6-
import strategy.PointGenerator;
74

85
public class Line {
96

10-
private final List<Point> points;
7+
final List<Point> points;
118

129
private Line(final List<Point> points) {
13-
this.points = Collections.unmodifiableList(points);
10+
this.points = List.copyOf(points);
1411
}
1512

16-
public static Line create(final int width, final PointGenerator generator) {
17-
return new Line(generatePoints(width, generator));
13+
public static Line from(final List<Point> points) {
14+
return new Line(points);
1815
}
1916

20-
/**
21-
* 주어진 너비와 PointGenerator를 바탕으로, 왼쪽에서 오른쪽 방향으로 연결된 Point 리스트를 생성한다.
22-
* 첫 번째 Point는 {@code Point.first()} 를 통해 생성되며,
23-
* 이후 Point는 이전 Point의 연결 상태를 기준으로 오른쪽으로 순차적으로 생성된다.
24-
* <p>
25-
* * 사다리는 왼쪽에서 오른쪽으로만 연결된다는 전제 하에 동작한다.
26-
27-
* @param width 사다리의 너비
28-
* @param generator 오른쪽 연결 여부를 결정하는 PointGenerator
29-
* @return 연결된 Point 리스트
30-
*/
31-
private static List<Point> generatePoints(final int width, final PointGenerator generator) {
32-
List<Point> points = new ArrayList<>();
33-
Point first = Point.first(generator.generate());
34-
points.add(first);
35-
36-
for (int i = 1; i < width; i++) {
37-
first = first.connectNext(generator.generate());
38-
points.add(first);
39-
}
40-
41-
return points;
17+
public boolean hasConnectionAt(final int index) {
18+
return points.get(index).right();
4219
}
4320

4421
public List<Point> getPoints() {

src/main/java/domain/Point.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public record Point(
44
boolean right
55
) {
66

7-
public static Point first(final boolean right) {
7+
public static Point from(final boolean right) {
88
return new Point(right);
99
}
1010

src/main/java/domain/Width.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package domain;
2+
3+
public record Width(
4+
int value
5+
) {
6+
7+
static final int MIN_LADDER_WIDTH_SIZE = 2;
8+
static final int MAX_LADDER_WIDTH_SIZE = 24;
9+
10+
public Width {
11+
validateWidthSize(value);
12+
}
13+
14+
public static Width from(final int value) {
15+
return new Width(value);
16+
}
17+
18+
private void validateWidthSize(final int value) {
19+
if (value < MIN_LADDER_WIDTH_SIZE || MAX_LADDER_WIDTH_SIZE < value) {
20+
throw new IllegalArgumentException(
21+
"사다리의 넓이는 %s 이상 %s 이하여야 합니다.".formatted(MIN_LADDER_WIDTH_SIZE, MAX_LADDER_WIDTH_SIZE));
22+
}
23+
}
24+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package domain.dto;
2+
3+
import domain.Height;
4+
import domain.Width;
5+
6+
public record RequestLadder(
7+
String width,
8+
String height
9+
) {
10+
11+
public RequestLadder {
12+
validateEmpty(width, height);
13+
}
14+
15+
private void validateEmpty(final String width, final String height) {
16+
if (width == null || width.isBlank() || height == null || height.isBlank()) {
17+
throw new IllegalArgumentException("사다리의 넓이와 높이를 입력해야 합니다.");
18+
}
19+
}
20+
21+
public Width toWidth() {
22+
try {
23+
return new Width(Integer.parseInt(width.strip()));
24+
} catch (NumberFormatException e) {
25+
throw new IllegalArgumentException("사다리의 넓이는 숫자여야 합니다.");
26+
}
27+
}
28+
29+
public Height toHeight() {
30+
try {
31+
return new Height(Integer.parseInt(height.strip()));
32+
} catch (NumberFormatException e) {
33+
throw new IllegalArgumentException("사다리의 높이는 숫자여야 합니다.");
34+
}
35+
}
36+
37+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package domain.ladder;
2+
3+
import domain.Line;
4+
import domain.Width;
5+
import java.util.List;
6+
import java.util.stream.IntStream;
7+
8+
public class Ladder {
9+
10+
private final List<Line> lines;
11+
12+
private Ladder(final List<Line> lines) {
13+
this.lines = List.copyOf(lines);
14+
}
15+
16+
public static Ladder from(final List<Line> lines) {
17+
return new Ladder(lines);
18+
}
19+
20+
public boolean isFullyConnected(final Width width) {
21+
return IntStream.range(0, width.value() - 1)
22+
.allMatch(this::isConnectedBetween);
23+
}
24+
25+
private boolean isConnectedBetween(final int index) {
26+
return lines.stream()
27+
.anyMatch(line -> line.hasConnectionAt(index));
28+
}
29+
30+
public List<Line> getLines() {
31+
return lines;
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package domain.ladder;
2+
3+
import domain.Height;
4+
import domain.Line;
5+
import domain.Width;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Optional;
9+
import java.util.stream.IntStream;
10+
import strategy.LineGenerator;
11+
12+
public class LadderFactory {
13+
14+
private static final int MAX_ATTEMPTS = 50;
15+
16+
public Ladder draw(final Width width, final Height height, final LineGenerator generator) {
17+
return findDrawableLadder(width, height, generator)
18+
.orElseThrow(() -> new IllegalArgumentException("유효한 사다리를 생성할 수 없습니다."));
19+
}
20+
21+
private Optional<Ladder> findDrawableLadder(final Width width, final Height height, final LineGenerator generator) {
22+
return IntStream.range(0, MAX_ATTEMPTS)
23+
.mapToObj(attempt -> drawLadder(width, height, generator))
24+
.filter(ladder -> ladder.isFullyConnected(width))
25+
.findFirst();
26+
}
27+
28+
private Ladder drawLadder(final Width width, final Height height, final LineGenerator lineGenerator) {
29+
List<Line> lines = new ArrayList<>();
30+
for (int i = 0; i < height.value(); i++) {
31+
lines.add(lineGenerator.generate(width.value()));
32+
}
33+
return Ladder.from(lines);
34+
}
35+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package strategy;
2+
3+
import domain.Line;
4+
5+
public interface LineGenerator {
6+
Line generate(int width);
7+
}

0 commit comments

Comments
 (0)