Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5387a35
docs: 각종 요구사항 추가
mckim123 Dec 11, 2022
dd8e5b2
docs: 기능 목록 정리
mckim123 Dec 11, 2022
00ef69c
chore: 최초 클래스 설계
mckim123 Dec 11, 2022
78bf3a2
feat: Application.java 구현
mckim123 Dec 11, 2022
d6cfe84
feat: GameController 구현
mckim123 Dec 11, 2022
d73dcca
feat: BaseballGame.java 구현
mckim123 Dec 11, 2022
a387c28
feat: Constant.java 생성 및 구현
mckim123 Dec 11, 2022
ca86aa3
feat: StrikeBallCount.java 구현
mckim123 Dec 11, 2022
04533b2
refactor: Judge -> Referee 클래스 명 수정
mckim123 Dec 12, 2022
d623397
feat: BaseballNumbers.java 구현
mckim123 Dec 12, 2022
44857ae
feat: BaseballNumbersGenerator.java 구현
mckim123 Dec 12, 2022
67965dc
feat: OutputView.java 구현
mckim123 Dec 12, 2022
b894af0
feat: Referee.java 판정 기능 구현, BaseballNumbers의 숫자 getter 추가
mckim123 Dec 12, 2022
5130085
feat: 추상클래스 Validator 구현
mckim123 Dec 12, 2022
21a8129
feat: InputUserAnswerValidator 구현, BaseballNumbers의 생성자 추가
mckim123 Dec 12, 2022
2f25dab
refactor: BaseballNumbersGenerator 수정
mckim123 Dec 12, 2022
895c320
feat: InputRestartValidator.java 구현
mckim123 Dec 12, 2022
3ccf51b
feat: InputView.java 구현
mckim123 Dec 12, 2022
2a399be
refactor: 사용자 입력 검증 과정에서의 예외 메시지 구현
mckim123 Dec 12, 2022
98c5dcd
refactor: 정답 시 메시지 출력 구현
mckim123 Dec 12, 2022
3f37811
style: 코드 컨벤션 적용
mckim123 Dec 12, 2022
543f110
docs: Readme.md 기능 목록 수정 및 결과 반영
mckim123 Dec 12, 2022
12332ec
refactor: Command enum class 추가
mckim123 Dec 12, 2022
136512c
test: OutputViewTest 구현
mckim123 Dec 16, 2022
c9b5d5d
test: InputRestartValidatorTest 구현
mckim123 Dec 16, 2022
fb4de62
test: InputUserAnswerValidatorTest 구현
mckim123 Dec 16, 2022
6f6accc
refactor: BaseballNumbers의 equals method override
mckim123 Dec 16, 2022
e280813
refactor: StrikeBallCount의 equals method override
mckim123 Dec 16, 2022
c36bf87
refactor: OutputViewTest의 inner enum StrikeBallCountCombination을 분리
mckim123 Dec 16, 2022
2caf477
test: BaseballGameTest 구현
mckim123 Dec 16, 2022
343265c
test: Readme.md 파일 통합
mckim123 Dec 19, 2022
215a041
chore: 자바 코드 컨벤션 적용
mckim123 Dec 19, 2022
9145cbb
chore: 오타 수정
mckim123 Dec 22, 2022
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
97 changes: 97 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,104 @@
## 숫자 야구 게임 기능 목록

#### 게임 컨트롤러 `GameController`
- [x] 최초에 게임 생성
- [x] 사용자의 정답 입력에 대해 결과 판정 후 출력
- [x] 3스트라이크인 경우 해당 게임 종료
- [x] 게임이 끝난 후 추가 진행 여부 입력이 1인 경우 새 게임 생성
- [x] 게임이 끝난 후 추가 진행 여부 입력이 2인 경우 전체 게임 종료

#### 숫자 야구 게임 `BaseballGame`
- [x] 최초 생성시 `BaseballNumbersGenerator`를 통해 정답 생성

#### 컴퓨터 숫자 생성 `BaseballNumbersGenerator`
- [x] `BaseballNumbers`(1부터 9까지 서로 다른 수로 이루어진 3자리의 수) 생성

#### 사용자의 입력 받음 `InputView`
- [x] 사용자의 정답을 입력 받음
- [x] 사용자의 새 게임 진행 여부를 입력 받음
- [x] 잘못된 입력이 들어오는 경우 에러메시지 출력 후 다시 입력 받음

#### 메시지 출력 `OutputView`
- [x] `StrikeBallCount`에 대한 결과 출력

#### 사용자의 정답 입력 검증 `InputUserAnswerValidator`
- [x] 사용자의 정답 입력을 검증
- [x] 사용자의 정답 입력을 `BaseballNumbers`로 변환

#### 사용자의 새 게임 진행 여부 입력 검증 `InputRestartValidator`
- [x] 사용자의 새 게임 진행 여부 입력을 검증

