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

1주차 미션 / 서버 1조 김경민 #16

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions src/main/java/ladder/Direction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ladder;

public enum Direction {
NONE(0),
RIGHT(1),
LEFT(-1);

private final int value;

Direction(int value) {
this.value = value;
}

}
19 changes: 19 additions & 0 deletions src/main/java/ladder/ExceptionMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ladder;

public enum ExceptionMessage {
INVALID_NATURAL_NUMBER("자연수가 아닙니다."),
INVALID_LINE_POSITION("라인 생성이 불가능한 위치 입니다."),
INVALID_POSITION("유효하지 않은 위치 입니다."),
INVALID_NUMBER_OF_PERSON("게임의 참여자 수는 1명 이상이어야 합니다.");


private final String message;

ExceptionMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}

}
27 changes: 0 additions & 27 deletions src/main/java/ladder/Ladder.java

This file was deleted.

21 changes: 21 additions & 0 deletions src/main/java/ladder/LadderCreator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ladder;

public class LadderCreator {
private final Row[] rows;

public LadderCreator(NaturalNumber numberOfRow, NaturalNumber numberOfPerson) {
rows = new Row[numberOfRow.getNum()];
for (int i = 0; i < numberOfRow.getNum(); i++) {
rows[i] = new Row(numberOfPerson);
}
}

public void drawLine(Position row, Position col) {
rows[row.getPosition()].drawLine(col);
}

public Row[] getRows() {
return rows;
}

}
15 changes: 15 additions & 0 deletions src/main/java/ladder/LadderGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ladder;

public class LadderGame {
private final LadderCreator ladderCreator;

public LadderGame(LadderCreator ladderCreator) {
this.ladderCreator = ladderCreator;
}

public int run(Position position) {
LadderRunner ladderRunner = new LadderRunner(ladderCreator.getRows());
return ladderRunner.run(position);
}

}
19 changes: 19 additions & 0 deletions src/main/java/ladder/LadderRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ladder;

public class LadderRunner {
private final Row[] rows;

// 의존성 주입(DI) 사용을 통해 필드 초기화
public LadderRunner(Row[] rows) {
this.rows = rows;
}

// 현재 포지션을 입력 받아, 마지막 위치를 표현하는 run() 메서드
public int run(Position position) {

for (int i = 0; i < rows.length; i++) {
position = rows[i].nextPosition(position);
}
return position.getPosition();
}
}
29 changes: 29 additions & 0 deletions src/main/java/ladder/NaturalNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ladder;

public class NaturalNumber {
private final int num;

// 생성자를 외부에서 호출하지 못하도록 private로 지정
private NaturalNumber(int num) {
validate(num);
this.num = num;
}
public static NaturalNumber of(int num) {
return new NaturalNumber(num);
}
public int getNum() {
return num;
}

// validate 메서드와 isNaturalNumber 메서드를 분리해, 메서드에 과도한 책임전가 X
private void validate(int num) {
if (!isNaturalNumber(num)) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_NUMBER_OF_PERSON.getMessage());
}
}

private static boolean isNaturalNumber(int num) {
return num >= 1;
}

}
42 changes: 42 additions & 0 deletions src/main/java/ladder/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ladder;

/**
* 각 행은 Node를 통해서 관리한다.
* 상속 대신 조합을 통해 클래스를 관리해보자.
*/

public class Node {
// 필드로 Direction 클래스만 갖는다. (조합 사용)
private Direction direction;

// 생성자는 private이며, direction 인스턴스를 받아 필드를 초기화한다.
private Node(Direction direction) {
this.direction = direction;
}

// 정적 팩터리 메서드 패턴
public static Node of(Direction direction) {
return new Node(direction);
}

// node의 move 메서드를 통해, 현재 위치를 입력받아, 현재 위치의 다음 위치를 반환한다.
public Position move(Position position) {
if (isRight()) {
return position.next();
}
if (isLeft()) {
return position.prev();
}
return position;
}

// 각 노드(사다리가 오른쪽을 가지는지) 방향 확인
public boolean isRight() {
return direction == Direction.RIGHT;
}

public boolean isLeft() {
return direction == Direction.LEFT;
}

}
63 changes: 63 additions & 0 deletions src/main/java/ladder/Position.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ladder;

/**
* 필드를 position만 갖는 이유가 뭘까?
* primitive type으로는 컴파일러가 의미적으로 프로그램 작성을 안내할 수 없다.
* 포장한 객체를 통해 예외 처리가 가능하다.
*/

