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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,22 @@

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

### 기능 요구사항
- 1부터 9까지 서로 다른 수로 이루어진 3자리 수를 맞추는 게임
- 사용자는 3자리 수를 제시
- 사용자가 제시한 수에 대한 응답
- n개의 (존재하는 수 & 자리 일치) : n 스트라이크
- n개의 (존재하는 수 & 자리 불일치) : n 볼
- 하나도 일치하지 않는 경우 : 낫싱
- 정답을 맞추면 게임 종료 or 게임 재시작 가능


### 구현할 기능 목록
[x] 랜덤 세 자리 숫자 생성 기능
[x] 사용자 추측 숫자 입력 기능
[x] 사용자 입력 추측 숫자에 대한 유효성 검사, 재입력 기능
[x] 추측 숫자에 대한 결과 도출 및 출력 기능
[x] 정답이 나올 때까지 추측 반복 기능
[x] 정답시 게임 재시작 or 종료 기능
[x] 사용자 게임 재시작 입력 숫자에 대한 유효성 검사, 재입력 기능
9 changes: 9 additions & 0 deletions src/main/java/NumberBaseBallGameApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import game.NumberBaseBallGameManager;

public class NumberBaseBallGameApplication {

public static void main(String[] args) {
NumberBaseBallGameManager numberBaseBallGameManager = new NumberBaseBallGameManager();
numberBaseBallGameManager.start();
}
}
9 changes: 9 additions & 0 deletions src/main/java/config/GlobalData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package config;

import domain.ballnumber.generator.BallNumberGenMode;

public class GlobalData {

public static final int BALL_NUMBER_LENGTH = 3;
public static final BallNumberGenMode BALL_NUMBER_GEN_MODE = BallNumberGenMode.RANDOM;
}
23 changes: 23 additions & 0 deletions src/main/java/domain/ballnumber/BallNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package domain.ballnumber;

import java.util.ArrayList;
import java.util.List;

public class BallNumber {

private List<Integer> digits;

public BallNumber(List<Integer> numbers) {
this.digits = new ArrayList<>();
this.digits.addAll(numbers);
}

public int getLength() {
return digits.size();
}

public List<Integer> getDigits() {
return this.digits;
}

}
51 changes: 51 additions & 0 deletions src/main/java/domain/ballnumber/BallResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package domain.ballnumber;

import config.GlobalData;

import java.util.HashSet;
import java.util.Set;

