Skip to content
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
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,42 @@
## 우아한테크코스 코드리뷰

- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md)

## 구현할 기능 목록
### 게임 진행
- 백이 먼저 시작한다.
- move 기물 시작위치 목적지 로 움직일 수 있다.
- ex) move P a2 a3
![img.png](img.png)
### 게임 종료
- 자신의 킹이 상대의 기물 한개 이상에 의해 공격받고 있을 때 그 상태를 "체크"라고 한다.
- 만약 체크를 막거나 피할 수 없는 상황이 된다면 자신은 체크메이트당한 것이며 경기는 체크메이트를 당한 선수의 패배로 끝난다.

### 기물 행마법 / 기물 잡는 법
#### 킹 (K, k)
- 상하좌우, 대각선 방향으로 각각 1칸씩만 움직일 수 있다. 1 1경기마다 각 선수는 단 1번 "캐슬링"이라는 특별 행마를 할 수 있다.
#### 퀸 (Q, q)
- 상하좌우, 대각선 방향으로 기물이 없는 칸에 한해서 칸수의 제한 없이 움직일 수 있다.
#### 룩 (R, r)
- 상하좌우 방향으로 기물이 없는 칸에 한해서 칸수의 제한 없이 움직일 수 있다. 룩은 캐슬링을 할 때 따라 움직인다.
#### 비숍 (B, b)
- 대각선 방향으로 기물이 없는 칸에 한해서 칸수의 제한 없이 움직일 수 있다.
#### 나이트 (N, n)
- 수직 방향으로 한칸 움직인 후 수평 방향으로 두칸 움직이거나 수직 방향으로 두칸 움직인 후 수평 방향으로 한칸 움직인다.
- 나이트는 유일하게 다른 기물을 넘어다닐 수 있다.
#### 폰 (P, p)
- 행마법과 기물을 잡는 법이 다른 유일한 기물이다.
- 바로 앞의 칸이 비어 있다면 앞으로 한 칸 전진할 수 있다.(바로 앞에 상대의 기물이 있어도 잡을 수 없다.)
- 경기중 단 한번도 움직이지 않은 폰은 바로 앞의 두칸이 비어 있을 때 두칸 전진할 수 있다.(한칸만 전진해도 된다.)
- 폰은 앞쪽으로만 움직이며 절대 뒤쪽으로 행마하지 않는다.
- 폰은 대각선 방향으로 바로 앞에 위치한 기물을 잡을 수 있다.(대각선 방향으로 바로 앞에 위치한 칸이 비어 있더라도 그곳으로 전진할 수 없다.)

#### 기타
- 폰을 제외한 기물들은 행마법과 기물 잡는 법이 동일하다.
- 앙파상은 고려하지 않는다.


### 고려할 수 있는 규칙들 (현재 적용 X)
- 캐슬링
- 프로모션
- 앙파상
Binary file added img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/main/java/chess/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package chess;

import chess.controller.ChessController;
import chess.domain.ChessBoard;
import chess.view.InputView;
import chess.view.OutputView;

public class Application {
public static void main(String[] args) {
InputView inputView = new InputView();
OutputView outputView = new OutputView();

ChessController chessController = new ChessController(inputView, outputView);
chessController.play();
}
}
66 changes: 66 additions & 0 deletions src/main/java/chess/controller/ChessController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package chess.controller;

import chess.domain.ChessBoard;
import chess.domain.Column;
import chess.domain.Position;
import chess.domain.Row;
import chess.domain.game.ChessGame;
import chess.domain.game.WhiteTurn;
import chess.view.InputView;
import chess.view.OutputView;

public class ChessController {
private final InputView inputView;
private final OutputView outputView;

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

public void play() {
ChessBoard board = ChessBoard.createInitialBoard();
outputView.displayBoard(board);

ChessGame game = new ChessGame(new WhiteTurn(board));

while (!game.isFinished()) {
playTurn(game, board);
}

}

private void playTurn(ChessGame game, ChessBoard board) {
progressWithReturn(() -> {
String[] command = inputView.readMoveCommand(game.getTurnColor().getTeamName());
String startInput = command[0];
String targetInput = command[1];

Position start = stringToPosition(startInput);
Position target = stringToPosition(targetInput);

game.move(start, target);
outputView.displayBoard(board);
});
}

private void progressWithReturn(Runnable runnable) {
while(true) {
try {
runnable.run();
} catch (Exception e) {
System.out.println("[Error] " + e.getMessage());
}
}
}

private Position stringToPosition(String input) {
char col = input.charAt(0);
Column column = Column.from(col);
char rowChar = input.charAt(1);
int rowNum = Integer.parseInt(String.valueOf(rowChar));
Row row = Row.from(rowNum);

return new Position(row, column);
}
}
91 changes: 91 additions & 0 deletions src/main/java/chess/domain/ChessBoard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package chess.domain;