#### 결과 판정 `Referee`
- [x] 게임의 정답과 사용자가 입력한 답을 비교하여 `StrikeBallCount` 생성
- [x] 각각의 숫자에 대해 포함된 여부, index가 같은 지 확인하여 볼카운트 판정

<br><br><br>


# 숫자 야구 게임
## 진행 방법
* 숫자 야구 게임 요구사항을 파악한다.
* 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 과제를 제출한다.

## 과제 제출 과정
* [과제 제출 방법](https://github.com/next-step/nextstep-docs/tree/master/ent-precourse)


## 기능 요구 사항

기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.

- 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞히면 승리한다.
- 예시) 상대방(컴퓨터)의 수가 425일 때
- 123을 제시한 경우 : 1스트라이크
- 456을 제시한 경우 : 1볼 1스트라이크
- 789를 제시한 경우 : 낫싱
- 위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한
결과를 출력한다.
- 이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.

#### 실행 결과 예시

```
숫자를 입력해주세요 : 123
1스트라이크 1볼
숫자를 입력해주세요 : 145
1볼
숫자를 입력해주세요 : 671
2볼
숫자를 입력해주세요 : 216
1스트라이크
숫자를 입력해주세요 : 713
3스트라이크
3개의 숫자를 모두 맞히셨습니다! 게임 종료
게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.
1
숫자를 입력해주세요 : 123
1스트라이크 1볼
...
```

---

## 프로그래밍 요구 사항 - 메소드 분리

- 자바 코드 컨벤션을 지켜가며 프로그래밍한다.
- https://github.com/woowacourse/woowacourse-docs/tree/master/styleguide/java 참고
- indent(인덴트, 들여쓰기) depth를 2가 넘지 않도록 구현한다. 1까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
- 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- 자바 8에 추가된 stream api를 사용하지 않고 구현해야 한다. 단, 람다는 사용 가능하다.
- else 예약어를 쓰지 않는다.
- 힌트 : if 절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
- else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데, switch/case도 허용하지 않는다.
- 함수(또는 메소드)의 길이가 10라인을 넘어가지 않도록 구현한다.
- 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.

## 프로그래밍 요구 사항 - 단위 테스트

- 로직에 단위 테스트를 구현한다. 단, UI(System.out, System.in, Scanner) 로직은 제외
- 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다.

- JUni5와 AssertJ 사용법에 익숙하지 않은 개발자는 첨부한 "학습테스트를 통해 JUnit 학습하기.pdf" 문서를 참고해 사용법을 익힌 후 JUnit5 기반 단위 테스트를 구현한다.

14 changes: 14 additions & 0 deletions src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package baseball;

import baseball.controller.GameController;
import baseball.view.InputView;
import baseball.view.OutputView;

public class Application {
public static void main(String[] args) {
InputView inputView = new InputView();
OutputView outputView = new OutputView();
GameController gameController = new GameController(inputView, outputView);
gameController.play();
}
}
25 changes: 25 additions & 0 deletions src/main/java/baseball/BaseballNumbersGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package baseball;

import baseball.constant.Constant;
import baseball.domain.BaseballNumbers;
import java.util.Random;

public class BaseballNumbersGenerator {
Random random;
private final int MIN = Constant.MIN_RANGE.getValue();
private final int MAX = Constant.MAX_RANGE.getValue();

public BaseballNumbersGenerator() {
random = new Random();
}

public BaseballNumbers generate() {
BaseballNumbers baseballNumbers = new BaseballNumbers();
boolean isFull = false;
while (!isFull) {
int nextNumber = MIN + random.nextInt(MAX - MIN);
isFull = baseballNumbers.add(nextNumber);
}
return baseballNumbers;
}
}
15 changes: 15 additions & 0 deletions src/main/java/baseball/constant/Command.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package baseball.constant;

