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

레디 미션 제출 #23

Open
wants to merge 61 commits into
base: reddevilmidzy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
d6a2ea5
[1,2단계 - 체스] 레디(최동근) 미션 제출합니다. (#678)
reddevilmidzy Mar 26, 2024
4a0d478
docs: 기능 요구 사항 추가
reddevilmidzy Mar 27, 2024
c7d94a6
feat: 남아있는 기물의 점수 계산
reddevilmidzy Mar 27, 2024
6959778
feat: 같은 세로줄에 있는 폰은 0.5로 계산
reddevilmidzy Mar 27, 2024
f710580
feat: 진영의 점수를 출력
reddevilmidzy Mar 27, 2024
7ede4eb
refactor: controller에서 출력 메서드 분리
reddevilmidzy Mar 27, 2024
df92d83
refactor: board와 commandLine 방어적 복사
reddevilmidzy Mar 27, 2024
1c33f96
refactor: 파라미터에 final 추가
reddevilmidzy Mar 27, 2024
df7b29a
feat: king을 잡는 경우 예외 발생
reddevilmidzy Mar 27, 2024
18337a8
feat: 승리한 진영 출력
reddevilmidzy Mar 28, 2024
0735435
docs: 완료한 구현 기능 목록 수정
reddevilmidzy Mar 28, 2024
1430061
chore: db 설정
reddevilmidzy Mar 28, 2024
525bdbb
test: 이동 저장 확인 테스트
reddevilmidzy Mar 28, 2024
3f5078e
refactor: moving 클래스 스키마 변경
reddevilmidzy Mar 29, 2024
ae56760
feat: board 저장 (위치, 기물, 진영)
reddevilmidzy Mar 29, 2024
f0dbfbc
refactor: 매 테스트마다 테이블 생성 후 삭제하도록 변경
reddevilmidzy Mar 29, 2024
ccdf574
fix: 같은 줄 폰 있는 경우 점수 계산 수정
reddevilmidzy Mar 29, 2024
1e7a3db
feat: 진행중인 게임 end 입력 후 재시작시 이전 게임 실행
reddevilmidzy Mar 29, 2024
fd0debd
chore: 테이블 삭제 쿼리 변경
reddevilmidzy Mar 30, 2024
fc1d118
docs: 구현 기능 목록 수정
reddevilmidzy Mar 30, 2024
c879ac5
refactor: 현재 보드 점수 계산 메서드 리팩터링
reddevilmidzy Mar 30, 2024
b3d1c8c
feat: 게임 저장하지 않고 종료하는 명령 기능 구현
reddevilmidzy Mar 30, 2024
bbc0175
refactor: 테이블 삭제 대신 데이터만 삭제(drop -> truncate)
reddevilmidzy Mar 30, 2024
702f306
refactor: pawn이 whitePawn과 blackPawn을 직접적으로 알고 있지 않게 변경
reddevilmidzy Mar 30, 2024
6f3e9fe
refactor: db connection 획득 클래스 분리
reddevilmidzy Mar 30, 2024
c5694c3
refactor: dao 분리
reddevilmidzy Mar 30, 2024
5e2041e
refactor: whitePawn, blackPawn 나눠 처리하던거 Pawn으로 묶음
reddevilmidzy Mar 30, 2024
bd740d2
refactor: dao들을 하나의 Repository로 묶기
reddevilmidzy Mar 30, 2024
cb14f6d
feat: SQLException 커스텀 예외로 변경
reddevilmidzy Mar 31, 2024
a306cb2
refactor: moving 테이블 스키마 변경
reddevilmidzy Mar 31, 2024
a4de87d
fix: 기보 저장시 순서 바뀌는 버그 수정
reddevilmidzy Mar 31, 2024
d75190f
feat: 게임 도중에 종료시에도 진행 상황 복구
reddevilmidzy Mar 31, 2024
a3574f6
feat: id로 기보를 찾을 때 없으면 예외가 발생
reddevilmidzy Mar 31, 2024
6b89a45
refactor: 폰 점수 관련 매직 넘버 제거
reddevilmidzy Mar 31, 2024
c00b9b9
refactor: 삼항 연산자 제거
reddevilmidzy Mar 31, 2024
15265d0
refactor: piece 타입 찾는 로직 리팩터링
reddevilmidzy Mar 31, 2024
44df19a
fix: 이전 게임이 있는지 찾는 메서드 수정
reddevilmidzy Mar 31, 2024
83ec223
refactor: 게임 종료 후 로직 메서드 수정
reddevilmidzy Mar 31, 2024
90659cc
refactor: var 제거
reddevilmidzy Mar 31, 2024
6183560
style: 개행 및 사용하지 않는 메서드 제거
reddevilmidzy Mar 31, 2024
394b828
docs: 구현 기능 목록 수정
reddevilmidzy Mar 31, 2024
62e632a
docs: 도커 및 db 스키마 리드미에 추가
reddevilmidzy Mar 31, 2024
b7881ec
refactor: pieceDto가 하던 camp를 찾는 책임 분리
reddevilmidzy Mar 31, 2024
b680512
refactor: enum에서 값을 찾을 때 return 타입 변경
reddevilmidzy Mar 31, 2024
c3200b3
test: dao 및 repository 테스트 추가
reddevilmidzy Mar 31, 2024
3687181
refactor: save할 때 camp와 turn 함께 dto로 묶음
reddevilmidzy Mar 31, 2024
f21c948
test: 저장 테스트 추가
reddevilmidzy Mar 31, 2024
8e82363
fix: 제일 처음 end 입력 시에도 보드 출력 안되도록 수정
reddevilmidzy Mar 31, 2024
fc88a14
feat: 제일 처음 quit 입력 가능
reddevilmidzy Mar 31, 2024
60644ad
refactor: 메서드 분리
reddevilmidzy Mar 31, 2024
719d55a
refactor: dto 다시 객체로 변환하는 메서드 명 변경
reddevilmidzy Mar 31, 2024
a094e2f
refactor: score add 메서드 이름 plus로 변경 및 테스트 추가
reddevilmidzy Mar 31, 2024
548cfa1
refactor: db 연결 관련된 상수 위치 변경
reddevilmidzy Apr 1, 2024
616c59c
refactor: isPawn, isKing 메서드 제거
reddevilmidzy Apr 1, 2024
0f6324e
chore: drop table 쿼리 삭제
reddevilmidzy Apr 1, 2024
7b87987
refactor: 테스트를 위한 메서드 혹은 사용되지 않던 메서드 삭제
reddevilmidzy Apr 1, 2024
bfd2139
refactor: pieceType 에서 camp 인스턴스 변수 제거
reddevilmidzy Apr 1, 2024
3ade17e
refactor: dao 메서드 분리
reddevilmidzy Apr 1, 2024
54bd0e5
docs: 요구사항 및 스키마 관련 정도 바로가기 링크 추가
reddevilmidzy Apr 1, 2024
2e17f45
style: todo 주석 제거
reddevilmidzy Apr 1, 2024
c3af772
리뷰용 푸시
reddevilmidzy Apr 1, 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ out/

### VS Code ###
.vscode/

### dockder ###
docker/
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

체스 미션 저장소


### [기능 요구 사항 바로가기](https://github.com/reddevilmidzy/java-chess/blob/62e632aa09435db4f69502e663a0cc7ef78a31bb/docs/README.md)

<br>

### [product db 스키마](https://github.com/reddevilmidzy/java-chess/blob/0f6324e83c0fef95c84bd95c5dba8df742a8b613/src/main/resources0)

<br>

### [test db 스키마](https://github.com/reddevilmidzy/java-chess/blob/0f6324e83c0fef95c84bd95c5dba8df742a8b613/src/test/resources)


## 우아한테크코스 코드리뷰

- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
runtimeOnly("com.mysql:mysql-connector-j:8.3.0")
}

