Skip to content

Step2 #2378

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

Open
wants to merge 11 commits into
base: kjy2844
Choose a base branch
from
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,19 @@
- Optional을 활용해 조건에 따른 반환
- Optional에서 값을 반환
- Optional에서 exception 처리

## 사다리 게임 기능 목록

1. 사용자 입력 처리
- [x] 참여자 이름 입력 받기 (쉼표로 구분)
- [x] 이름 유효성 검사 (최대 5글자)
- [x] 사다리 높이 입력 받기 (숫자)
2. 사다리 생성
- [x] 사다리 높이만큼 행 생성
- [x] 참여자 수에 맞게 열 생성
- [x] 랜덤으로 가로 연결선 생성
- [x] 가로 연결선 겹치면 안됨
3. 사다리 출력
- [x] 참여자 이름 출력 (5자 기준 정렬)
- [x] 사다리 모양 출력 ("|", "-" 사용)

16 changes: 16 additions & 0 deletions src/main/java/LadderGameApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import view.InputView;
import view.ResultView;
import domain.Ladder;
import domain.Players;


public class LadderGameApplication {

public static void main(String[] args) {
Players players = InputView.inputPlayers();
int ladderHeight = InputView.inputLadderHeight();

Ladder ladder = new Ladder(ladderHeight, players.size());
ResultView.printResult(players, ladder);
}
}
22 changes: 22 additions & 0 deletions src/main/java/domain/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
public class Ladder {

private static final Random RANDOM = new Random();

private final List<LadderRow> ladderRows = new ArrayList<>();

public Ladder(int height, int width) {
for (int i = 0; i < height; i++) {
ladderRows.add(new LadderRow(width, () -> RANDOM.nextBoolean()));
}
}
Comment on lines +13 to +17

Choose a reason for hiding this comment

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

이러면 여기에 대한 테스트가 불가할것으로 보입니다.
인터페이스를 통한 generator를 만들어서 인자로 넣는 방식을 이용하면 어떨까여?


public void forEach(Consumer<LadderRow> consumer) {
ladderRows.forEach(consumer);
}
}
35 changes: 35 additions & 0 deletions src/main/java/domain/LadderRow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package domain;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.function.Consumer;

public class LadderRow {

private final List<Boolean> columns = new ArrayList<>();

public LadderRow(int width, Supplier<Boolean> connectionFunction) {
initializeColumns(width, connectionFunction);
}

private void initializeColumns(int width, Supplier<Boolean> connectionFunction) {
boolean prevPoint = false;
for (int i = 0; i < width - 1; i++) {
boolean isConnected = determineConnection(prevPoint, connectionFunction);
columns.add(isConnected);
prevPoint = isConnected;
}
}

private boolean determineConnection(boolean prevPoint, Supplier<Boolean> connectionFunction) {
if (prevPoint) {
return false;
}
return connectionFunction.get();
}

public void forEach(Consumer<Boolean> consumer) {
columns.forEach(consumer);
}
}
24 changes: 24 additions & 0 deletions src/main/java/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package domain;

public class Player {
private final String name;

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

private void validate(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("이름은 필수입니다.");
}

if (name.length() > 5) {

Choose a reason for hiding this comment

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

상수를 통해 의미 전달을 해보시면 좋겠습니다.

throw new IllegalArgumentException("이름은 최대 5글자입니다.");
}
}

public String getName() {
return name;
}
}
31 changes: 31 additions & 0 deletions src/main/java/domain/Players.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package domain;

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

public class Players {

private final List<Player> players;

public Players(List<String> playerNames) {
if (playerNames == null) {
throw new IllegalArgumentException("플레이어가 존재하지 않습니다.");
}
this.players = playerNames.stream()
.map(Player::new)
.collect(Collectors.toList());
}
Comment on lines +11 to +18

Choose a reason for hiding this comment

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

여기 테스트가 미흡합니다.


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

public void forEach(Consumer<Player> consumer) {
players.forEach(consumer);
}

public List<Player> getPlayers() {
return players;
}
}
6 changes: 0 additions & 6 deletions src/main/java/nextstep/fp/Conditional.java