public enum Command {
RESTART("1"), QUIT("2");

private final String value;

Command(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}
15 changes: 15 additions & 0 deletions src/main/java/baseball/constant/Constant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package baseball.constant;

public enum Constant {
LENGTH(3), MIN_RANGE(1), MAX_RANGE(9);

private final int value;

Constant(int number) {
this.value = number;
}

public int getValue() {
return value;
}
}
47 changes: 47 additions & 0 deletions src/main/java/baseball/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package baseball.controller;

import baseball.BaseballNumbersGenerator;
import baseball.constant.Constant;
import baseball.domain.BaseballGame;
import baseball.domain.StrikeBallCount;
import baseball.view.InputView;
import baseball.view.OutputView;

public class GameController {
private static final String END_FORMAT = "%d개의 숫자를 모두 맞히셨습니다! 게임 종료";
private static final String END_MESSAGE = String.format(END_FORMAT, Constant.LENGTH.getValue());
private final InputView inputView;
private final OutputView outputView;
private final BaseballNumbersGenerator baseballNumbersGenerator;
private BaseballGame baseballGame;
private StrikeBallCount strikeBallCount;

public GameController(InputView inputView, OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
baseballNumbersGenerator = new BaseballNumbersGenerator();
}

public void play() {
do {
initializeGame();
playGame();
System.out.println(END_MESSAGE);
} while (inputView.readInputRestart());
}

private void initializeGame() {
baseballGame = new BaseballGame(baseballNumbersGenerator.generate());
}

private void playGame() {
do {
strikeBallCount = baseballGame.getResult(inputView.readInputUserAnswer());
printResult();
} while (!strikeBallCount.getIsComplete());
}

private void printResult() {
outputView.printResult(strikeBallCount);
}
}
13 changes: 13 additions & 0 deletions src/main/java/baseball/domain/BaseballGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package baseball.domain;

public class BaseballGame {
private final Referee referee;

public BaseballGame(BaseballNumbers baseballNumbers) {
referee = new Referee(baseballNumbers);
}

public StrikeBallCount getResult(BaseballNumbers userNumbers) {
return referee.judge(userNumbers);
}
}
52 changes: 52 additions & 0 deletions src/main/java/baseball/domain/BaseballNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package baseball.domain;

import baseball.constant.Constant;
import java.util.ArrayList;
import java.util.List;

public class BaseballNumbers {
private final List<Integer> numbers;
private final int length = Constant.LENGTH.getValue();

public BaseballNumbers() {
numbers = new ArrayList<>();
}

public BaseballNumbers(String[] input) {
this();
for (String num : input) {
this.add(Integer.parseInt(num));
}
}

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

public boolean add(int number) {
if (!contains(number)) {
numbers.add(number);
}
return isFull();
}

public boolean isFull() {
return numbers.size() == length;
}

public int getNumberAt(int index) {
return numbers.get(index);
}

public int getIndex(int number) {
return numbers.indexOf(number);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof BaseballNumbers) {
return numbers.equals(((BaseballNumbers) obj).numbers);
}
return false;
}
}
37 changes: 37 additions & 0 deletions src/main/java/baseball/domain/Referee.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package baseball.domain;

import baseball.constant.Constant;

public class Referee {
private final BaseballNumbers answer;
private final StrikeBallCount strikeBallCount;
private final int length = Constant.LENGTH.getValue();

public Referee(BaseballNumbers answer) {
this.answer = answer;
this.strikeBallCount = new StrikeBallCount();
}

public StrikeBallCount judge(BaseballNumbers userNumbers) {
strikeBallCount.resetCounts();
for (int index = 0; index < length; index++) {
int number = userNumbers.getNumberAt(index);
judgeOneNumber(index, number);
}
return strikeBallCount;
}

private void judgeOneNumber(int index, int number) {
if (answer.contains(number)) {
changeCount(index, number);
}
}

private void changeCount(int index, int number) {
if (index == answer.getIndex(number)) {
strikeBallCount.addStrikeCount();
return;
}
strikeBallCount.addBallCount();
}
}
47 changes: 47 additions & 0 deletions src/main/java/baseball/domain/StrikeBallCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package baseball.domain;

import baseball.constant.Constant;

public class StrikeBallCount {
private int strikeCount;
private int ballCount;
private final int length;

public StrikeBallCount() {
length = Constant.LENGTH.getValue();
}

public void resetCounts() {
strikeCount = 0;
ballCount = 0;
}

public void addStrikeCount() {
strikeCount++;
}

public void addBallCount() {
ballCount++;
}

public int getStrikeCount() {
return strikeCount;
}

public int getBallCount() {
return ballCount;
}

public boolean getIsComplete() {
return strikeCount == length;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof StrikeBallCount) {
StrikeBallCount strikeBallCount = (StrikeBallCount) obj;
return strikeCount == strikeBallCount.getStrikeCount() && ballCount == strikeBallCount.getBallCount();
}
return false;
}
}
20 changes: 20 additions & 0 deletions src/main/java/baseball/validator/InputRestartValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package baseball.validator;

import baseball.constant.Command;

public class InputRestartValidator extends Validator {
private static final String restart = Command.RESTART.getValue();
private static final String quit = Command.QUIT.getValue();
private static final String INVALID_RESTART_INPUT_ERROR_MESSAGE = "[ERROR] 입력을 확인해주세요.";

public static Boolean validate(String input) {
String trimmedInput = removeSpace(input);
if (trimmedInput.equals(restart)) {
return true;
}
if (trimmedInput.equals(quit)) {
return false;
}
throw new IllegalArgumentException(INVALID_RESTART_INPUT_ERROR_MESSAGE);
}
}
Loading