Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
ff4f19d
feat: remove web dependency
woowahan-neo Mar 13, 2023
1bab9ff
feat: add example for functional programming api example
woowahan-neo Mar 13, 2023
98598c0
chore: change package
woowahan-neo Mar 13, 2023
1dd0f93
docs: 구현 기능 목록 정리
woo-chang Mar 14, 2023
a762eb2
feat: 흑과 백 생성
woo-chang Mar 14, 2023
1610552
feat: a부터 h까지 인덱스를 갖는 세로줄 생성
woo-chang Mar 14, 2023
20539aa
feat: 1부터 8까지 인덱스를 갖는 가로줄 생성
woo-chang Mar 14, 2023
295abff
feat: 검은색인지 확인하는 기능 구현
woo-chang Mar 14, 2023
d721903
feat: 기물에서 검은색인지 확인하는 기능 구현
woo-chang Mar 14, 2023
279523e
feat: 체스 기물 구현
woo-chang Mar 14, 2023
a244af0
refactor: 도메인 패키지 분리
woo-chang Mar 14, 2023
b94e60c
feat: 같은 칸인지 확인하는 기능 구현
woo-chang Mar 14, 2023
f8c8cfc
feat: 기물 위치 초기화
woo-chang Mar 15, 2023
a3464a7
feat: 게임 시작/종료 여부 입력 기능 구현
woo-chang Mar 15, 2023
0018acb
feat: 체스 실행명령 상태 구현
woo-chang Mar 15, 2023
85cd37d
feat: 게임 시작 문구 출력
woo-chang Mar 15, 2023
83ce04a
feat: 특정 칸에 존재하는 기물 확인
woo-chang Mar 15, 2023
c3bd497
feat: 체스판 출력
woo-chang Mar 15, 2023
7f968ee
refactor: 패키지명 수정
woo-chang Mar 15, 2023
a94dbb4
feat: 파일 위치(이전, 다음, 거리) 계산 기능 구현
woo-chang Mar 15, 2023
b865ae3
feat: 랭크 위치(이전, 다음, 거리) 계산 기능 구현
woo-chang Mar 15, 2023
ff8bc45
feat: 방향 벡터(다음 파일, 다음 랭크, 방향 확인) 기능 구현
woo-chang Mar 15, 2023
8ccc18f
feat: 룩이 움직이는 경로 구하는 기능 구현
woo-chang Mar 15, 2023
09db9cc
feat: 비숍이 움직이는 경로 구하는 기능 구현
woo-chang Mar 15, 2023
e589479
feat: 퀸이 움직이는 경로 구하는 기능 구현
woo-chang Mar 15, 2023
b4fe033
feat: 나이트가 움직이는 경로 구하는 기능 구현
woo-chang Mar 15, 2023
8933b75
feat: 킹이 움직이는 경로 구하는 기능 구현
woo-chang Mar 15, 2023
7e4d664
feat: 이동 경로로 이동할 수 있는지 확인
woo-chang Mar 16, 2023
cfa6f6a
feat: 폰이 움직이는 경로 확인
woo-chang Mar 16, 2023
72fcb86
feat: 폰이 이동 경로로 이동할 수 있는지 확인
woo-chang Mar 16, 2023
1f57caa
feat: 체스보드에서 기물 위치 업데이트
woo-chang Mar 16, 2023
8278add
refactor: 예외 메시지 수정
woo-chang Mar 16, 2023
50440a5
feat: 폰인지 확인하는 기능 구현
woo-chang Mar 16, 2023
98e5b26
refactor: Optional 반환하도록 수정
woo-chang Mar 16, 2023
3918940
feat: 기물 이동
woo-chang Mar 16, 2023
8c20f4a
refactor: 게임 시작 문구 수정
woo-chang Mar 16, 2023
1d11b77
feat: 체스 게임 구현 완료
woo-chang Mar 16, 2023
b6ee99a
feat: 체스 재입력 기능 구현
woo-chang Mar 17, 2023
727d999
feat: 람다, 스트림 미션 구현
woo-chang Mar 17, 2023
334d8e8
refactor: 모든 테스트에 한글 메서드명을 위한 어노테이션 추가
woo-chang Mar 18, 2023
03c3e84
refactor: 불변 Map을 생성하도록 수정
woo-chang Mar 18, 2023
0e3476e
refactor: static 키워드 사용
woo-chang Mar 18, 2023
86451fb
refactor: Character -> char 수정
woo-chang Mar 18, 2023
47cf4bc
refactor: 변수명 수정
woo-chang Mar 18, 2023
0c5feb5
refactor: 보일러 플레이트 코드가 아래에 위치하도록 수정
woo-chang Mar 18, 2023
d86af18
refactor: 사용하지 않는 코드 삭제
woo-chang Mar 18, 2023
eb37ed2
refactor: Optional을 받는 시점에 처리하도록 수정
woo-chang Mar 18, 2023
661e1e5
feat: 같은 색인지 판단하는 기능 구현
woo-chang Mar 18, 2023
55d8bce
refactor: dto 패키지 controller -> view 수정
woo-chang Mar 18, 2023
04af044
feat: Turn에 알맞은 기물이 움직이는 기능 구현
woo-chang Mar 18, 2023
6f81b3b
refactor: 생성자 주입으로 수정
woo-chang Mar 18, 2023
ca97f14
refactor: 메서드 순서 수정
woo-chang Mar 18, 2023
153a5d4
refactor: 가독성을 위한 코드 수정
woo-chang Mar 18, 2023
adaee92
refactor: 불필요한 import 제거 및 컨벤션 수정
woo-chang Mar 18, 2023
7910ae9
refactor: 도메인 의미에 맞게 x,y -> file,rank 수정
woo-chang Mar 18, 2023
0d0e5f4
feat: SquareFixture 생성
woo-chang Mar 18, 2023
65e4c3d
refactor: Board -> BoardFactory 보드 생성 역할 수정
woo-chang Mar 18, 2023
8f6d9a5
refactor: 각 기물에 맞는 전략을 가지도록 수정
woo-chang Mar 18, 2023
b8237f4
refactor: 게임 상태에 따른 커맨드 패턴 적용
woo-chang Mar 18, 2023
f63f543
refactor: 메서드 순서 수정
woo-chang Mar 18, 2023
9d9f51f
docs: 요구사항 명세서 수정
woo-chang Mar 18, 2023
932d774
refactor: 함수형 인터페이스 어노테이션 사용
woo-chang Mar 19, 2023
abdb43c
refactor: 개행 코드 컨벤션 수정
woo-chang Mar 20, 2023
951b32d
refactor: 용도에 알맞은 변수명으로 수정
woo-chang Mar 20, 2023
b0eb44c
refactor: 사용되지 않는 주석 제거
woo-chang Mar 20, 2023
c015026
refactor: 의미를 잘 나타내는 메서드명으로 수정
woo-chang Mar 20, 2023
c986ac9
refactor: 사용하지 않는 TestPiece 제거
woo-chang Mar 20, 2023
e2eeee0
refactor: vector 패키지 수정
woo-chang Mar 20, 2023
932f1fe
refactor: 동일 전략은 공통화하도록 수정
woo-chang Mar 21, 2023
584a958
feat: 기물에서 책임을 다하기 위해 BoardSnapShot 구현
woo-chang Mar 21, 2023
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
3 changes: 0 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ repositories {
}