public class BallResult {

private int strike;
private int ball;

public BallResult() {
this.strike = 0;
this.ball = 0;
}

public int getStrike() {
return strike;
}

public int getBall() {
return ball;
}

public static BallResult createBallResult(BallNumber correctBallNumber, BallNumber guessedBallNumber) {
BallResult ballResult = new BallResult();
Set correctBallNumberSet = new HashSet(correctBallNumber.getDigits());
for(int i=0; i<guessedBallNumber.getLength(); i++) {
int numberToCheck = guessedBallNumber.getDigits().get(i);
ballResult.countStrikeBall(correctBallNumberSet.contains(numberToCheck),
correctBallNumber.getDigits().get(i)==numberToCheck);
}
return ballResult;
}

public void countStrikeBall(boolean isContained, boolean isDigitSame) {
if(isDigitSame) {
this.strike++;
return;
}
if(isContained) {
this.ball++;
}
}

public boolean isAllStrike() {
return strike== GlobalData.BALL_NUMBER_LENGTH;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package domain.ballnumber.generator;

public enum BallNumberGenMode {
RANDOM
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package domain.ballnumber.generator;

import domain.ballnumber.BallNumber;

public interface BallNumberGenerator {

BallNumber generate(int length);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package domain.ballnumber.generator;

import domain.ballnumber.BallNumber;
import domain.ballnumber.generator.BallNumberGenerator;

import java.util.*;

public class RandomBallNumberGenerator implements BallNumberGenerator {

@Override
public BallNumber generate(int length) {
Set<Integer> numberSet = new LinkedHashSet<>();
while(numberSet.size() < length) {
numberSet.add((int)(Math.random()*1000)%9+1);
}
return new BallNumber(new ArrayList<>(numberSet));
}
}
5 changes: 5 additions & 0 deletions src/main/java/domain/game/GameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package domain.game;

public enum GameResult {
RESTART, EXIT
}
5 changes: 5 additions & 0 deletions src/main/java/domain/game/GameStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package domain.game;

public enum GameStatus {
READY, PLAYING, FINISH
}
55 changes: 55 additions & 0 deletions src/main/java/game/NumberBaseBallGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package game;

import config.GlobalData;
import domain.ballnumber.BallNumber;
import domain.ballnumber.BallResult;
import domain.ballnumber.generator.BallNumberGenMode;
import domain.ballnumber.generator.BallNumberGenerator;
import domain.ballnumber.generator.RandomBallNumberGenerator;
import domain.game.GameStatus;

public class NumberBaseBallGame {

private GameStatus gameStatus;
private BallNumberGenerator ballNumberGenerator;
private BallNumber correctBallNumber;

private NumberBaseBallGame() {
this.gameStatus = GameStatus.READY;
}

public NumberBaseBallGame(BallNumberGenMode mode) {
this();
if (BallNumberGenMode.RANDOM.equals(mode))
this.ballNumberGenerator = new RandomBallNumberGenerator();
}

public GameStatus getGameStatus() {
return this.gameStatus;
}

public BallNumber getCorrectBallNumber() {
return this.correctBallNumber;
}

public void initGame() {
generateBallNumber();
this.gameStatus = GameStatus.PLAYING;
}

public void generateBallNumber() {
if(this.ballNumberGenerator==null) return;
this.correctBallNumber = this.ballNumberGenerator.generate(GlobalData.BALL_NUMBER_LENGTH);
}

public BallResult throwBall(BallNumber guessedBallNumber) {
BallResult ballResult = compareBallNumber(guessedBallNumber);
if(ballResult.isAllStrike()) this.gameStatus = GameStatus.FINISH;
return ballResult;
}

public BallResult compareBallNumber(BallNumber guessedBallNumber) {
return BallResult.createBallResult(this.correctBallNumber, guessedBallNumber);
}

}
43 changes: 43 additions & 0 deletions src/main/java/game/NumberBaseBallGameManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package game;

import config.GlobalData;
import domain.ballnumber.BallNumber;
import domain.game.GameResult;
import domain.game.GameStatus;
import view.InputManager;
import view.OutputView;

public class NumberBaseBallGameManager {

private NumberBaseBallGame numberBaseBallGame;
private InputManager inputManager;
private OutputView outputView;

public NumberBaseBallGameManager() {
this.numberBaseBallGame = new NumberBaseBallGame(GlobalData.BALL_NUMBER_GEN_MODE);
this.inputManager = new InputManager();
this.outputView = new OutputView();
}

public void start() {
while(!GameResult.EXIT.equals(play())){}
}

public GameResult play() {
this.numberBaseBallGame.initGame();
while(isGamePlaying()) {
outputView.showBallResult(numberBaseBallGame.throwBall(guessBallNumber()));
}
outputView.showGameFinished();
return inputManager.inputGameResult();
}

public boolean isGamePlaying() {
return GameStatus.PLAYING.equals(numberBaseBallGame.getGameStatus());
}

public BallNumber guessBallNumber() {
return inputManager.inputGuessedBallNumber();
}

}
49 changes: 49 additions & 0 deletions src/main/java/view/InputManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package view;

import domain.ballnumber.BallNumber;
import domain.game.GameResult;
import view.InputView;

public class InputManager {

private InputView inputView;

public InputManager() {
this.inputView = new InputView();
}

public BallNumber inputGuessedBallNumber() {
BallNumber guessedBallNumber = null;
while((guessedBallNumber=tryInputGuessedBallNumber())==null){}
return guessedBallNumber;
}

public BallNumber tryInputGuessedBallNumber() {
BallNumber guessedBallNumber = null;
try {
guessedBallNumber = inputView.inputGuessedBallNumber();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
return guessedBallNumber;
}
}

public GameResult inputGameResult() {
GameResult gameResult = null;
while((gameResult=tryInputGameResult())==null){}
return gameResult;
}

public GameResult tryInputGameResult() {
GameResult gameResult = null;
try {
gameResult = inputView.inputGameResult();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
return gameResult;
}
}

}
63 changes: 63 additions & 0 deletions src/main/java/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package view;

import config.GlobalData;
import domain.ballnumber.BallNumber;
import domain.game.GameResult;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

public class InputView {

private BufferedReader br;

public InputView() {
this.br = new BufferedReader(new InputStreamReader(System.in));
}

public BallNumber inputGuessedBallNumber() throws Exception{
System.out.print("숫자를 입력해주세요 : ");
String input = br.readLine();
validateBallNumberInput(input);
return new BallNumber(stringToIntList(input));
}

public void validateBallNumberInput(String input) {
if(input.length()!= GlobalData.BALL_NUMBER_LENGTH)
throw new IllegalArgumentException(GlobalData.BALL_NUMBER_LENGTH+" 자리 숫자를 입력해주세요.");
Set<Character> numberSet = new HashSet<>();
for(char c : input.toCharArray()) {
validateBallNumberChar(c);
numberSet.add(c);
}
if(numberSet.size()!=GlobalData.BALL_NUMBER_LENGTH)
throw new IllegalArgumentException("숫자는 중복되지 않습니다.");
}

public void validateBallNumberChar(char c) {
if(c<'1' || c>'9') throw new IllegalArgumentException("각 자리는 1 이상 9 이하의 숫자로 이루어져야 합니다.");
}

public List<Integer> stringToIntList(String input) {
List<Integer> result = new ArrayList<>();
for(char c : input.toCharArray()) {
result.add(c-'0');
}
return result;
}

public GameResult inputGameResult() throws Exception{
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
String input = br.readLine();
validateGameResultInput(input);
int selected = input.charAt(0)-'0';
if(selected==1) return GameResult.RESTART;
return GameResult.EXIT;
}

public void validateGameResultInput(String input) {
if(input.length()!=1 || (input.charAt(0)<'1' || input.charAt(0)>'2'))
throw new IllegalArgumentException("1 과 2 중에서 선택해주세요.");
}
}
Loading