Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4c2f777
docs: docs/README.md 구현할 기능 목록 작성
jisu-om Oct 19, 2023
ed77363
docs: docs/README.md 구현할 기능 목록 수정
jisu-om Oct 19, 2023
2776639
test: 테스트코드 작성
jisu-om Oct 19, 2023
8117e54
feat: OutputView에 게임 시작, 결과, 종료 문구 출력 기능 추가
jisu-om Oct 19, 2023
1dc44e4
feat: InputView에사용자 입력값을 받아들이는 readInput 메서드 추가
jisu-om Oct 19, 2023
7b565a1
feat: OutputView printGetInput 메서드 수정
jisu-om Oct 19, 2023
649738c
feat: 컴퓨터 숫자를 생성하는 ComputerNumber 클래스 생성
jisu-om Oct 20, 2023
820420d
feat: PlayerNumber 생성(사용자로부터 값을 입력받아 검증 후 PlayerNumber 생성)
jisu-om Oct 20, 2023
70b1e5e
feat: PlayerNumber의 validation 로직 수정, GameResultGenerator 생성
jisu-om Oct 20, 2023
2566772
feat: PlayerChoice(게임종료 시 받는 사용자 입력값 객체) 생성, 심판관 역할을 하는 GameControlle…
jisu-om Oct 20, 2023
30c1841
Refactor: GameController.run(), Application.main() 반복문 로직 수정
jisu-om Oct 20, 2023
591e16a
Refactor: GameController 싱글톤 패턴 적용(static 메서드를 사용하기 보다는 항상 같은 인스턴스를 반…
jisu-om Oct 21, 2023
053079a
Refactor: GameController 싱글톤에서 이전 방식으로 변경(불필요한 과한 코드를 늘리는 것 같고, Appli…
jisu-om Oct 23, 2023
1b3245e
Refactor: PlayerNumber 수정 - validation 변경(같은 숫자가 두번 들어오고 전체 길이가 3개가 아…
jisu-om Oct 23, 2023
9ca14ab
Test: BaseballGameTest 테스트코드 작성(TDD 추가 공부 필요)
jisu-om Oct 23, 2023
a6c52db
Refactor: static factory 메서드 이름 변경
jisu-om Oct 24, 2023
06f4fc1
Refactor: GameResultGenerator의 calculateResult 메서드 리팩토링
jisu-om Oct 24, 2023
037572c
feat: PlayerChoice에 대한 검증 추가(문자열 입력받을 경우에 대해서 검증하지 않아서 추가함)
jisu-om Oct 26, 2023
3e1c9ea
Refactor: PlayerNumber의 getter()에 방어적 복사 적용
jisu-om Oct 26, 2023
8e0b105
refactor: getNumbers() 메서드 방어적 복사 수정
jisu-om Oct 26, 2023
e5d24ec
Refactor: 모든 주석 삭제
jisu-om Nov 17, 2023
d41fd8f
Refactor(computerNumber#getNumbers): 불변객체 리턴하도록 변경
jisu-om Nov 17, 2023
9eb5ee2
Rename(gameResultService): service 패키지 하위로 이동, 이름 변경
jisu-om Nov 17, 2023
4e95bd0
Refactor(gameController, application): gameController 의 구조 변경, 싱글톤 적용
jisu-om Nov 17, 2023
f0d5f4b
Refactor(inputView, outputView, userNumber): inputView, outputView 변경…
jisu-om Nov 17, 2023
94f2e06
Refactor(inputView, outputView, playAgainInput): playAgainInput 으로 이름…
jisu-om Nov 17, 2023
3611304
Refactor: userNumber 받고 생성하는 로직 리팩토링
jisu-om Nov 17, 2023
d17cf9b
Refactor: playAgainDecision 으로 변경 및 추가 리팩토링, 테스트코드 수정
jisu-om Nov 17, 2023
a55fef3
Refactor: 구조 전체적으로 변경 - 객체가 능동적으로 일하도록 변경
jisu-om Nov 18, 2023
5298702
Refactor(gameController): 메서드 순서 변경
jisu-om Nov 18, 2023
91852d0
Refactor(roundResult#processRound, outputView#printResult): 동작하도록 수정,…
jisu-om Nov 18, 2023
7f62426
Test: 테스트코드 수정
jisu-om Nov 18, 2023
f88292f
Remove: 테스트 클래스 삭제
jisu-om Nov 18, 2023
be3545f
Test: 테스트 에러 수정
jisu-om Nov 18, 2023
30aee38
Refactor: inputView, outputView 싱글톤으로 변경
jisu-om Nov 20, 2023
6d784f0
Refactor(gameRestartController): gameController의 기능을 쪼개서 분담
jisu-om Nov 20, 2023
129fdbe
Rename(mainController): gameController 에서 mainController 로 이름 변경
jisu-om Nov 20, 2023
59da69c
Refactor(gamePlayController): mainController의 play 역할을 gamePlayContro…
jisu-om Nov 20, 2023
117baf9
Refactor(gameManager): computerNumber 생성을 gameManager가 생성될 때 자동으로 되도록 숨김
jisu-om Nov 20, 2023
99f06af
Refactor(mainController#run): 로직 수정
jisu-om Nov 20, 2023
9128a6f
Style: 불필요한 import 제거
jisu-om Nov 20, 2023
26531df
Style: 불필요한 import 제거
jisu-om Nov 20, 2023
9729001
Refactor(mainController#run): run의 로직 변경
jisu-om Nov 20, 2023
baf4a3c
Refactor(gamePlayController#playRound): 메서드 이름 변경(play -> playRound)
jisu-om Nov 20, 2023
47f179b
Refactor(mainController): 필드 순서 변경
jisu-om Nov 21, 2023
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
44 changes: 44 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# [ 구현할 기능 목록 ]

1. 게임 시작 문구 출력
- "숫자 야구 게임을 시작합니다." 출력


2. 1~9 의 서로 다른 숫자 3개 생성 (컴퓨터숫자 생성)


3. 사용자로부터 숫자 입력 받기


4. 입력 받은 숫자 Validation 진행
- (1) 1부터 9 까지의 (2) 서로 다른 (3) 숫자 (4) 3개여야 함
- 예외 처리 : 0, 숫자가 아닌 값, 서로 다른 숫자 3개가 아닌 경우


5. 입력 받은 숫자와 컴퓨터 숫자를 비교
- 낫싱 여부, 볼 개수, 스트라이크 개수 계산


6. 비교한 값을 전달 받아 결과 문자열 생성
- (ex) 낫싱, 1볼, 2스트라이크, 1볼 1스트라이크


7. 결과 문자열 출력


8. 게임 종료 여부 체크
- 3개의 숫자를 모두 맞추면 (3 스트라이크) true, 아니면 false
- true 인 경우, 아래 내용 출력
- "3개의 숫자를 모두 맞히셨습니다! 게임 종료"
- "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."
- false 인 경우
- 3번 (사용자로부터 숫자 입력받기) 으로 돌아가서 값이 true일 때까지 반복


9. 8번이 true인 경우, 8번에 대한 입력 값 Validation 진행
- 1 또는 2 가 아닌 값이면 예외 처리


10. 입력 값에 따라 다시 시작, 완전 종료 진행
- 1 -> 다시 시작 (2번 부터 반복)
- 2 -> 완전 종료 (프로그램 종료)
7 changes: 6 additions & 1 deletion src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package baseball;

import baseball.controller.MainController;
import camp.nextstep.edu.missionutils.Console;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
MainController mainController = MainController.getInstance();
mainController.run();
Console.close();
}
}
57 changes: 57 additions & 0 deletions src/main/java/baseball/controller/GamePlayController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package baseball.controller;

import baseball.dto.RoundResultDto;
import baseball.model.UserNumber;
import baseball.service.GameManager;
import baseball.view.InputView;
import baseball.view.OutputView;

import java.util.List;

public class GamePlayController {
private static GamePlayController instance = new GamePlayController(InputView.getInstance(), OutputView.getInstance());
private final InputView inputView;
private final OutputView outputView;
private GameManager gameManager;

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

public static GamePlayController getInstance() {
return instance;
}

public boolean playRound() {
outputView.printStart();
initializeGameManager();
boolean needsNextRound = true;
while (needsNextRound) {
UserNumber userNumber = readUserNumber();
needsNextRound = playRound(userNumber);
printRoundResult();
}
return needsNextRound;
}

private void initializeGameManager() {
gameManager = GameManager.create();
}

private UserNumber readUserNumber() {
List<Integer> numbers = inputView.readUserNumber();
return UserNumber.from(numbers);
}

private boolean playRound(UserNumber userNumber) {
boolean needsNextRound;
needsNextRound = gameManager.playRound(userNumber);
return needsNextRound;
}

private void printRoundResult() {
RoundResultDto resultDto = gameManager.createResultDto();
outputView.printResult(resultDto.isNothing(), resultDto.getBallCount(), resultDto.getStrikeCount());
}
}
31 changes: 31 additions & 0 deletions src/main/java/baseball/controller/GameRestartController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package baseball.controller;

import baseball.model.PlayAgainDecision;
import baseball.view.InputView;
import baseball.view.OutputView;

public class GameRestartController {
public static GameRestartController instance = new GameRestartController(InputView.getInstance(), OutputView.getInstance());
private final InputView inputView;
private final OutputView outputView;

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

public static GameRestartController getInstance() {
return instance;
}

public boolean wantsRestart() {
outputView.printEnd();
PlayAgainDecision playAgainDecision = readPlayAgainInput();
return playAgainDecision.isAgain();
}

private PlayAgainDecision readPlayAgainInput() {
int input = inputView.readPlayAgainInput();
return PlayAgainDecision.of(input);
}
}
25 changes: 25 additions & 0 deletions src/main/java/baseball/controller/MainController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package baseball.controller;

public class MainController {
public static MainController instance = new MainController(GamePlayController.getInstance(), GameRestartController.getInstance());
private final GamePlayController gamePlayController;
private final GameRestartController gameRestartController;

private MainController(GamePlayController gamePlayController, GameRestartController gameRestartController) {
this.gamePlayController = gamePlayController;
this.gameRestartController = gameRestartController;
}

public static MainController getInstance() {
return instance;
}

public void run() {
boolean continuePlaying = true;
while (continuePlaying) {
if (!gamePlayController.playRound()) {
continuePlaying = gameRestartController.wantsRestart();
}
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/baseball/dto/RoundResultDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package baseball.dto;

import baseball.model.RoundResult;

public class RoundResultDto {
public boolean isNothing;
public int ballCount;
public int strikeCount;

private RoundResultDto() {
}

public static RoundResultDto from(RoundResult roundResult) {
RoundResultDto dto = new RoundResultDto();
dto.isNothing = roundResult.isNothing();
dto.ballCount = roundResult.provideBallCount();
dto.strikeCount = roundResult.provideStrikeCount();
return dto;
}

public boolean isNothing() {
return isNothing;
}

public int getBallCount() {
return ballCount;
}

public int getStrikeCount() {
return strikeCount;
}
}
19 changes: 19 additions & 0 deletions src/main/java/baseball/exception/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package baseball.exception;

public enum ErrorMessage {
ERROR_CAPTION("[ERROR] "),
INVALID_USER_NUMBER_INPUT_FORMAT("숫자를 입력해 주세요."),
INVALID_USER_NUMBER_CONTAINS_ZERO("0이 아닌 숫자 3개를 입력해주세요."),
DUPLICATED_USER_NUMBER("서로 다른 숫자 3개를 입력해주세요."),
INVALID_PLAY_AGAIN("1 또는 2를 입력해주세요.");

private final String message;

ErrorMessage(String message) {
this.message = message;
}

public String getMessage() {
return ERROR_CAPTION.message + message;
}
}
26 changes: 26 additions & 0 deletions src/main/java/baseball/model/ComputerNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package baseball.model;

import baseball.utils.NumbersGenerator;

import java.util.List;

public class ComputerNumber {
private final List<Integer> numbers;

private ComputerNumber(List<Integer> numbers) {
this.numbers = numbers;
}

public static ComputerNumber create() {
List<Integer> numbers = NumbersGenerator.generate();
return new ComputerNumber(numbers);
}

public boolean containsNumber(int number) {
return numbers.contains(number);
}

public int findNumberByPosition(int position) {
return numbers.get(position);
}
}
39 changes: 39 additions & 0 deletions src/main/java/baseball/model/PlayAgainDecision.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package baseball.model;

import static baseball.exception.ErrorMessage.INVALID_PLAY_AGAIN;
import static baseball.model.PlayAgainDecision.PlayAgainConstants.NO;
import static baseball.model.PlayAgainDecision.PlayAgainConstants.YES;

public class PlayAgainDecision {
private final int value;

private PlayAgainDecision(int input) {
value = input;
}

public static PlayAgainDecision of(int input) {
validate(input);
return new PlayAgainDecision(input);
}

private static void validate(int input) {
if ((input != YES.value) && (input != NO.value)) {
throw new IllegalArgumentException(INVALID_PLAY_AGAIN.getMessage());
}
}

public boolean isAgain() {
return value == YES.value;
}

enum PlayAgainConstants {
YES(1),
NO(2);

private final int value;

PlayAgainConstants(int value) {
this.value = value;
}
}
}
48 changes: 48 additions & 0 deletions src/main/java/baseball/model/RoundResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package baseball.model;

import java.util.stream.IntStream;

import static baseball.utils.Constants.NUMBERS_SIZE;
import static baseball.utils.Constants.START_INDEX;

public class RoundResult {
private int ballCount = 0;
private int strikeCount = 0;

private RoundResult(ComputerNumber computerNumber, UserNumber userNumber) {
processRound(computerNumber, userNumber);
}

public static RoundResult create(ComputerNumber computerNumber, UserNumber userNumber) {
return new RoundResult(computerNumber, userNumber);
}

private void processRound(ComputerNumber computerNumber, UserNumber userNumber) {
for (int position = START_INDEX; position < NUMBERS_SIZE; position++) {
int number = userNumber.findNumberByPosition(position);
if (computerNumber.containsNumber(number)) {
if (computerNumber.findNumberByPosition(position) == number) {
strikeCount++;
continue;
}
ballCount++;
}
}
}

public boolean isNothing() {
return ballCount == 0 && strikeCount == 0;
}

public boolean needsNextRound() {
return strikeCount != 3;
}

public int provideBallCount() {
return ballCount;
}

public int provideStrikeCount() {
return strikeCount;
}
}
25 changes: 25 additions & 0 deletions src/main/java/baseball/model/UserNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package baseball.model;

import java.util.List;

import static baseball.utils.validator.UserNumberValidator.*;


public class UserNumber {
private final List<Integer> numbers;

private UserNumber(List<Integer> numbers) {
this.numbers = numbers;
}

public static UserNumber from(List<Integer> numbers) {
validateNonZero(numbers);
validateDuplicate(numbers);
validateSize(numbers);
return new UserNumber(numbers);
}

public int findNumberByPosition(int position) {
return numbers.get(position);
}
}
Loading