import chess.domain.piece.Bishop;
import chess.domain.piece.EmptyPiece;
import chess.domain.piece.King;
import chess.domain.piece.Knight;
import chess.domain.piece.Pawn;
import chess.domain.piece.Piece;
import chess.domain.piece.Queen;
import chess.domain.piece.Rook;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ChessBoard {
private final Map<Position, Piece> board;

public ChessBoard(Map<Position, Piece> board) {
this.board = board;
}

public static ChessBoard createInitialBoard() {
Map<Position, Piece> piecePositionInfo = new HashMap<>();
for (Column col : Column.values()) {
piecePositionInfo.put(new Position(Row.TWO, col), new Pawn(TeamColor.WHITE));
}
piecePositionInfo.put(new Position(Row.ONE, Column.A), new Rook(TeamColor.WHITE));
piecePositionInfo.put(new Position(Row.ONE, Column.H), new Rook(TeamColor.WHITE));

piecePositionInfo.put(new Position(Row.ONE, Column.B), new Knight(TeamColor.WHITE));
piecePositionInfo.put(new Position(Row.ONE, Column.G), new Knight(TeamColor.WHITE));

piecePositionInfo.put(new Position(Row.ONE, Column.C), new Bishop(TeamColor.WHITE));
piecePositionInfo.put(new Position(Row.ONE, Column.F), new Bishop(TeamColor.WHITE));

piecePositionInfo.put(new Position(Row.ONE, Column.D), new Queen(TeamColor.WHITE));

piecePositionInfo.put(new Position(Row.ONE, Column.E), new King(TeamColor.WHITE));

// 흑 팀
for (Column col : Column.values()) {
piecePositionInfo.put(new Position(Row.SEVEN, col), new Pawn(TeamColor.BLACK));
}

piecePositionInfo.put(new Position(Row.EIGHT, Column.A), new Rook(TeamColor.BLACK));
piecePositionInfo.put(new Position(Row.EIGHT, Column.H), new Rook(TeamColor.BLACK));

piecePositionInfo.put(new Position(Row.EIGHT, Column.B), new Knight(TeamColor.BLACK));
piecePositionInfo.put(new Position(Row.EIGHT, Column.G), new Knight(TeamColor.BLACK));

piecePositionInfo.put(new Position(Row.EIGHT, Column.C), new Bishop(TeamColor.BLACK));
piecePositionInfo.put(new Position(Row.EIGHT, Column.F), new Bishop(TeamColor.BLACK));

piecePositionInfo.put(new Position(Row.EIGHT, Column.D), new Queen(TeamColor.BLACK));

piecePositionInfo.put(new Position(Row.EIGHT, Column.E), new King(TeamColor.BLACK));

return new ChessBoard(piecePositionInfo);
}


public Piece findPieceBy(Position position) {
return board.getOrDefault(position, EmptyPiece.getInstance());
}


public void move(Position start, Position target) {
Piece piece = findPieceBy(start);

boolean availablePath = piece.availablePath(start, target);
if (!availablePath) {
throw new IllegalArgumentException("이동할 수 없는 위치입니다.");
}

List<Position> routes = piece.findAllRouteToTarget(start, target);
List<Piece> piecesOnRoute = routes.stream()
.map(this::findPieceBy)
.toList();

boolean canMove = piece.canMove(piecesOnRoute, start, target);

if (!canMove) {
throw new IllegalArgumentException("이동할 수 없는 위치입니다.");
}

board.remove(start);
board.put(target, piece);

piece.incrementMoveCount();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package chess;
package chess.domain;

public enum Color {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
package chess;
package chess.domain;

import java.util.Arrays;

public enum Column {

A,
B,
C,
D,
E,
F,
G,
H;
A(1, 'a'),
B(2, 'b'),
C(3, 'c'),
D(4, 'd'),
E(5, 'e'),
F(6, 'f'),
G(7, 'g'),
H(8, 'h');

private final int value;
private final char charValue;

Column(int value, char charValue) {
this.value = value;
this.charValue = charValue;
}

public static Column from(int value) {
return Arrays.stream(Column.values())
.filter(col -> col.value == value)
.findAny()
.orElseThrow();
}

public static Column from(char charValue) {
return Arrays.stream(Column.values())
.filter(col -> col.charValue == charValue)
.findAny()
.orElseThrow();
}

public boolean isFarLeft() {
return ordinal() == 0;
Expand Down Expand Up @@ -50,4 +74,9 @@ public Column moveRight(final int step) {

throw new IllegalStateException("움직일 수 없는 위치입니다.");
}

public int intValue() {
return value;
};

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package chess;
package chess.domain;

public enum Movement {
UP(0, 1),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package chess;
package chess.domain;

public record Position(
Column column,
Expand Down Expand Up @@ -167,4 +167,31 @@ public Position moveHorizontal(final int step) {
}
return this;
}

public boolean onStraight(Position other) {
return this.row() == other.row() || this.column == other.column;
}

public boolean onSameRow(Position other) {
return this.row == other.row();
}

public boolean onSameColumn(Position other) {
return this.column == other.column;
}

public boolean onDiagonal(Position other) {
int rowDiff = Math.abs(this.row().intValue() - other.row().intValue());
int colDiff = Math.abs(this.column.intValue() - other.column.intValue());

return rowDiff == colDiff;
}

public int rowValue() {
return this.row().intValue();
}

public int colValue() {
return this.column.intValue();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
package chess;
package chess.domain;

import java.util.Arrays;

public enum Row {

EIGHT,
SEVEN,
SIX,
FIVE,
FOUR,
THREE,
TWO,
ONE;
EIGHT(8),
SEVEN(7),
SIX(6),
FIVE(5),
FOUR(4),
THREE(3),
TWO(2),
ONE(1);

private final int value;

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

public static Row from(int value) {
return Arrays.stream(Row.values())
.filter(row -> row.value == value)
.findAny()
.orElseThrow();
}

public boolean isTop() {
return ordinal() == 0;
Expand Down Expand Up @@ -50,4 +65,8 @@ public Row moveDown(final int step) {

throw new IllegalStateException("움직일 수 없는 위치입니다.");
}

public int intValue() {
return value;
};
}
18 changes: 18 additions & 0 deletions src/main/java/chess/domain/TeamColor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package chess.domain;

public enum TeamColor {
WHITE("백팀"),
BLACK("흑팀"),
NONE("X"),
;

private final String teamName;

TeamColor(String teamName) {
this.teamName = teamName;
}

public String getTeamName() {
return teamName;
}
}
Loading