java {
Expand Down
18 changes: 18 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: "3.9"
services:
db:
image: mysql:8.0.28
platform: linux/x86_64
restart: always
ports:
- "13306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: chess
MYSQL_USER: user
MYSQL_PASSWORD: password
TZ: Asia/Seoul
volumes:
- ./db/mysql/data:/var/lib/mysql
- ./db/mysql/config:/etc/mysql/conf.d
- ./db/mysql/init:/docker-entrypoint-initdb.d
72 changes: 62 additions & 10 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# 체스 미션

## DB 연동

### Docker 실행하기

```bash
docker-compose -p chess up -d
```

### DB 스키마

```sql
use chess;

drop table if exists board;

create table board
(
position varchar(2) not null,
piece_type varchar(6) not null,
camp varchar(5) not null

);

drop table if exists moving;

create table moving
(
movement_id INT primary key auto_increment,
camp varchar(5) not null,
start varchar(2) not null,
destination varchar(2) not null
);

drop table if exists turn;

create table turn
(
camp varchar(5) not null,
count int not null
);
```


## 기능 요구 사항

* [x] 8 * 8 의 체스 판 생성
Expand All @@ -16,7 +59,22 @@
* [x] 기물의 이동 규칙을 벗어나는 경우 예외 발생
* [x] 현재 위치로 빈 칸을 입력받은 경우 예외 발생
* [x] 현재 턴이 아닌 기물을 이동하는 경우 예외 발생
* [x] status 기능 구현
* [x] 남아있는 기물의 점수 계산
* queen: 9
* rook: 5
* bishop 3
* knight: 2.5
* pawn: 1
* [x] 같은 세로줄에 있는 같은 pawn인 경우 0.5
* [x] 진영의 점수를 출력
* [x] 승리한 진영의 결과 확인
* [x] 킹이 잡히면 게임 종료
* [x] end 가 입력되면 프로그램 종료
* [x] 예외 시 재입력
* [x] 진행중인 게임 end 입력 후 재시작시 이전 게임 실행
* [x] quit 입력시 저장하지 않고 게임 종료
* [x] db 예외 처리

## 기물의 이동 기능

Expand All @@ -37,18 +95,12 @@

* start: 게임을 시작하는 명령어
* 게임 시작은 start 명령어만 가능하다
* end: 게임을 종료하는 명령어
* end: 게임을 저장 후 종료하는 명령어
* quit: 게임을 저장하지 않고 종료하는 명령어
* move: 게임 중 기물을 움직이는 명령어
* 게임이 시작되지 않았는데 move 명령어를 입력한다면 예외가 발생한다.
* 형식은 move [a-h1-8] [a-h1-8] 형태이고 아닐시 예외가 발생한다.


## 리팩터링

* [x] 테스트 코드 보충
* [x] 프로그래밍 요구 사항 지키기
* [x] 예외 메시지를 커스텀 예외로 만들기
* [x] 예외 시 재입력 구현하기
* status: 현재 점수를 확인하는 명령어

## 우선순위가 낮지만 구현해보고 싶은 기능

Expand All @@ -57,5 +109,5 @@
* [ ] 프로모션
* [ ] 캐슬링
* 체크 상황
* [ ] 체크 메이트면 자동으로 게임 종료
* [ ] 체크 상황이면 체크를 피하는 방향으로만 이동 가능
* [ ] log 입력시 현재까지 기보 출력
7 changes: 6 additions & 1 deletion src/main/java/application/Application.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package application;

import controller.ChessController;
import db.exception.DBException;
import java.util.Scanner;
import view.InputView;
import view.OutputView;
Expand All @@ -12,6 +13,10 @@ public static void main(String[] args) {
final OutputView outputView = new OutputView();

final ChessController chessController = new ChessController(inputView, outputView);
chessController.run();
try {
chessController.run();
} catch (DBException exception) {
outputView.printException(exception.getErrorCode());
}
}
}
17 changes: 13 additions & 4 deletions src/main/java/constant/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
package constant;