dependencies {
implementation 'com.sparkjava:spark-core:2.9.3'
implementation 'com.sparkjava:spark-template-handlebars:2.7.1'
implementation 'ch.qos.logback:logback-classic:1.2.10'
Comment on lines -12 to -14

Choose a reason for hiding this comment

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

이 부분이 변경된 이유가 있나욥><
큰 이유가 없다면, 변경되지 않았어도 좋을 것 같아욥><!

Copy link
Author

Choose a reason for hiding this comment

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

헉 건들이지 않았던 것 같은데 무슨일이죠 🤔

testImplementation 'org.assertj:assertj-core:3.22.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}
Expand Down
93 changes: 93 additions & 0 deletions src/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
## 도메인 객체 그래프

```mermaid
graph TD
ChessController --> InputView
ChessController --> OutputView
ChessController --> ExecuteState
ChessController --> ChessGame
ChessGame --> Board
Square --> File
Square --> Rank
BoardFactory --> Board
Board --> Square
Board --> PIECE
PIECE --> Color
PIECE --> Strategy
subgraph PIECE
direction BT
Pawn -.-> Piece
Rook -.-> Piece
Bishop -.-> Piece
Knight -.-> Piece
Queen -.-> Piece
King -.-> Piece
end
```

## 구현 기능 목록
Copy link
Member

Choose a reason for hiding this comment

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

구현 목록이 깔끔해서 좋은 것 같아!


### 체스 게임

- [x] 기물을 이동시킨다.

### 체스 보드

- [x] 체스 기물 위치를 알고 있다.
- [x] 특정 칸에 존재하는 기물을 확인한다.
- [x] 이동 경로로 이동할 수 있는지 확인한다.
- [x] 폰이 이동 경로로 이동할 수 있는지 확인한다.
- [x] 기물 위치를 업데이트한다.

### 체스 칸

- 세로줄 (File)
- [x] 왼쪽부터 a ~ h이다.
- [x] [예외사항] 존재하지 않는 인덱스라면 예외를 던진다.
- [x] 파일 간 거리를 계산한다.
- [x] 다음 파일을 반환한다.
- [x] 이전 파일을 반환한다.
- 가로줄 (Rank)
- [x] 아래부터 1 ~ 8이다.
- [x] [예외사항] 존재하지 않는 인덱스라면 예외를 던진다.
- [x] 랭크 간 거리를 계산한다.
- [x] 다음 랭크를 반환한다.
- [x] 이전 랭크를 반환한다.

### 체스 기물

- 여러 가지 기물이 존재한다.
-
-
- 나이트
- 비숍
-
-
- 색을 가진다.
- [x] 흑과 백이 존재한다.
- [x] 검은색인지 확인한다.
- [x] 같은 색인지 확인한다.
- [x] 움직이는 경로를 반환한다.
- [x] 폰인지 확인한다.

### 방향 벡터

- [x] 움직이려는 방향으로 갈 수 있는지 확인한다.
- [x] 방향의 다음 파일을 반환한다.
- [x] 방향의 다음 랭크를 반환한다.

### 입력

- [x] 게임 실행 명령을 입력한다.

### 출력

- [x] 게임 시작 문구를 출력한다.
- [x] 체스판을 출력한다.
- [x] 에러 메시지를 출력한다.
14 changes: 14 additions & 0 deletions src/main/java/chess/ChessApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package chess;

import chess.controller.ChessController;
import chess.domain.ChessGame;
import chess.domain.board.BoardFactory;

public class ChessApplication {
public static void main(String[] args) {
final ChessController chessController = new ChessController(
new ChessGame(BoardFactory.create())
);
chessController.run();
}
}
22 changes: 0 additions & 22 deletions src/main/java/chess/WebApplication.java

This file was deleted.

104 changes: 104 additions & 0 deletions src/main/java/chess/controller/ChessController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package chess.controller;

import static chess.controller.ExecuteState.END;
import static chess.controller.ExecuteState.INIT;
import static chess.controller.ExecuteState.MOVE;
import static chess.controller.ExecuteState.START;

import chess.domain.ChessGame;
import chess.domain.board.Square;
import chess.view.InputView;
import chess.view.OutputView;
import chess.view.dto.ChessBoardDto;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class ChessController {

private static final InputView inputView = new InputView();
private static final OutputView outputView = new OutputView();
Comment on lines +19 to +20
Copy link
Member

Choose a reason for hiding this comment

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

여기서 생성하신 이유가 있나욥?

Copy link
Author

@woo-chang woo-chang Mar 20, 2023

Choose a reason for hiding this comment

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

클래스 필드가 늘어나는 것도 막을 수 있고, 뷰 자체로 상태를 가지지 않기에 static으로 둬도 괜찮다고 판단하였습니다!


private final ChessGame chessGame;
private ExecuteState executeState = INIT;
private final Map<ExecuteState, Consumer<List<String>>> actions = Map.of(
START, this::start,
MOVE, this::move,
END, this::end
);

public ChessController(final ChessGame chessGame) {
this.chessGame = chessGame;
}

public void run() {
outputView.printStartMessage();
while (executeState != END) {
playChessGame();
Comment on lines +35 to +37
Copy link
Member

Choose a reason for hiding this comment

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

that's cooooool

}
}

private void playChessGame() {
try {
final List<String> commands = inputView.readExecuteCommands();
final ExecuteState executeState = readExecuteState(commands);
actions.get(executeState).accept(commands);
} catch (IllegalArgumentException e) {
outputView.printErrorMessage(e.getMessage());
}
}

private ExecuteState readExecuteState(final List<String> commands) {
validateCommands(commands);
return ExecuteState.from(commands.get(0));
Copy link
Member

Choose a reason for hiding this comment

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

매직넘버들 빼주시면 좋을 것 같아욥~!

Copy link
Author

Choose a reason for hiding this comment

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

좋은데요 🏎️

}

private void validateCommands(final List<String> commands) {
if (commands.size() == 0) {
throw new IllegalArgumentException("게임 실행을 위해서는 명령 입력이 필요합니다.");
}
}

private void start(final List<String> commands) {
validateForNotMove(commands);
validateInit();
executeState = START;
outputView.printChessBoard(ChessBoardDto.from(chessGame));
}

private void end(final List<String> commands) {
validateForNotMove(commands);
executeState = END;
}

private void move(final List<String> commands) {
validateForMove(commands);
validateStart();
chessGame.move(Square.from(commands.get(1)), Square.from(commands.get(2)));
outputView.printChessBoard(ChessBoardDto.from(chessGame));
}

private static void validateForNotMove(final List<String> commands) {
if (commands.size() != 1) {
throw new IllegalArgumentException("실행 명령만 정확히 입력이 필요합니다.");
}
}

private void validateInit() {
if (executeState != INIT) {
throw new IllegalArgumentException("게임 시작은 처음 상태일때만 가능합니다.");
}
}

private void validateStart() {
if (executeState != START) {
throw new IllegalArgumentException("게임 진행중일때만 가능합니다.");
}
}

private static void validateForMove(final List<String> commands) {
if (commands.size() != 3) {
throw new IllegalArgumentException("이동을 위해서는 예시와 같이 입력이 필요합니다. 예) move b2 b3");
}
}
}
20 changes: 20 additions & 0 deletions src/main/java/chess/controller/ExecuteState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package chess.controller;

import java.util.Arrays;

public enum ExecuteState {

INIT,
START,
MOVE,
END,
;

public static ExecuteState from(final String input) {
return Arrays.stream(ExecuteState.values())
.filter(executeState -> executeState != INIT)
.filter(executeState -> executeState.name().toLowerCase().equals(input))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 실행 명령입니다."));
}
}
49 changes: 49 additions & 0 deletions src/main/java/chess/domain/ChessGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package chess.domain;

import static java.lang.String.format;

import chess.domain.board.Board;
import chess.domain.board.Square;
import chess.domain.piece.Color;
import chess.domain.piece.Piece;
import java.util.List;

public class ChessGame {

private final Board board;
private Color turnColor = Color.WHITE;

public ChessGame(final Board board) {
this.board = board;
}

public void move(final Square source, final Square destination) {
final Piece piece = board.findPieceOf(source)
.orElseThrow(() -> new IllegalArgumentException("움직일 기물이 존재하지 않습니다."));
validateTurn(piece);
moveToDestination(piece, source, destination);
nextTurn();
}

private void validateTurn(final Piece piece) {
if (!piece.isSameColor(turnColor)) {
throw new IllegalArgumentException(format("%s의 차례입니다.", turnColor));
}
}

private void moveToDestination(final Piece piece, final Square source, final Square destination) {
final List<Square> route = piece.findRoute(source, destination);
if (!piece.isMovable(source, route, board.getBoardSnapShot())) {
throw new IllegalArgumentException("움직일 수 없는 위치입니다.");
}
board.move(source, destination);
}

private void nextTurn() {
turnColor = turnColor.reverse();
}

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

import chess.domain.piece.Piece;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

public class Board {

private final Map<Square, Piece> board;

public Board(final Map<Square, Piece> board) {
this.board = board;
}

public Optional<Piece> findPieceOf(final Square square) {
Copy link
Member

Choose a reason for hiding this comment

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

optional을 반환하는 이유가 뭐죠? 여기서 예외를 처리하는 것이 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

view에 없는 위치를 표현하기 위해 메서드 자체적으로 예외는 발생시키지 않았습니다

return Optional.ofNullable(board.get(square));
}

public void move(final Square source, final Square destination) {
board.put(destination, board.remove(source));
}

public BoardSnapShot getBoardSnapShot() {
return BoardSnapShot.from(board);
}

public Map<Square, Piece> getBoard() {
return Collections.unmodifiableMap(board);
}
}
Loading