This file was deleted.

3 changes: 2 additions & 1 deletion src/main/java/nextstep/fp/Lambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

public class Lambda {
public static void printAllOld(List<Integer> numbers) {
Expand Down Expand Up @@ -39,7 +40,7 @@ public static int sumAllOverThree(List<Integer> numbers) {
return sumAll(numbers, number -> number > 3);
}

private static int sumAll(List<Integer> numbers, Conditional condition) {
private static int sumAll(List<Integer> numbers, Predicate<Integer> condition) {
int total = 0;
for (int number : numbers) {
if (condition.test(number)) {
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/nextstep/optional/ComputerStore.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nextstep.optional;

import java.util.Optional;
import nextstep.optional.Computer.Soundcard;
import nextstep.optional.Computer.USB;

Expand All @@ -21,6 +22,10 @@ public static String getVersion(Computer computer) {
}

public static String getVersionOptional(Computer computer) {
return null;
return Optional.ofNullable(computer)
.map(Computer::getSoundcard)
.map(Soundcard::getUsb)
.map(USB::getVersion)
.orElse(UNKNOWN_VERSION);
}
}
35 changes: 35 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package view;

import java.util.Scanner;
import java.util.List;
import domain.Players;
public class InputView {

private static final Scanner scanner = new Scanner(System.in);

public static Players inputPlayers() {
System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)");
return new Players(parseCommaSeparatedString(scanner.nextLine()));
}

public static int inputLadderHeight() {
System.out.println("최대 사다리 높이는 몇 개 인가요?");
return parseInt(scanner.nextLine());
}

private static int parseInt(String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("숫자를 입력해주세요.");
}
}

private static List<String> parseCommaSeparatedString(String input) {
try {
return List.of(input.split(","));
} catch (NullPointerException e) {
throw new IllegalArgumentException("쉼표(,)로 구분된 문자열을 입력해주세요.");
}
}
}
18 changes: 18 additions & 0 deletions src/main/java/view/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package view;

import domain.Ladder;
import domain.Players;

public class ResultView {
public static void printResult(Players players, Ladder ladder) {
System.out.println("실행 결과");
players.forEach(player -> System.out.printf("%-5s ", player.getName()));
System.out.println();

ladder.forEach(ladderRow -> {
System.out.print("|");
ladderRow.forEach(column -> System.out.print(column ? "-----|" : " |"));
System.out.println();
});
}
}
33 changes: 33 additions & 0 deletions src/test/java/domain/LadderRowTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package domain;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

class LadderRowTest {

@Test
@DisplayName("사다리 행의 열은 전체 너비 - 1 만큼 생성된다.")
void createColumns() {
LadderRow ladderRow = new LadderRow(5, () -> true);
AtomicInteger count = new AtomicInteger();
ladderRow.forEach(column -> count.getAndIncrement());
assertThat(count.get()).isEqualTo(4);
}

@Test
@DisplayName("사다리에서 연결된 다음 열은 연결되지 않는다.")
void adjacentConnectionsDoNotOverlap() {
LadderRow ladderRow = new LadderRow(5, () -> true);
List<Boolean> expected = List.of(true, false, true, false);

AtomicInteger index = new AtomicInteger();
ladderRow.forEach(column -> {
assertThat(column).isEqualTo(expected.get(index.getAndIncrement()));
});
}
}
14 changes: 14 additions & 0 deletions src/test/java/domain/LadderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package domain;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class LadderTest {
@Test
@DisplayName("사다리 생성")
void createLadder() {
assertThat(new Ladder(3, 4)).isNotNull();
}
}
26 changes: 26 additions & 0 deletions src/test/java/domain/PlayerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package domain;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class PlayerTest {

Choose a reason for hiding this comment

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

빈값에 대한 테스트도 필요해 보입니다.


@Test
@DisplayName("플레이어 생성")
void createPlayer() {
assertThat(new Player("홍길동")).isNotNull();
}

@Test
@DisplayName("플레이어 이름은 최대 5글자이다")
void playerNameMaxLength() {
assertThatThrownBy(() -> new Player("123456"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("이름은 최대 5글자입니다.");
}


}