Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
37434cc
feat(추상): 추상 - 이름 짓기
LeeHyungGeol Oct 3, 2024
abbc409
feat(추상): 추상 - 메서드 선언부
LeeHyungGeol Oct 3, 2024
138fbeb
feat(추상): 추상 - 추상화 레벨
LeeHyungGeol Oct 3, 2024
8479a0d
feat(추상): 매직 넘버, 매직 스트링
LeeHyungGeol Oct 4, 2024
44107dd
feat(논리,-사고의-흐름): [논리, 사고의 흐름] Early Return
LeeHyungGeol Oct 4, 2024
5529e4f
feat(논리,-사고의-흐름): [논리, 사고의 흐름] 사고의 depth 줄이기
LeeHyungGeol Oct 4, 2024
d0ce33a
feat(논리,-사고의-흐름): [논리, 사고의 흐름] 공백 라인을 대하는 자세
LeeHyungGeol Oct 4, 2024
a04e022
feat(논리,-사고의-흐름): [논리, 사고의 흐름] 부정어를 대하는 자세
LeeHyungGeol Oct 4, 2024
e5dd92c
feat(논리,-사고의-흐름): [논리, 사고의 흐름] 해피 케이스와 예외 처리
LeeHyungGeol Oct 4, 2024
c4cc310
feat(객체-지향-패러다임): [객체 지향 패러다임] 객체 설계하기
LeeHyungGeol Oct 14, 2024
f40102a
feat(객체-지향-패러다임): [객체 지향 패러다임] SRP
LeeHyungGeol Oct 15, 2024
3e7ba5f
feat(객체-지향-패러다임): [객체 지향 패러다임] OCP
LeeHyungGeol Oct 15, 2024
1c1dff9
feat(객체-지향-패러다임): [객체 지향 패러다임] LSP
LeeHyungGeol Oct 16, 2024
2019ceb
feat(객체-지향-패러다임): [객체 지향 패러다임] ISP
LeeHyungGeol Oct 16, 2024
173ead6
feat(객체-지향-패러다임): [객체 지향 패러다임] DIP
LeeHyungGeol Oct 17, 2024
579ffd5
feat(객체-지향-적용): 상속 대신 조합, Value Object
LeeHyungGeol Mar 12, 2025
73ca430
feat(객체-지향-적용하기): 일급 컬렉션
LeeHyungGeol Mar 12, 2025
15e938f
feat(객체-지향-적용하기): Enum 적용 + Cell 의 CellSign 책임을 ConsoleOutputHandler로…
LeeHyungGeol Mar 13, 2025
0b1a96c
feat(객체-지향-적용하기-->-다형성-활용하기): interface 이용하기 -> CellSignProvidable 을 …
LeeHyungGeol Mar 13, 2025
a8f6342
feat(다형성-활용하기-->-CellSnapshotStatus-가-추가될-때마다-CellSignFinder-에도-추가해야-…
LeeHyungGeol Mar 13, 2025
7a91abb
feat(객체-지향-적용하기): 숨겨져 있는 도메인 개념 도출하기
LeeHyungGeol Mar 13, 2025
f8a1e0b
feat(코드-다듬기): 주석의 양면성 > int gameStatus > enum GameStatus 로 변경
LeeHyungGeol Mar 15, 2025
b1659ed
feat(코드-다듬기): 변수와 메서드의 나열 순서
LeeHyungGeol Mar 15, 2025
f755006
feat(코드-다듬기): 패키지 나누기
LeeHyungGeol Mar 15, 2025
e68af35
feat(코드-다듬기): 기능 유지 보수 > 버그 잡기
LeeHyungGeol Mar 15, 2025
a11cfc0
feat(코드-다듬기): 알고리즘 교체하기 > 기존의 backtracking 방식 > dfs(stack 사용) 방식으로 변경
LeeHyungGeol Mar 15, 2025
fbd6c01
코드 다듬기 > IDE 도움 받기 > SonarCube > Stack을 Deque로 교체
LeeHyungGeol Mar 15, 2025
267b9fc
fix(Minesweeper): ConsoleInputHandler, CellSnapshot row, col index er…
LeeHyungGeol Mar 18, 2025
2651222
feat(CellTest): CellState, NumberCell, LAndMineCell, EmptyCell test
LeeHyungGeol Mar 18, 2025
3beacfd
feat(Cell-Test): edit ladnMineCell Test > getSnapshot()
LeeHyungGeol Mar 18, 2025
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
Binary file added .DS_Store
Binary file not shown.
21 changes: 21 additions & 0 deletions src/main/java/cleancode/minesweeper/tobe/GameApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cleancode.minesweeper.tobe;

import cleancode.minesweeper.tobe.minesweeper.Minesweeper;
import cleancode.minesweeper.tobe.minesweeper.config.GameConfig;
import cleancode.minesweeper.tobe.minesweeper.gamelevel.Beginner;
import cleancode.minesweeper.tobe.minesweeper.io.ConsoleInputHandler;
import cleancode.minesweeper.tobe.minesweeper.io.ConsoleOutputHandler;

public class GameApplication {

// 이 클래스는 딱 프로그램 실행에 진입점만 가지게 된다.
// 이름도 MinesweeperGame 에서 GameApplication 으로 변경한다. -> 이렇게 변경하면 지뢰찾기게임(Minesweeper 뿐만이 아닌 다른 게임도 실행할 수 있게 된다.)
// 게임 실행에 대한 책임과 지뢰찾기 도메인 자체, 지뢰찾기 게임을 담당하는 역할을 분리했다.
public static void main(String[] args) {
GameConfig gameConfig = new GameConfig(new Beginner(), new ConsoleInputHandler(), new ConsoleOutputHandler());

Minesweeper minesweeper = new Minesweeper(gameConfig);
minesweeper.initialize();
minesweeper.run();
}
}
187 changes: 0 additions & 187 deletions src/main/java/cleancode/minesweeper/tobe/MinesweeperGame.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cleancode.minesweeper.tobe.game;

public interface GameInitializable {
void initialize();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cleancode.minesweeper.tobe.game;

public interface GameRunnable {
void run();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cleancode.minesweeper.tobe.minesweeper;

import cleancode.minesweeper.tobe.minesweeper.board.GameBoard;
import cleancode.minesweeper.tobe.minesweeper.config.GameConfig;
import cleancode.minesweeper.tobe.minesweeper.exception.GameException;
import cleancode.minesweeper.tobe.game.GameInitializable;
import cleancode.minesweeper.tobe.game.GameRunnable;
import cleancode.minesweeper.tobe.minesweeper.io.InputHandler;
import cleancode.minesweeper.tobe.minesweeper.io.OutputHandler;
import cleancode.minesweeper.tobe.minesweeper.board.positoion.CellPosition;
import cleancode.minesweeper.tobe.minesweeper.user.UserAction;

public class Minesweeper implements GameInitializable, GameRunnable {

// BOARD 도 하는 일이 너무 많고 중요하기 때문에 Minesweeper 클래스 내부에 상수로 두기에는 너무 책임이 과도하다.
// 이렇게 GameBoard 클래스를 두면 Minesweeper 입장에서는 Cell[][] 이중배열에 대해서는 모른다.
// 객체로 추상화가 되었고, 데이터 구조에 대한 것은 캐슐화가 되었기 때문이다.
private final GameBoard gameBoard;
// SRP: cellInput 이라는 사용자의 입력을 받아서 rowIndex, colIndex 로 변환하는 역할을 하는 또 하나의 클래스로 볼 수 있지 않을까?

// 게임이 진행되는 핵심 로직들과 사용자 입출력에 대한 로직 책임을 분리한다.
// DIP: InputHandler, OutputHandler 는 이제 Console 에 관한 것은 모른다. 인터페이스만 의존하고 있다.
// 구현체가 변경되어도 Minesweeper 클래스는 영향을 받지 않는다.
private final InputHandler inputHandler;
private final OutputHandler outputHandler;

public Minesweeper(GameConfig gameConfig) {
gameBoard = new GameBoard(gameConfig.getGameLevel());
this.inputHandler = gameConfig.getInputHandler();
this.outputHandler = gameConfig.getOutputHandler();
}

@Override
public void initialize() {
gameBoard.initializeGame();
}

@Override
public void run() {
outputHandler.showGameStartComments();

while (gameBoard.isInProgress()) {
try {
outputHandler.showBoard(gameBoard);

CellPosition cellPosition = getCellInputFromUser();
UserAction userActionInput = getUserActionInputFromUser();
actOnCell(cellPosition, userActionInput);
} catch (GameException e) {
outputHandler.showExceptionMessage(e);
} catch (Exception e) {
outputHandler.showSimpleMessage("프로그램에 문제가 생겼습니다.");
}
}
outputHandler.showBoard(gameBoard);

if (gameBoard.isWinStatus()) {
outputHandler.showGameWinningComment();
}
if (gameBoard.isLoseStatus()) {
outputHandler.showGameLosingComment();
}
}

private CellPosition getCellInputFromUser() {
outputHandler.showCommentForSelectingCell();
CellPosition cellPosition = inputHandler.getCellPositionFromUser();
if (gameBoard.isInvalidCellPosition(cellPosition)) {
throw new GameException("잘못된 좌표를 선택하셨습니다.");
}

return cellPosition;
}

private UserAction getUserActionInputFromUser() {
outputHandler.showCommentForUserAction();
return inputHandler.getUserActionFromUser();
}

private void actOnCell(CellPosition cellPosition, UserAction userActionInput) {
if (doesUserChooseToPlantFlag(userActionInput)) {
gameBoard.flagAt(cellPosition);
return;
}
if (doesUserChooseToOpenCell(userActionInput)) {
gameBoard.openAt(cellPosition);
return;
}
throw new GameException("잘못된 번호를 선택하셨습니다.");
}

private boolean doesUserChooseToPlantFlag(UserAction userAction) {
return userAction == UserAction.FLAG;
}

private boolean doesUserChooseToOpenCell(UserAction userAction) {
return userAction == UserAction.OPEN;
}
}
Loading