public enum ErrorCode {

INVALID_INPUT,
INVALID_STATUS,
INVALID_COMMAND,
INVALID_POSITION,
INVALID_MOVEMENT_RULE,
INVALID_PAWN_MOVEMENT,
INVALID_KING_MOVEMENT,
INVALID_BISHOP_MOVEMENT,
INVALID_KNIGHT_MOVEMENT,
INVALID_QUEEN_MOVEMENT,
INVALID_ROOK_MOVEMENT,
PIECE_EXIST_IN_ROUTE,
OWN_PIECE_EXIST_POSITION,
PIECE_DOES_NOT_EXIST_POSITION,
INVALID_CAMP_PIECE,
NO_MESSAGE;

KING_DEAD,
CONNECTION,
FAIL_SAVE,
FAIL_FIND,
FAIL_DELETE,
NO_MESSAGE
}
96 changes: 69 additions & 27 deletions src/main/java/controller/ChessController.java
Original file line number Diff line number Diff line change
@@ -1,76 +1,118 @@
package controller;

import db.Repository;
import db.dto.BoardDto;
import db.dto.MovingDto;
import db.dto.TurnDto;
import dto.ChessBoardDto;
import dto.ScoreDto;
import exception.CustomException;
import java.util.Collections;
import java.util.List;
import model.ChessBoard;
import model.Command;
import model.Board;
import model.Camp;
import model.ChessGame;
import model.Turn;
import model.command.CommandLine;
import model.status.GameStatus;
import model.status.Initialization;
import model.status.StatusFactory;
import view.InputView;
import view.OutputView;

