Skip to content

[1,2,3단계 - 체스] 포츈(정윤성) 미션 제출합니다. #197

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

Merged
merged 62 commits into from
Mar 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7dde154
docs (README) : 1단계 기능목록 작성
unluckyjung Mar 16, 2021
18cb973
feat (Position) : position 도메인 구현
unluckyjung Mar 16, 2021
668d201
feat : 입력 좌표를 실제 좌표로 치환
unluckyjung Mar 16, 2021
931ea4c
docs(README) : 기능목록 재작성
unluckyjung Mar 18, 2021
07ef8a7
refactor : col row 로 네이밍 통일
unluckyjung Mar 18, 2021
46db8cf
feat : Pawn 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
4acb1be
feat : Rook 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
d2d3d48
refactor : 패키지 구조 변경
unluckyjung Mar 18, 2021
3e93f5d
feat : Knight 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
47bd99f
feat : Rook 초기 Col 위치 검증 로직 추가
unluckyjung Mar 18, 2021
ae22a87
feat : Bishop 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
e42c849
feat : Queen 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
eb93d2c
refactor : 패키지 구조 변경
unluckyjung Mar 18, 2021
4d11549
feat : King 생성시 팀에 따른 위치 초기화
unluckyjung Mar 18, 2021
37e9d26
feat : 타입별로 초기 ROW 좌표를 정해주며 Piece 를 생성하는 기능 추가
unluckyjung Mar 18, 2021
50cc856
feat : Board 생성하는 기능 구현
unluckyjung Mar 18, 2021
d4740c3
feat : 체스판 초기화 구현
unluckyjung Mar 18, 2021
65f6251
feat(Command) : 명령어 목록을 가지고 있는 Enum 구현
unluckyjung Mar 19, 2021
db0b509
feat(Board) : Piece 움직임 요청 기능 구현
unluckyjung Mar 19, 2021
82b89c9
feat : 목적지가 갈수 있는 위치에 포함되는지 확인하는 기능 구현
unluckyjung Mar 19, 2021
2500577
feat : 일급 컬렉션 Pieces 구현
unluckyjung Mar 19, 2021
38b9fde
feat : pawn white 팀 이동 구현
unluckyjung Mar 19, 2021
dafdb18
refactor : 예외 메시지 추가
unluckyjung Mar 21, 2021
9332cc7
feat(Pawn) : pawn 이동 구현
unluckyjung Mar 21, 2021
47babd3
refactor : Board에서 말이 맵 크기를 벗어나려고 하는지 검증
unluckyjung Mar 21, 2021
b3ebe19
feat(Rook) : Rook 이동 구현
unluckyjung Mar 21, 2021
2044845
feat(Bishop) : Bishop 이동 구현
unluckyjung Mar 21, 2021
d29f309
feat(Knight) : Knight 이동 구현
unluckyjung Mar 21, 2021
a4973a2
feat(Queen) : Queen 이동 구현
unluckyjung Mar 21, 2021
1b90dd9
feat(King) : King 이동 구현
unluckyjung Mar 21, 2021
09cf32b
feat : 턴을 번걸아가며 말을 조작하는 기능 구현
unluckyjung Mar 21, 2021
c5d6323
feat(Command) : 명령어에 따라 알맞은 기능 수행
unluckyjung Mar 21, 2021
7058cd9
test(PiecesTest) : 조회, 삭제 테스트 구현
unluckyjung Mar 21, 2021
5187175
feat : 왕이 잡히면 게임이 종료되는 기능 구현
unluckyjung Mar 21, 2021
bd7ca3b
feat(Pieces) : 왕이 살아있는지 여부 확인, 점수계산 기능 구현
unluckyjung Mar 21, 2021
b0162b5
feat : view 구현
unluckyjung Mar 21, 2021
db367e7
refactor(CommandTest) : 추가된 명령어 테스트 구현
unluckyjung Mar 21, 2021
2a1c23c
refactor : 컨벤션 적용
unluckyjung Mar 21, 2021
b49ec90
fix : 게임 종료 때 발생하는 버그 수정
unluckyjung Mar 22, 2021
9001be0
refactor : 접근 제어자 변경 및 오버라이딩을 원치 않는 메소드를 final로 제한
unluckyjung Mar 22, 2021
6485e0e
refactor : pawn 초기 이동 로직 수정
unluckyjung Mar 22, 2021
abc4b19
feat : 체스판 좌표 UI 출력 기능 구현
unluckyjung Mar 22, 2021
caa4d1b
refactor(Pieces) : 예외 메시지 변경
unluckyjung Mar 22, 2021
816d7c5
test(Piece) : 이동에 관련된 테스트 코드 추가
unluckyjung Mar 22, 2021
60393f0
docs(README) : 구현하지 못한 사항에 대해서 기능목록 분리
unluckyjung Mar 22, 2021
ed5c057
fix : 입력받는 좌표 길이가 2인지 확인하는 검증로직 추가
unluckyjung Mar 22, 2021
7ea33b6
doc(README) : 리팩토링 목록 작성
unluckyjung Mar 25, 2021
b697952
feat(OutputView) : 게임 이동 커멘드 메시지 출력
unluckyjung Mar 25, 2021
cd19b86
refactor : 게임 플레이 순서를 ChessGame 이 컨트롤하게 변경, winner를 필드값에서 제거
unluckyjung Mar 25, 2021
dba3ca6
refactor(BoardFactory) : 최초 한번만 초기화된 Board 생성 후, 새로운 Board 요청시 복사해서 전달
unluckyjung Mar 25, 2021
a02b562
refactor : Col, Row 를 현재 담당하고 있는 역할에 맞춰 Util 클래스로 변경
unluckyjung Mar 25, 2021
06c837d
refactor : 축약한 네이밍 변경
unluckyjung Mar 25, 2021
8341be6
refactor : 명령어에 따른 분기 처리를 컨트롤러에서 처리하도록 수정
unluckyjung Mar 25, 2021
d6931b3
refactor : start 입력시 새로운 체스게임 객체를 할당받도록 수정
unluckyjung Mar 25, 2021
f09e8ea
refactor : 위치를 조정하는 팩토리 메서드 추가
unluckyjung Mar 25, 2021
4ff7dc3
refactor(Position) : 클래스 변수와 인스턴스 변수 사이에 공백 생성
unluckyjung Mar 25, 2021
1a3b663
refactor : 메소드들을 중요도에 맞춰 위치 수정
unluckyjung Mar 25, 2021
28bd722
refactor : 상속을 기대하지 않는 클래스에 final 키워드 삽입
unluckyjung Mar 25, 2021
abab70e
feat : 테스트에 공통되게 사용되는 객체들을 모아두는 클래스 구현
unluckyjung Mar 25, 2021
786175c
refactor : 중복되는 기능 인터페이스로 분리, 추상메소드화
unluckyjung Mar 26, 2021
cdc3c35
refactor : Piece에게 팀을 주면 해당 팀에 해당하는 초기 위치의 Pieces를 얻어오게 수정
unluckyjung Mar 26, 2021
9e850ac
refactor : 읽기만 기대하는 인자에 대해서 final 키워드 추가
unluckyjung Mar 26, 2021
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: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ bin/
.idea
*.iws
*.iml
*.ipr
*.ipr
/src/main/java/docs/TODO.md
10 changes: 10 additions & 0 deletions src/main/java/chess/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package chess;

