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

πŸš€ 2단계 - 사닀리(생성) #2120

Open
wants to merge 36 commits into
base: sang5c
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f851cb7
build: java 11
sang5c Apr 2, 2024
f887f8a
docs: step2 μš”κ΅¬μ‚¬ν•­ μž‘μ„±
sang5c Apr 2, 2024
0c09d1e
feat: 사닀리 κ²Œμž„ κΈ°λ³Έ 좜λ ₯ ν˜•νƒœ μž‘μ„±
sang5c Apr 3, 2024
f6311a6
docs: μš”κ΅¬μ‚¬ν•­ 뢄석 μΆ”κ°€
sang5c Apr 6, 2024
066ce9d
build: gradle 5.0
sang5c Apr 6, 2024
1adfd82
feat: 쒌, 우 λͺ¨λ‘ 이동 κ°€λŠ₯ν•œ PointλŠ” 생성할 수 μ—†λ‹€
sang5c Apr 6, 2024
dff1072
test: PointλŠ” 쒌, 우 이동 κ°€λŠ₯ μ—¬λΆ€λ₯Ό 가진닀.
sang5c Apr 6, 2024
85f0fcc
feat: μ‚¬λžŒ 수λ₯Ό λ°›μ•„ κ°€λ‘œ 라인을 μƒμ„±ν•œλ‹€
sang5c Apr 6, 2024
ad63923
refactor: 포인트 생성 λ©”μ„œλ“œ 포인트둜 이동
sang5c Apr 6, 2024
2368cef
refactor: 랜덀 포인트 생성 λ©”μ„œλ“œλͺ… λͺ…ν™•ν•˜κ²Œ λ³€κ²½
sang5c Apr 6, 2024
7f26af3
docs: μ™„λ£Œλœ μš”κ΅¬μ‚¬ν•­ μ™„λ£Œ 처리
sang5c Apr 6, 2024
7b8e81d
feat: λž˜λ”κ²Œμž„ μ™„μ„±
sang5c Apr 6, 2024
fab1fe5
refactor: 맀직 λ¦¬ν„°λŸ΄ μƒμˆ˜λ‘œ μ‚¬μš©
sang5c Apr 6, 2024
9427f15
feat: 일급 μ»¬λ ‰μ…˜ 적용
sang5c Apr 6, 2024
6929a1f
feat: μ°Έκ°€μžλŠ” 이름을 κ°–λŠ”λ‹€
sang5c Apr 6, 2024
53309ed
refactor: LadderGame 뢄리
sang5c Apr 6, 2024
e3bdceb
refactor: domain νŒ¨ν‚€μ§€ 뢄리
sang5c Apr 6, 2024
5f53b78
test: 도메인 ν…ŒμŠ€νŠΈ μž‘μ„±
sang5c Apr 6, 2024
73d2e59
refactor: 쀑간 포인트 생성 λ©”μ„œλ“œ 뢄리
sang5c Apr 6, 2024
99c8db7
refactor: Line λ©”μ„œλ“œ 뢄리
sang5c Apr 6, 2024
d10073d
feat: μ°Έκ°€μžλŠ” 1λͺ… 이상이닀
sang5c Apr 6, 2024
e4da849
refactor: Line 생성 둜직 LineBuilder둜 뢄리
sang5c Apr 6, 2024
a241c10
feat: 이동 κ°€λŠ₯ν•œ ν¬μΈνŠΈκ°„μ— μ„œλ‘œ 이동 κ°€λŠ₯ν•˜μ§€ μ•ŠμœΌλ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€
sang5c Apr 6, 2024
9d2ef6c
feat: λ§ˆμ§€λ§‰ 포인트λ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μŒ 포인트λ₯Ό μƒμ„±ν•˜λ„λ‘ λ³€κ²½
sang5c Apr 6, 2024
82cb335
refactor: λ³€μˆ˜λͺ…, λ©”μ„œλ“œλͺ… μΌκ΄€μ„±μžˆκ³  λͺ…ν™•ν•˜κ²Œ λ³€κ²½
sang5c Apr 6, 2024
82abe22
refactor: ConsoleUtil 뢄리
sang5c Apr 7, 2024
6aaabc1
refactor: 멀버 λ³€μˆ˜ final
sang5c Apr 7, 2024
7e1e4ec
refactor: λ©”μ„œλ“œλͺ… λͺ…ν™•ν•˜κ²Œ λ³€κ²½
sang5c Apr 7, 2024
1b2b225
feat: μ‚¬μš©μž input λ°›μ•„ κ²Œμž„ μ‹€ν–‰
sang5c Apr 7, 2024
30de861
refactor: λΆˆν•„μš”ν•œ static 제거
sang5c Apr 11, 2024
439d1cc
refactor: 맀직 λ„˜λ²„ μƒμˆ˜ν™”
sang5c Apr 18, 2024
6498f49
feat: playerλŠ” λͺ‡ 번째 μžλ¦¬μΈμ§€ 확인할 수 μžˆλŠ” indexλ₯Ό κ°–λŠ”λ‹€
sang5c Apr 18, 2024
a8a84a8
feat: PointλŠ” λͺ‡ 번째 μžλ¦¬μΈμ§€ 확인할 수 μžˆλŠ” indexλ₯Ό κ°–λŠ”λ‹€
sang5c Apr 18, 2024
9ad91e8
refactor: collectingAndThen μ‚¬μš©ν•˜μ—¬ λ°”λ‘œ λ°˜ν™˜
sang5c Apr 18, 2024
9a91a2f
refactor: LineBuilderλ₯Ό Line λ‚΄λΆ€λ‘œ 이동
sang5c Apr 21, 2024
4a9ad30
refactor: Lines 생성 μ±…μž„μ„ LinesGenerator둜 뢄리
sang5c Apr 21, 2024
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
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
# 사닀리 κ²Œμž„