public class ChessController {

private final InputView inputView;
private final OutputView outputView;
private final Repository repository = new Repository("chess");

public ChessController(final InputView inputView, final OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
}

public void run() {
final ChessBoard chessBoard = ChessBoard.setupStartingPosition();
outputView.printStartMessage();
GameStatus gameStatus = initGame();

final ChessGame chessGame = create();
if (gameStatus.isRunning()) {
outputView.printChessBoard(ChessBoardDto.from(chessGame));
}
while (gameStatus.isRunning()) {
printCurrentStatus(chessBoard);
gameStatus = play(gameStatus, chessBoard);
gameStatus = play(gameStatus, chessGame);
}
save(gameStatus, chessGame);
}

private void save(final GameStatus gameStatus, final ChessGame chessGame) {
if (gameStatus.isCheck() || gameStatus.isQuit()) {
repository.removeAll();
return;
}
final Board board = chessGame.getBoard();
final Camp camp = chessGame.getCamp();
final Turn turn = chessGame.getTurn();
final BoardDto boardDto = BoardDto.from(board);
final TurnDto turnDto = TurnDto.from(camp, turn);
repository.save(boardDto, turnDto);
}

private ChessGame create() {
if (repository.hasGame()) {
return repository.findGame();
}
return ChessGame.setupStartingPosition();
}

private GameStatus initGame() {
try {
return Initialization.gameSetting(getCommand());
return StatusFactory.create(readCommandLine());
} catch (final CustomException exception) {
outputView.printException(exception.getErrorCode());
return initGame();
}
}

private GameStatus play(final GameStatus gameStatus, final ChessBoard chessBoard) {
private GameStatus play(final GameStatus preStatus, final ChessGame chessGame) {
try {
return gameStatus.play(getCommand(), chessBoard);
} catch (CustomException exception) {
final CommandLine commandLine = readCommandLine();
final GameStatus status = preStatus.play(commandLine, chessGame);
saveMoving(chessGame, commandLine);
print(status, commandLine, chessGame);
return status;
} catch (final CustomException exception) {
outputView.printException(exception.getErrorCode());
return play(gameStatus, chessBoard);
return play(preStatus, chessGame);
}
}

private void printCurrentStatus(final ChessBoard chessBoard) {
outputView.printChessBoard(ChessBoardDto.from(chessBoard));
outputView.printCamp(chessBoard.getCamp());
private void saveMoving(final ChessGame chessGame, final CommandLine commandLine) {
if (commandLine.isMove()) {
final List<String> body = commandLine.getBody();
final Camp camp = chessGame.getCamp().toggle();
final MovingDto movingDto = MovingDto.from(body, camp);
repository.saveMoving(movingDto);
}
}

private List<String> getCommand() {
List<String> command = Collections.emptyList();
while (command.isEmpty()) {
command = readCommand();
private void print(final GameStatus gameStatus, final CommandLine commandLine, final ChessGame chessGame) {
if (gameStatus.isCheck()) {
outputView.printWinner(chessGame.getCamp().toString());
return;
}
if (commandLine.isStatus()) {
outputView.printScore(ScoreDto.from(chessGame));
}
if (commandLine.isStart() || commandLine.isMove()) {
outputView.printChessBoard(ChessBoardDto.from(chessGame));
}
return command;
}

private List<String> readCommand() {
private CommandLine readCommandLine() {
try {
List<String> command = inputView.readCommandList();
Command.validate(command);
return command;
} catch (CustomException exception) {
final List<String> command = inputView.readCommandList();
return CommandLine.from(command);
} catch (final CustomException exception) {
outputView.printException(exception.getErrorCode());
}
return Collections.emptyList();
return readCommandLine();
}
}
Loading