import chess.controller.ChessGameController;

public class App {
public static void main(String[] args) {
ChessGameController chessGameController = new ChessGameController();
chessGameController.start();
}
}
56 changes: 56 additions & 0 deletions src/main/java/chess/ChessGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package chess;

import chess.domain.Team;
import chess.domain.board.Board;
import chess.domain.board.BoardFactory;
import chess.domain.position.Position;

public final class ChessGame {
Copy link
Author

Choose a reason for hiding this comment

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

더이상 상속을 통해 기능확장을 기대하지 않는 클래스에 대해서는 메소드가 아닌 클래스에 final을 붙이게 했어요!

private final Board board;
private boolean isPlaying = true;
private Team currentTurnTeam;

public ChessGame() {
this(new BoardFactory().getBoard(), Team.WHITE);
}

public ChessGame(final Board board, final Team team) {
this.board = board;
currentTurnTeam = team;
}

public void end() {
isPlaying = false;
}

public boolean isPlaying() {
return isPlaying;
}

public Board getBoard() {
return board;
}

public final void move(final Position startPoint, final Position endPoint) {
board.move(startPoint, endPoint, currentTurnTeam);
if (board.isEnemyKingDie(currentTurnTeam)) {
end();
}
currentTurnTeam = Team.getAnotherTeam(currentTurnTeam);
Copy link
Author

Choose a reason for hiding this comment

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

원래 controller가 하고있던 턴 교체를 ChessGame이 수행하게 바꾸었어요

}

public double getScoreByTeam(final Team team) {
return board.scoreByTeam(team);
}

public boolean isKingDieEnd() {
return board.isEnemyKingDie(currentTurnTeam) || board.isEnemyKingDie(Team.getAnotherTeam(currentTurnTeam));
}

public Team winner() {
if (board.isEnemyKingDie(currentTurnTeam)) {
return currentTurnTeam;
}
return Team.getAnotherTeam(currentTurnTeam);
}
}
97 changes: 97 additions & 0 deletions src/main/java/chess/controller/ChessGameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package chess.controller;