## 진행 방법

* 사닀리 κ²Œμž„ κ²Œμž„ μš”κ΅¬μ‚¬ν•­μ„ νŒŒμ•…ν•œλ‹€.
* μš”κ΅¬μ‚¬ν•­μ— λŒ€ν•œ κ΅¬ν˜„μ„ μ™„λ£Œν•œ ν›„ μžμ‹ μ˜ github 아이디에 ν•΄λ‹Ήν•˜λŠ” λΈŒλžœμΉ˜μ— Pull Request(μ΄ν•˜ PR)λ₯Ό 톡해 μ½”λ“œ 리뷰 μš”μ²­μ„ ν•œλ‹€.
* μ½”λ“œ 리뷰 ν”Όλ“œλ°±μ— λŒ€ν•œ κ°œμ„  μž‘μ—…μ„ ν•˜κ³  λ‹€μ‹œ PUSHν•œλ‹€.
* λͺ¨λ“  ν”Όλ“œλ°±μ„ μ™„λ£Œν•˜λ©΄ λ‹€μŒ 단계λ₯Ό λ„μ „ν•˜κ³  μ•žμ˜ 과정을 λ°˜λ³΅ν•œλ‹€.

## 온라인 μ½”λ“œ 리뷰 κ³Όμ •
* [ν…μŠ€νŠΈμ™€ μ΄λ―Έμ§€λ‘œ μ‚΄νŽ΄λ³΄λŠ” 온라인 μ½”λ“œ 리뷰 κ³Όμ •](https://github.com/nextstep-step/nextstep-docs/tree/master/codereview)

* [ν…μŠ€νŠΈμ™€ μ΄λ―Έμ§€λ‘œ μ‚΄νŽ΄λ³΄λŠ” 온라인 μ½”λ“œ 리뷰 κ³Όμ •](https://github.com/nextstep-step/nextstep-docs/tree/master/codereview)

---

## Step 2. 사닀리(생성)

### κΈ°λŠ₯ μš”κ΅¬μ‚¬ν•­

- 사닀리 κ²Œμž„μ— μ°Έμ—¬ν•˜λŠ” μ‚¬λžŒμ— 이름을 μ΅œλŒ€5κΈ€μžκΉŒμ§€ λΆ€μ—¬ν•  수 μžˆλ‹€. 사닀리λ₯Ό 좜λ ₯ν•  λ•Œ μ‚¬λžŒ 이름도 같이 좜λ ₯ν•œλ‹€.
- μ‚¬λžŒ 이름은 μ‰Όν‘œ(,)λ₯Ό κΈ°μ€€μœΌλ‘œ κ΅¬λΆ„ν•œλ‹€.
- μ‚¬λžŒ 이름을 5자 κΈ°μ€€μœΌλ‘œ 좜λ ₯ν•˜κΈ° λ•Œλ¬Έμ— 사닀리 폭도 λ„“μ–΄μ Έμ•Ό ν•œλ‹€.
- 사닀리 타기가 μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜λ €λ©΄ 라인이 κ²ΉμΉ˜μ§€ μ•Šλ„λ‘ ν•΄μ•Ό ν•œλ‹€.
- |-----|-----| λͺ¨μ–‘κ³Ό 같이 κ°€λ‘œ 라인이 κ²ΉμΉ˜λŠ” 경우 μ–΄λŠ λ°©ν–₯으둜 이동할지 κ²°μ •ν•  수 μ—†λ‹€.

### ν”„λ‘œκ·Έλž˜λ° μš”κ΅¬μ‚¬ν•­

- μžλ°” 8의 슀트림과 λžŒλ‹€λ₯Ό μ μš©ν•΄ ν”„λ‘œκ·Έλž˜λ°ν•œλ‹€.
- κ·œμΉ™ 6: λͺ¨λ“  μ—”ν‹°ν‹°λ₯Ό μž‘κ²Œ μœ μ§€ν•œλ‹€.

### μš”κ΅¬μ‚¬ν•­ 뢄석

- [X] μ°Έκ°€μžλŠ” 이름을 κ°–λŠ”λ‹€.
- [X] 이름은 μ΅œλŒ€ 5μžμ΄λ‹€.
- [X] 이름이 λΉ„μ–΄μžˆκ±°λ‚˜ 6자 이상이면 μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€.
- [ ] 사닀리
- [X] μ‚¬λ‹€λ¦¬μ˜ κ°€λ‘œ 라인을 수λ₯Ό μ„€μ •ν•  수 μžˆλ‹€. (높이)
- [X] μ‚¬λ‹€λ¦¬μ˜ μ„Έλ‘œ 라인은 μ‚¬λžŒ 수 만큼 μƒμ„±λœλ‹€. (λ„ˆλΉ„)
- [X] μ‚¬λ‹€λ¦¬μ˜ 각 κ°€λ‘œ λΌμΈμ—λŠ” μ‚¬λžŒ 수 만큼 포인트(점)κ°€ μƒμ„±λœλ‹€.
- [X] 쒌, μš°μ— ν¬μΈνŠΈκ°€ μ‘΄μž¬ν•˜λŠ” 경우 이동할 수 μžˆλ‹€.
- [X] κ°€μž₯ μ™Όμͺ½ ν¬μΈνŠΈμ—μ„œλŠ” 쒌둜 이동 λΆˆκ°€ν•˜λ‹€.
- [X] κ°€μž₯ 였λ₯Έμͺ½ ν¬μΈνŠΈμ—μ„œλŠ” 우둜 이동 λΆˆκ°€ν•˜λ‹€.
- [X] μ—°μ†μœΌλ‘œ 이동 κ°€λŠ₯ν•œ ν¬μΈνŠΈλŠ” μ‘΄μž¬ν•  수 μ—†λ‹€. -> 쒌 우 λͺ¨λ‘ 이동 κ°€λŠ₯ν•œ ν¬μΈνŠΈλŠ” μ‘΄μž¬ν•  수 μ—†λ‹€
- [ ] 포인트
- [X] 쒌, 우 λͺ¨λ‘ 이동 κ°€λŠ₯ν•œ ν¬μΈνŠΈλŠ” μ‘΄μž¬ν•  수 μ—†λ‹€. μ„Έ 가지 경우만 μ‘΄μž¬ν•œλ‹€.
- [X] 쒌 이동 λΆˆκ°€, 우 이동 λΆˆκ°€
- [X] 쒌 이동 κ°€λŠ₯, 우 이동 λΆˆκ°€
- [X] 쒌 이동 λΆˆκ°€, 우 이동 κ°€λŠ₯
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply plugin: 'java'
apply plugin: 'eclipse'

version = '1.0.0'
sourceCompatibility = 1.8
sourceCompatibility = 11
Copy link
Author

Choose a reason for hiding this comment

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

λ―Έμ…˜ λ‹€μ‹œ μ‹œμž‘ν•  땐 λ¦¬λ·°μš”μ²­μ„ 염두에 두지 μ•Šκ³  μ§„ν–‰ν•΄μ„œ μžλ°” 버전을 λ°”κΏ¨μ—ˆλŠ”λ°μš”!
ν˜Ήμ‹œ λ²„μ „λ‹€μš΄μ΄ ν•„μš”ν•˜λ©΄ 내리고 λ‹€μ‹œ μš”μ²­λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€!


repositories {
mavenCentral()
Expand Down
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Sat Apr 06 16:04:18 KST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
18 changes: 18 additions & 0 deletions src/main/java/nextstep/ladder/LadderGameApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package nextstep.ladder;

import nextstep.ladder.domain.LadderGame;
import nextstep.ladder.util.ConsoleUtil;

import java.util.List;

public class LadderGameApplication {

public static void main(String[] args) {
List<String> playerNames = ConsoleUtil.inputPlayerNames();
int height = ConsoleUtil.inputHeight();

LadderGame ladderGame = LadderGame.start(playerNames, height);

ConsoleUtil.printGameResults(ladderGame);
}
}
29 changes: 29 additions & 0 deletions src/main/java/nextstep/ladder/domain/LadderGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nextstep.ladder.domain;

import java.util.List;

public class LadderGame {

private final Players players;
private final Lines lines;

private LadderGame(final Players players, final Lines lines) {
this.players = players;
this.lines = lines;
}

public static LadderGame start(List<String> playerNames, int height) {
Players players = Players.of(playerNames);
LinesGenerator linesGenerator = new RandomLinesGenerator(players.count(), height);

return new LadderGame(players, linesGenerator.generate());
}

public Players getPlayers() {
return players;
}

public Lines getLines() {
return lines;
}
}
96 changes: 96 additions & 0 deletions src/main/java/nextstep/ladder/domain/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package nextstep.ladder.domain;

import java.util.ArrayList;
import java.util.List;

public class Line {
private static final int MIN_POINT_SIZE = 2;

private final List<Point> points;

private Line(List<Point> points) {
validate(points);
this.points = points;
}

private void validate(List<Point> points) {
validatePointsListSize(points);
validatePointMovements(points);
}

private void validatePointsListSize(List<Point> points) {
if (points == null || points.isEmpty()) {
throw new IllegalArgumentException("점이 μ—†μŠ΅λ‹ˆλ‹€.");
}

if (points.size() < MIN_POINT_SIZE) {
throw new IllegalArgumentException("점이 " + MIN_POINT_SIZE + "개 이상 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.");
}
}

private void validatePointMovements(List<Point> points) {
if (firstPoint(points).canMoveLeft() || lastPoint(points).canMoveRight()) {
throw new IllegalArgumentException("첫 μ μ—μ„œλŠ” μ™Όμͺ½μœΌλ‘œ 이동할 수 μ—†κ³ , λ§ˆμ§€λ§‰ μ μ—μ„œλŠ” 였λ₯Έμͺ½μœΌλ‘œ 이동할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}

for (int i = 0; i < points.size() - 1; i++) {
assertConsecutivePointsAreMovable(points, i);
}
}

private void assertConsecutivePointsAreMovable(List<Point> points, int i) {
if (points.get(i).canMoveRight() && !points.get(i + 1).canMoveLeft()) {
throw new IllegalArgumentException("μ—°μ†λœ μ μ—μ„œλŠ” μ„œλ‘œ 이동 κ°€λŠ₯ν•΄μ•Ό ν•©λ‹ˆλ‹€.");
}
}

private Point firstPoint(List<Point> points) {
return points.get(0);
}

private Point lastPoint(List<Point> points) {
return points.get(points.size() - 1);
}

public int width() {
return points.size();
}

public Point getPoint(int index) {
return points.stream()
.filter(point -> point.sameIndex(index))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("ν¬μΈνŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€. index: " + index));
}

static class LineBuilder {
private final List<Point> points;

public LineBuilder() {
this.points = new ArrayList<>();
}

public LineBuilder point(boolean canMoveRight) {
if (points.isEmpty()) {
points.add(Point.createLeftmost(canMoveRight));
return this;
}
points.add(lastPoint().createNext(canMoveRight));
return this;
}

public Line build() {
if (points.isEmpty()) {
throw new IllegalStateException("점이 μ—†μŠ΅λ‹ˆλ‹€.");
}

points.add(lastPoint().createRightmost());

return new Line(points);
}

private Point lastPoint() {
return points.get(points.size() - 1);
}
}
}
26 changes: 26 additions & 0 deletions src/main/java/nextstep/ladder/domain/Lines.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nextstep.ladder.domain;

import java.util.List;

public class Lines {
private final List<Line> lines;

public Lines(List<Line> lines) {
validate(lines);
this.lines = lines;
}

private void validate(List<Line> lines) {
if (lines == null || lines.isEmpty()) {
throw new IllegalArgumentException("사닀리 λ†’μ΄λŠ” 1 이상이어야 ν•©λ‹ˆλ‹€.");
}
}

public int getHeight() {
return lines.size();
}

public Line getLine(int targetHeight) {
return lines.get(targetHeight);
}
}
5 changes: 5 additions & 0 deletions src/main/java/nextstep/ladder/domain/LinesGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nextstep.ladder.domain;

public interface LinesGenerator {
Lines generate();
}
40 changes: 40 additions & 0 deletions src/main/java/nextstep/ladder/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package nextstep.ladder.domain;

public class Player {
private static final int MAX_NAME_LENGTH = 5;
private static final int MIN_INDEX = 0;

private final int index;
private final String name;

public Player(int index, String name) {
validate(index);
validate(name);
this.index = index;
this.name = name;
}

private static void validate(int index) {
if (index < MIN_INDEX) {
throw new IllegalArgumentException("μΈλ±μŠ€λŠ” " + MIN_INDEX + "보닀 μž‘μ„ 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void validate(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("이름은 λΉ„μ–΄μžˆμ„ 수 μ—†μŠ΅λ‹ˆλ‹€.");
}

if (name.length() > MAX_NAME_LENGTH) {
throw new IllegalArgumentException("이름은 " + MAX_NAME_LENGTH + "자 μ΄ν•˜μ—¬μ•Ό ν•©λ‹ˆλ‹€.");
}
}

public String getName() {
return name;
}

public boolean sameIndex(int index) {
return this.index == index;
}
}
39 changes: 39 additions & 0 deletions src/main/java/nextstep/ladder/domain/Players.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package nextstep.ladder.domain;

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

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;

public class Players {
private final List<Player> players;

private Players(List<Player> players) {
validate(players);
this.players = players;
}

private void validate(List<Player> players) {
if (players == null || players.isEmpty()) {
throw new IllegalArgumentException("μ°Έκ°€μžκ°€ μ—†μŠ΅λ‹ˆλ‹€.");
}
}

public static Players of(List<String> playerNames) {
return IntStream.range(0, playerNames.size())
.mapToObj(index -> new Player(index, playerNames.get(index)))
.collect(collectingAndThen(toList(), Players::new));
}

public int count() {
return players.size();
}

public Player getPlayer(int index) {
return players.stream()
.filter(player -> player.sameIndex(index))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("μ°Έκ°€μžκ°€ μ—†μŠ΅λ‹ˆλ‹€. index: " + index));
}
}
68 changes: 68 additions & 0 deletions src/main/java/nextstep/ladder/domain/Point.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package nextstep.ladder.domain;

import java.util.Objects;

public class Point {
private static final int MIN_INDEX = 0;

private final int index;
private final boolean left;
private final boolean right;

public Point(int index, boolean left, boolean right) {
validate(index);
validate(left, right);
this.index = index;
this.left = left;
this.right = right;
}

private void validate(int index) {
if (index < MIN_INDEX) {
throw new IllegalArgumentException("μΈλ±μŠ€λŠ” " + MIN_INDEX + "보닀 μž‘μ„ 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void validate(boolean left, boolean right) {
if (left && right) {
throw new IllegalArgumentException("쒌 우 λͺ¨λ‘ 이동 κ°€λŠ₯ν•œ Point 생성 λΆˆκ°€");
}
}

public static Point createLeftmost(boolean canMoveRight) {
return new Point(MIN_INDEX, false, canMoveRight);
}

public Point createRightmost() {
return new Point(this.index + 1, this.right, false);
}

public Point createNext(boolean canMoveRight) {
return new Point(this.index + 1, this.right, !this.right && canMoveRight);
}

public boolean canMoveLeft() {
return left;
}

public boolean canMoveRight() {
return right;
}

public boolean sameIndex(int index) {
return this.index == index;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return index == point.index && left == point.left && right == point.right;
}

@Override
public int hashCode() {
return Objects.hash(index, left, right);
}
}
Loading