public class Position {
private int position;

private Position(int position) {
this.position = position;
}

public int getPosition() {
return position;
}

/**
* static의 특징은 무엇일까?
* 1. 메모리에 고정적으로 할당된다.
* 2. 객체 생성 없이 사용하 수 있다.
* 3. 프로그램이 시작되면 메모리의 static 영역에 적재되고, 프로그램이 종료될 때 해제된다.
* 4. Static 메서드 내에서는 인스턴스 변수를 사용할 수 없다.
*
* from : 하나의 매개변수를 받아서 객체를 생성
* of : 여러 개의 매개 변수를 받아서 객체를 생성
*
*/

public static Position of(int position) {
validatePosition(position);
return new Position(position);
}

public Position prev() {
// 이전 위치는 현재 위치 -1인가?
return new Position(position - 1);
}

public Position next() {
return new Position(position + 1);
}

private static void validatePosition(int position) {
if(!isPosition(position)) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_POSITION.getMessage());
}
}

private static boolean isPosition(int position) {
return position >= 0;
}

public boolean isSmallerThan(int position) {
return this.position < position;
}

public boolean isBiggerThan(int position) {
return this.position > position;
}
}
96 changes: 57 additions & 39 deletions src/main/java/ladder/Row.java
Original file line number Diff line number Diff line change
@@ -1,60 +1,78 @@
package ladder;

public class Row {
private int[] row;

public Row(int numberOfPerson) {
validateNumberOfPerson(numberOfPerson);
row = new int[numberOfPerson];
// 필드로 Node[] 클래스만 갖는다. (조합 사용)
private Node[] nodes;

/**
* 각 행의 nodes를 관리해보자.
* 정적 팩터리 메서드 패턴을 통해 node 배열을 초기화하고,
* 사람의 수를 NaturalNumber를 통해 인스턴스로 받아, Node 배열을 초기화 해보자.
*
* NaturalNumber 클래스를 통해 사람의 수를 예외처리하고,
* 1개의 행의 nodes를 사람의 수로 초기화 한다.
*/

public Row(NaturalNumber numberOfPerson) {
nodes = new Node[numberOfPerson.getNum()];
for (int i = 0; i < numberOfPerson.getNum(); i++) {
nodes[i] = Node.of(Direction.NONE);
}
}

public void drawLine(int lineStartPosition) {
validateDrawLinePosition(lineStartPosition);
row[lineStartPosition] = 1;
row[lineStartPosition + 1] = -1;
// 사다리 그리기 (포지션을 입력받아 선 그리기)
public void drawLine(Position startPosition) {
validateDrawLinePosition(startPosition);
setDirectionAtPosition(startPosition, Direction.RIGHT);
setDirectionAtPosition(startPosition.next(), Direction.LEFT);
// row[lineStartPosition] = 1;
// row[lineStartPosition + 1] = -1;
}

public int nextPosition(int position) {

validatePosition(position);

if (isLeft(position)) {
return position - 1;
}
if (isRight(position)) {
return position + 1;
}

return position;
private void setDirectionAtPosition(Position startPosition, Direction direction) {
nodes[startPosition.getPosition()] = Node.of(direction);
}

private boolean isLeft(int position) {
return row[position] == -1;
/**
* 선을 그리는 위치가 유효한지 판단.
* 노드의 방향이 이미 정해진 경우를 판단하여 예외처리한다.
*/
private void validateDrawLinePosition(Position startPosition) {
if (isInvalidDrawPosition(startPosition)
|| isDuplicatedDrawPosition(startPosition)) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_LINE_POSITION.getMessage());
}
}

private boolean isRight(int position) {
return row[position] == 1;
private boolean isDuplicatedDrawPosition(Position position) {
return (nodes[position.getPosition()].isRight()
|| nodes[position.next().getPosition()].isRight()
|| nodes[position.getPosition()].isLeft());
}

private void validateNumberOfPerson(int numberOfPerson) {
if(numberOfPerson < 1) {
throw new IllegalArgumentException("게임의 참여자 수는 1명 이상이어야 합니다.");
}
public Position nextPosition(Position currentPosition) {
isInvalidNextPosition(currentPosition);
return nodes[currentPosition.getPosition()].move(currentPosition);
// if (isLeft(position)) {
// return position - 1;
// }
// if (isRight(position)) {
// return position + 1;
// }
//
// return position;
}

private void validateDrawLinePosition(int lineStartPosition) {
if(lineStartPosition < 0 || lineStartPosition >= row.length - 1 || row[lineStartPosition] == -1 || row[lineStartPosition + 1] == 1) {
throw new IllegalArgumentException("라인 생성이 불가능한 위치 입니다.");
private boolean isInvalidDrawPosition(Position position) {
if(position.isBiggerThan(nodes.length - 2) || position.isSmallerThan(0)) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_LINE_POSITION.getMessage());
}
return false;
}

private void validatePosition(int position) {
if(position >= row.length || position < 0 ) {
throw new IllegalArgumentException("유효하지 않은 위치 입니다.");
private void isInvalidNextPosition(Position position) {
if (position.isBiggerThan(nodes.length - 1) || position.isSmallerThan(0) ) {
throw new IllegalArgumentException(ExceptionMessage.INVALID_POSITION.getMessage());
}
}




}
Loading