import chess.ChessGame;
import chess.domain.Team;
import chess.domain.position.Position;
import chess.domain.util.ColumnConverter;
import chess.domain.util.RowConverter;
import chess.view.Command;
import chess.view.InputView;
import chess.view.OutputView;

import java.util.Objects;

public final class ChessGameController {
private ChessGame chessGame;

public void start() {
OutputView.printStartMessage();
run();
}

private void run() {
do {
turnExecute();
} while (Objects.nonNull(chessGame) && chessGame.isPlaying());

if (Objects.nonNull(chessGame) && chessGame.isKingDieEnd()) {
OutputView.printWinner(chessGame.winner(), chessGame.getScoreByTeam(Team.BLACK), chessGame.getScoreByTeam(Team.WHITE));
}
}

private void turnExecute() {
try {
Command command = Command.valueOf(InputView.getCommand());
commandExecute(command);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}

private void commandExecute(final Command command) {
if (Objects.isNull(chessGame) && command.equals(Command.MOVE)) {
OutputView.printNoStartMessage();
turnExecute();
return;
}
interactiveCommand(command);
unInteractiveCommand(command);
printCurrentBoard(command);
}

private void unInteractiveCommand(final Command command) {
if (command.equals(Command.START)) {
chessGame = new ChessGame();
}
if (command.equals(Command.END) && Objects.nonNull(chessGame)) {
chessGame.end();
}
}

private void interactiveCommand(final Command command) {
if (command.equals(Command.MOVE)) {
move();
}
if (command.equals(Command.STATUS)) {
OutputView.printEachTeamScore(chessGame.getScoreByTeam(Team.BLACK), chessGame.getScoreByTeam(Team.WHITE));
}
}

private void printCurrentBoard(final Command command) {
if (!command.isPrintCommand()) {
return;
}
printBoard();
}

private void move() {
String startPoint = InputView.getPoint();
String endPoint = InputView.getPoint();

Position startPosition = position(startPoint);
Position endPosition = position(endPoint);
chessGame.move(startPosition, endPosition);
}


private Position position(final String point) {
return new Position(
RowConverter.getLocation(String.valueOf(point.charAt(1))),
ColumnConverter.getLocation(String.valueOf(point.charAt(0)))
);
}

private void printBoard() {
OutputView.printBoard(chessGame.getBoard());
}
}
25 changes: 25 additions & 0 deletions src/main/java/chess/domain/Team.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package chess.domain;

import chess.domain.util.RowConverter;

public enum Team {
BLACK(RowConverter.getLocation("7")),
WHITE(RowConverter.getLocation("2"));

private final int pawnInitRow;

Choose a reason for hiding this comment

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

전체적으로 만들어둔 enum 등을 사용하는 것이 아닌 원시값으로 가지고 있으신데 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

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

ui 에 보이는것과 동일한 값을 넣어주는것을 의도해서 저렇게 해두었었는데, 지금 보니 저 도메인은 플레이어가 접근할 가능성이 없으니
enum을 사용하는것이 괜찮아보이네요


Team(final int pawnInitRow) {
this.pawnInitRow = pawnInitRow;
}

public static Team getAnotherTeam(final Team userTeam) {
if (Team.BLACK.equals(userTeam)) {
return WHITE;
}
return BLACK;
}

public boolean isInitPawn(final int row) {
return pawnInitRow == row;
}
}
48 changes: 48 additions & 0 deletions src/main/java/chess/domain/board/Board.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package chess.domain.board;

import chess.domain.Team;
import chess.domain.pieces.Piece;
import chess.domain.pieces.Pieces;
import chess.domain.position.Position;

import java.util.HashMap;
import java.util.Map;

public final class Board {
public static final int RANGE_MIN_PIVOT = 0;
public static final int RANGE_MAX_PIVOT = 7;

private final Map<Team, Pieces> board;

public Board(final Map<Team, Pieces> board) {
this.board = new HashMap<>(board);
}

public Map<Team, Pieces> toMap() {
return new HashMap<>(board);
}

public void move(final Position startPoint, final Position endPoint, final Team team) {
Pieces pieces = board.get(team);
Piece startPointPiece = pieces.getPieceByPosition(startPoint);
startPointPiece.move(this, endPoint);
}

public final Pieces piecesByTeam(final Team team) {
return board.get(team);
}

public boolean validateRange(final int row, final int col) {
return !(row < RANGE_MIN_PIVOT || row > RANGE_MAX_PIVOT || col < RANGE_MIN_PIVOT || col > RANGE_MAX_PIVOT);
}

public boolean isEnemyKingDie(final Team team) {
Pieces enemyPieces = board.get(Team.getAnotherTeam(team));
return !enemyPieces.kingAlive();
}

public double scoreByTeam(final Team team) {
Pieces pieces = board.get(team);
return pieces.calculateScore(RANGE_MIN_PIVOT, RANGE_MAX_PIVOT);
}
}
71 changes: 71 additions & 0 deletions src/main/java/chess/domain/board/BoardFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package chess.domain.board;

import chess.domain.Team;
import chess.domain.pieces.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class BoardFactory {
private final Map<Team, Pieces> board = new HashMap<>();

public BoardFactory() {
initSetting();
}

public Board getBoard() {
return new Board(board);
}

private void initSetting() {
List<Piece> black = new ArrayList<>();
List<Piece> white = new ArrayList<>();

pawnInitSetting(black, white);
rookInitSetting(black, white);
knightInitSetting(black, white);
bishopInitSetting(black, white);
queenInitSetting(black, white);
kingInitSetting(black, white);

makeBoard(black, white);
}

private void pawnInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(Pawn.getInitPawns(Team.BLACK));
white.addAll(Pawn.getInitPawns(Team.WHITE));
}

private void rookInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(Rook.getInitRooks(Team.BLACK));
white.addAll(Rook.getInitRooks(Team.WHITE));
}

