-
Notifications
You must be signed in to change notification settings - Fork 0
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
켈리 3 & 4 제출 합니다. #25
base: kelly6bf
Are you sure you want to change the base?
켈리 3 & 4 제출 합니다. #25
Changes from all commits
f96ec49
7367e53
30a24f4
227468e
1587af3
a83fbb9
829536b
4ccb6b0
1e00559
0cc9b84
2a0e6d1
71b1478
5fa072e
bd27350
215a75a
2c6e406
f408e3e
7a47024
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
|
||
Co-authored-by: Hyunguk Ryu <[email protected]> | ||
|
||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
## 프로그램 흐름 | ||
|
||
- 사용자로부터 게임 시작 여부를 입력받는다. | ||
- `start`를 입력받으면 게임을 생성하고 초기 체스판의 상태를 출력한다. | ||
- `end`를 입력받으면 프로그램을 종료한다. | ||
- 기물 이동 여부를 입력받는다. | ||
- `move b2 b4`와 같이 입력받으면 `b2`에 존재하는 기물을 `b4`로 이동시킨다. | ||
- `end`를 입력받으면 프로그램을 종료한다. | ||
|
||
## 도메인별 기능 | ||
|
||
### Piece | ||
|
||
- [x] 출발지 & 목적지 정보를 토대로 기물이 이동할 수 있는지 검사한다. | ||
- [x] 입력받은 색상을 토대로 자신의 적 여부를 반환한다. | ||
|
||
#### Rook | ||
|
||
- 상/하/좌/우 거리 제한 없이 이동 가능 | ||
- 비었거나 적 기물이 존재하는 칸으로만 이동 가능 | ||
- 이동 경로에 기물이 존재하면 이동 불가 | ||
|
||
#### Bishop | ||
|
||
- 대각선 방향 거리 제한 없이 이동 가능 | ||
- 비었거나 적 기물이 존재하는 칸으로만 이동 가능 | ||
- 이동 경로에 기물이 존재하면 이동 불가 | ||
|
||
#### Queen | ||
|
||
- 상/하/좌/우, 대각선 방향 거리 제한 없이 이동 가능 | ||
- 비었거나 적 기물이 존재하는 칸으로만 이동 가능 | ||
- 이동 경로에 기물이 존재하면 이동 불가 | ||
|
||
#### King | ||
|
||
- 상/하/좌/우, 대각선 방향 중 한 칸만 이동 가능 | ||
- 비었거나 적 기물이 존재하는 칸으로만 이동 가능 | ||
|
||
#### Knight | ||
|
||
- 상/하/좌/우 중 한 칸 이동 후 전진 방향의 대각석으로 한 칸 이동 가능 | ||
- 비었거나 적 기물이 존재하는 칸으로만 이동 가능 | ||
- 이동 경로에 기물이 존재해도 이동 가능 | ||
|
||
#### Pawn | ||
|
||
- 특정 조건에 따라 이동 선택 | ||
- 기본적으로 한 칸 전진 가능 | ||
- 출발지가 초기 위치일 경우 두 칸 전진 가능 | ||
- 전진 경로 혹은 목적지에 기물이 존재하면 이동 불가 | ||
- 전진 방향 대각선 한 칸에 적 기물이 존재시 이동 가능 | ||
|
||
## Board | ||
|
||
- [x] 특정 색상의 기물 이동 | ||
- `출발지` == `도착지`인 경우 예외 처리 | ||
- 출발지에 기물이 존재하지 않으면 예외 처리 | ||
- 상대 색상의 기물을 이동시키려 할 시 예외 처리 | ||
|
||
## ChessGame | ||
|
||
- [x] `흰색` 플레이어와 `검은색` 플레이어의 게임 순서 관리 및 `Board`에 기물 이동 요청 전달 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import controller.GameController; | ||
import dao.ProductionTurnColorDao; | ||
import dao.ProductionPieceDao; | ||
import database.JdbcConnectionPool; | ||
import domain.board.Board; | ||
import domain.board.BoardInitializer; | ||
import domain.board.Position; | ||
import domain.game.ChessGame; | ||
import domain.piece.Piece; | ||
import view.InputView; | ||
import view.OutputView; | ||
|
||
import java.util.Map; | ||
|
||
public class Application { | ||
public static void main(String[] args) { | ||
JdbcConnectionPool connectionPool = JdbcConnectionPool.getInstance(); | ||
Map<Position, Piece> initialPiecePositions = BoardInitializer.initBoard(); | ||
ProductionPieceDao productionPieceDao = new ProductionPieceDao(connectionPool); | ||
Board board = new Board(productionPieceDao, initialPiecePositions); | ||
|
||
ProductionTurnColorDao productionPieceColorDao = new ProductionTurnColorDao(connectionPool); | ||
ChessGame chessGame = new ChessGame(productionPieceColorDao, board); | ||
|
||
GameController gameController = new GameController(new InputView(), new OutputView(), chessGame); | ||
gameController.run(); | ||
|
||
connectionPool.close(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package controller; | ||
|
||
import domain.board.Position; | ||
import domain.game.ChessGame; | ||
import domain.game.GameCommand; | ||
import domain.game.GameCommandType; | ||
import domain.game.GameScore; | ||
import domain.game.GameStatus; | ||
import domain.piece.PieceColor; | ||
import dto.BoardDto; | ||
import view.InputView; | ||
import view.OutputView; | ||
|
||
public class GameController { | ||
private final InputView inputView; | ||
private final OutputView outputView; | ||
private final ChessGame chessGame; | ||
|
||
public GameController(final InputView inputView, final OutputView outputView, final ChessGame chessGame) { | ||
this.inputView = inputView; | ||
this.outputView = outputView; | ||
this.chessGame = chessGame; | ||
} | ||
|
||
public void run() { | ||
initGame(); | ||
|
||
if (chessGame.isRunning()) { | ||
start(); | ||
} | ||
} | ||
|
||
private void initGame() { | ||
try { | ||
GameCommand gameCommand = inputCommand(); | ||
gameCommand.execute(this); | ||
} catch (Exception e) { | ||
outputView.printErrorMessage(e.getMessage()); | ||
initGame(); | ||
} | ||
} | ||
|
||
private GameCommand inputCommand() { | ||
String[] inputValues = inputView.inputCommand().split(" "); | ||
return GameCommandType.of(inputValues); | ||
} | ||
|
||
public void buildGame() { | ||
if (chessGame.existPrevGame()) { | ||
outputView.printInputRoadGameMessage(); | ||
GameCommand gameCommand = inputCommand(); | ||
gameCommand.execute(this); | ||
return; | ||
} | ||
createChessGame(); | ||
start(); | ||
} | ||
|
||
public void createChessGame() { | ||
chessGame.createChessGame(); | ||
} | ||
|
||
public void roadPrevGame() { | ||
chessGame.roadPrevGame(); | ||
} | ||
|
||
public void start() { | ||
chessGame.gameStart(); | ||
outputView.printWelcomeMessage(); | ||
while (chessGame.isRunning()) { | ||
BoardDto boardDto = BoardDto.from(chessGame.piecePositions()); | ||
PieceColor currentPlayTeamColor = chessGame.currentPlayTeamColor(); | ||
outputView.printTurnStatus(boardDto, currentPlayTeamColor); | ||
playTurn(); | ||
} | ||
} | ||
|
||
private void playTurn() { | ||
try { | ||
GameCommand gameCommand = inputCommand(); | ||
gameCommand.execute(this); | ||
} catch (Exception e) { | ||
outputView.printErrorMessage(e.getMessage()); | ||
playTurn(); | ||
} | ||
} | ||
|
||
public void movePiece(final Position source, final Position destination) { | ||
chessGame.movePiece(source, destination); | ||
} | ||
Comment on lines
+88
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 비즈니스 로직이라고 봐도 될 것 같은데 |
||
|
||
public GameStatus gameStatus() { | ||
return chessGame.gameStatus(); | ||
} | ||
|
||
public void end() { | ||
chessGame.gameEnd(); | ||
} | ||
|
||
public void printGameStatus() { | ||
GameScore gameScore = chessGame.getGameResult(); | ||
outputView.printGameResult( | ||
gameScore.whiteTeamScore(), | ||
gameScore.blackTeamScore(), | ||
gameScore.gameResult()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package dao; | ||
|
||
import domain.board.File; | ||
import domain.board.Rank; | ||
|
||
import java.util.List; | ||
|
||
public interface PieceDao { | ||
|
||
List<PieceEntity> findAll(); | ||
|
||
boolean existPiecePositions(); | ||
|
||
void save(PieceEntity piece); | ||
|
||
void update(File sourceFile, Rank sourceRank, File destinationFile, Rank destinationRank); | ||
|
||
void delete(File file, Rank rank); | ||
|
||
void deleteAll(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package dao; | ||
|
||
import domain.board.File; | ||
import domain.board.Rank; | ||
import domain.piece.PieceColor; | ||
import domain.piece.PieceType; | ||
|
||
public record PieceEntity(PieceType pieceType, PieceColor pieceColor, File file, Rank rank) { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package dao; | ||
|
||
import database.JdbcConnectionPool; | ||
import domain.board.File; | ||
import domain.board.Rank; | ||
import domain.piece.PieceColor; | ||
import domain.piece.PieceType; | ||
|
||
import java.sql.Connection; | ||
import java.sql.PreparedStatement; | ||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.sql.Statement; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class ProductionPieceDao implements PieceDao { | ||
private static final int PIECE_COUNT_INDEX = 1; | ||
private static final int FILE_INDEX = 1; | ||
private static final int RANK_INDEX = 2; | ||
private static final int PIECE_TYPE_INDEX = 3; | ||
private static final int PIECE_COLOR_INDEX = 4; | ||
private static final int DESTINATION_FILE_INDEX = 3; | ||
private static final int DESTINATION_RANK_INDEX = 4; | ||
|
||
private final JdbcConnectionPool connectionPool; | ||
|
||
public ProductionPieceDao(final JdbcConnectionPool connectionPool) { | ||
this.connectionPool = connectionPool; | ||
} | ||
|
||
@Override | ||
public List<PieceEntity> findAll() { | ||
final String query = "SELECT * FROM piece"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. final 이 붙은건 네오의 코드 복붙해오는 과정에서 사용했다고 생각하는데 final을 붙일거면 전부다 필사적으로 붙여야 한다고 생각! |
||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) { | ||
ResultSet resultSet = preparedStatement.executeQuery(); | ||
return createPieceEntities(resultSet); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SQLException을 잡고 RuntimeExcpetion으로 넘기기 보다 IllegalStatementException을 던지는건 어때? |
||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
|
||
private List<PieceEntity> createPieceEntities(final ResultSet resultSet) throws SQLException { | ||
List<PieceEntity> pieceEntities = new ArrayList<>(); | ||
while (resultSet.next()) { | ||
File file = File.of(resultSet.getString("file")); | ||
Rank rank = Rank.of(resultSet.getString("rank")); | ||
PieceType type = PieceType.of(resultSet.getString("type")); | ||
PieceColor color = PieceColor.of(resultSet.getString("color")); | ||
|
||
pieceEntities.add(new PieceEntity(type, color, file, rank)); | ||
} | ||
|
||
return pieceEntities; | ||
} | ||
|
||
@Override | ||
public boolean existPiecePositions() { | ||
final String query = "SELECT COUNT(*) FROM piece"; | ||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) { | ||
ResultSet resultSet = preparedStatement.executeQuery(); | ||
if (resultSet.next()) { | ||
int pieceCount = resultSet.getInt(PIECE_COUNT_INDEX); | ||
return pieceCount > 0; | ||
} | ||
|
||
return false; | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
|
||
@Override | ||
public void save(final PieceEntity piece) { | ||
final String query = "INSERT INTO piece (file, `rank`, type, color) VALUES (?, ?, ?, ?)"; | ||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { | ||
preparedStatement.setString(FILE_INDEX, piece.file().name()); | ||
preparedStatement.setInt(RANK_INDEX, piece.rank().value()); | ||
preparedStatement.setString(PIECE_TYPE_INDEX, piece.pieceType().name()); | ||
preparedStatement.setString(PIECE_COLOR_INDEX, piece.pieceColor().name()); | ||
preparedStatement.executeUpdate(); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
|
||
@Override | ||
public void update(final File sourceFile, final Rank sourceRank, final File destinationFile, final Rank destinationRank) { | ||
final String query = "UPDATE piece SET file=?, `rank`=? WHERE file=? AND `rank`=?"; | ||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) { | ||
preparedStatement.setString(FILE_INDEX, destinationFile.name()); | ||
preparedStatement.setInt(RANK_INDEX, destinationRank.value()); | ||
preparedStatement.setString(DESTINATION_FILE_INDEX, sourceFile.name()); | ||
preparedStatement.setInt(DESTINATION_RANK_INDEX, sourceRank.value()); | ||
preparedStatement.executeUpdate(); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
|
||
@Override | ||
public void delete(final File file, final Rank rank) { | ||
final String query = "DELETE FROM piece WHERE file=? AND `rank`=?"; | ||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) { | ||
preparedStatement.setString(FILE_INDEX, file.name()); | ||
preparedStatement.setInt(RANK_INDEX, rank.value()); | ||
preparedStatement.executeUpdate(); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
|
||
@Override | ||
public void deleteAll() { | ||
final String query = "DELETE FROM piece"; | ||
Connection connection = connectionPool.getConnection(); | ||
|
||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) { | ||
preparedStatement.execute(); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
connectionPool.releaseConnection(connection); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
진짜 사소한 의견이긴 한데 공백도 컨벤션이니 위의 두줄은 없어도 되지 않을까..?