private void knightInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(Knight.getInitKnights(Team.BLACK));
white.addAll(Knight.getInitKnights(Team.WHITE));
}

private void bishopInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(Bishop.getInitBishop(Team.BLACK));
white.addAll(Bishop.getInitBishop(Team.WHITE));
}

private void queenInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(Queen.getInitQueen(Team.BLACK));
white.addAll(Queen.getInitQueen(Team.WHITE));
}

private void kingInitSetting(final List<Piece> black, final List<Piece> white) {
black.addAll(King.getInitKing(Team.BLACK));
white.addAll(King.getInitKing(Team.WHITE));
}

private void makeBoard(final List<Piece> black, final List<Piece> white) {
board.put(Team.BLACK, new Pieces(black));
board.put(Team.WHITE, new Pieces(white));
}
}

63 changes: 63 additions & 0 deletions src/main/java/chess/domain/pieces/Bishop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package chess.domain.pieces;

import chess.domain.Team;
import chess.domain.board.Board;
import chess.domain.pieces.Movable.MultiMove;
import chess.domain.position.Position;
import chess.domain.util.ColumnConverter;
import chess.domain.util.RowConverter;

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

public final class Bishop extends NoKingPieces implements MultiMove {
private static final String BLACK_TEAM_ROW = "8";
private static final String WHITE_TEAM_ROW = "1";
private static final double SCORE = 3.0;
private static final int LEFT_SIDE_INIT_COL = 2;
private static final int RIGHT_SIDE_INIT_COL = 5;

private Bishop(final Team team, final Position position) {
super(position, "B", team, SCORE);
}

private Bishop(final Position position, final String initial, final Team team, final double score) {
super(position, initial, team, score);
}

public static Bishop of(final Team team, final Position position) {
return new Bishop(position, "B", team, SCORE);
}

public static Bishop of(final Team team, final int col) {
if (col != LEFT_SIDE_INIT_COL && col != RIGHT_SIDE_INIT_COL) {
throw new IllegalArgumentException("잘못된 초기 위치입니다.");
}
return new Bishop(team, getInitPosition(team, col));
}

private static Position getInitPosition(final Team team, final int col) {
if (team.equals(Team.BLACK)) {
return new Position(RowConverter.getLocation(BLACK_TEAM_ROW), col);
}
return new Position(RowConverter.getLocation(WHITE_TEAM_ROW), col);
}

public static List<Bishop> getInitBishop(final Team team) {
List<Bishop> bishops = new ArrayList<>();
ColumnConverter.getBishopInitCols().forEach((col) -> bishops.add(Bishop.of(team, col)));
return bishops;
}

@Override
public List<Position> getMovablePositions(final Board board) {
int[] rowDir = {-1, 1, -1, 1};
int[] colDir = {-1, 1, 1, -1};
return getMovablePositionsByDir(board, rowDir, colDir);
}

@Override
public boolean isMoveAble(final List<Position> movablePositions, final Board board, final int nextRow, final int nextCol) {
return isMoveAbleDir(movablePositions, board, nextRow, nextCol, getTeam());
}
}
Loading