Skip to content
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

feat : 숫자야구게임 구현 #113

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
10 changes: 10 additions & 0 deletions src/main/java/baseball/BaseballApp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package baseball;

import baseball.controller.BaseballController;

public class BaseballApp {
public static void main(String[] args) {
BaseballController baseballController = BaseballConfig.set();
baseballController.start();
}
}
16 changes: 16 additions & 0 deletions src/main/java/baseball/BaseballConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package baseball;

import baseball.controller.BaseballController;
import baseball.model.entity.AnswerNumberImpl;
import baseball.model.service.BaseballService;
import baseball.model.service.BaseballServiceImpl;
import baseball.model.validator.InputValidatorImpl;
import baseball.view.InputView;
import baseball.view.OutputView;

public class BaseballConfig {
public static BaseballController set() {
BaseballService baseballService = new BaseballServiceImpl(new InputValidatorImpl(), new AnswerNumberImpl());
return new BaseballController(new InputView(), new OutputView(), baseballService);
}
}
60 changes: 60 additions & 0 deletions src/main/java/baseball/controller/BaseballController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package baseball.controller;

import baseball.model.dto.BaseballGameResultDto;
import baseball.model.service.BaseballService;
import baseball.view.InputView;
import baseball.view.OutputView;

public class BaseballController {

private final InputView inputView;

private final OutputView outputView;

private final BaseballService baseballService;

public BaseballController(InputView inputView, OutputView outputView, BaseballService baseballService) {
this.inputView = inputView;
this.outputView = outputView;
this.baseballService = baseballService;
}

public void start() {
try {
String numbers = inputView.number();
baseballService.validateInputValue(numbers);
BaseballGameResultDto gameResult = baseballService.getGameResult(numbers);
outputView.result(gameResult);
end(gameResult.getComplete());
} catch (IllegalArgumentException e) {
outputView.exception(e.getMessage());
start();
}
}

private void end(Boolean complete) {
if (complete) {
retry();
}

if (!complete) {
start();
}
}

private void retry() {
String retry = inputView.retry();

try {
baseballService.validateRetryInput(retry);
} catch (NumberFormatException e) {
outputView.exception(e.getMessage());
retry();
}

if (retry.equals("1")) {
baseballService.resetAnswerNumber();
start();
}
}
}
35 changes: 35 additions & 0 deletions src/main/java/baseball/model/dto/BaseballGameResultDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package baseball.model.dto;

public class BaseballGameResultDto {

private final Integer strikes;

private final Integer balls;

private final Boolean nothing;

private final Boolean complete;

public BaseballGameResultDto(Integer strikes, Integer balls, Boolean nothing, Boolean complete) {
this.strikes = strikes;
this.balls = balls;
this.nothing = nothing;
this.complete = complete;
}

public Integer getStrikes() {
return strikes;
}

public Integer getBalls() {
return balls;
}

public Boolean getNothing() {
return nothing;
}

public Boolean getComplete() {
return complete;
}
}
14 changes: 14 additions & 0 deletions src/main/java/baseball/model/entity/AnswerNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package baseball.model.entity;

public interface AnswerNumber {

Integer countStrikes(String number);

Integer countBalls(String number);

Boolean isNothing(String number);

Boolean isComplete(String number);

void resetAnswerNumber();
}
86 changes: 86 additions & 0 deletions src/main/java/baseball/model/entity/AnswerNumberImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package baseball.model.entity;

import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class AnswerNumberImpl implements AnswerNumber {

private String answerNumber;

private final Integer limit = 3;

public AnswerNumberImpl() {
this.answerNumber = generateRandomNumber();
}

private String generateRandomNumber() {
Set<Integer> randomNumbers = getRandomNumberSet(1, 11, limit);

return randomNumbers.stream()
.map(String::valueOf)
.collect(Collectors.joining());
}

private Set<Integer> getRandomNumberSet(int origin, int bound, int limit) {
Random random = new Random();

return random.ints(origin, bound)
.distinct()
.limit(limit)
.boxed()
.collect(Collectors.toSet());
}

@Override
public Integer countStrikes(String number) {
String[] answerNumbers = splitInput(answerNumber);
String[] numbers = splitInput(number);

return (int) IntStream.range(0, limit)
.filter(i -> answerNumbers[i].equals(numbers[i]))
.count();
}

@Override
public Integer countBalls(String number) {
String[] answerNumbers = splitInput(answerNumber);
String[] numbers = splitInput(number);

return (int) IntStream.range(0, limit)
.filter(i -> isBall(numbers[i], i, answerNumbers))
.count();
}

private boolean isBall(String str, int index, String[] stringArr) {

return IntStream.range(0, limit)
.anyMatch(i -> i != index && stringArr[i].equals(str));
}

@Override
public Boolean isNothing(String number) {
if (countStrikes(number).equals(0) && countBalls(number).equals(0)) {
return true;
}
return false;
}

@Override
public Boolean isComplete(String number) {
if (countStrikes(number).equals(limit)) {
return true;
}
return false;
}

@Override
public void resetAnswerNumber() {
this.answerNumber = generateRandomNumber();
}

private String[] splitInput(String input) {
return input.split("");
}
}
14 changes: 14 additions & 0 deletions src/main/java/baseball/model/service/BaseballService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package baseball.model.service;

import baseball.model.dto.BaseballGameResultDto;

public interface BaseballService {

void validateInputValue(String input);

BaseballGameResultDto getGameResult(String input);

void resetAnswerNumber();

void validateRetryInput(String input);
}
44 changes: 44 additions & 0 deletions src/main/java/baseball/model/service/BaseballServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package baseball.model.service;

import baseball.model.dto.BaseballGameResultDto;
import baseball.model.entity.AnswerNumber;
import baseball.model.validator.InputValidator;

public class BaseballServiceImpl implements BaseballService {

private final InputValidator inputValidator;

private final AnswerNumber answerNumber;

public BaseballServiceImpl(InputValidator inputValidator, AnswerNumber answerNumber) {
this.inputValidator = inputValidator;
this.answerNumber = answerNumber;
}

@Override
public void validateInputValue(String input) {
inputValidator.validateDistinctInput(input);
inputValidator.validateThreeInput(input);
inputValidator.validateNaturalNumbers(input);
}

@Override
public BaseballGameResultDto getGameResult(String input) {
Integer strikes = answerNumber.countStrikes(input);
Integer balls = answerNumber.countBalls(input);
Boolean nothing = answerNumber.isNothing(input);
Boolean complete = answerNumber.isComplete(input);

return new BaseballGameResultDto(strikes, balls, nothing, complete);
}

@Override
public void resetAnswerNumber() {
answerNumber.resetAnswerNumber();
}

@Override
public void validateRetryInput(String input) {
inputValidator.validateOneOrTwo(input);
}
}
12 changes: 12 additions & 0 deletions src/main/java/baseball/model/validator/InputValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package baseball.model.validator;

public interface InputValidator {

void validateNaturalNumbers(String input);

void validateDistinctInput(String input);

void validateThreeInput(String input);

void validateOneOrTwo(String input);
}
62 changes: 62 additions & 0 deletions src/main/java/baseball/model/validator/InputValidatorImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package baseball.model.validator;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public class InputValidatorImpl implements InputValidator {

private final String NATURAL_NUMBERS_MESSAGE = "각 자리는 자연수로만 이루어져야 합니다.";
private final String DISTINCT_INPUT_MESSAGE = "서로 다른 수로 이루어져야 합니다.";
private final String THREE_INPUT_MESSAGE = "3자리 수로 이루어져야 합니다.";
private final String ONE_OR_TWO_MESSAGE = "입력은 1 또는 2만 가능합니다.";

@Override
public void validateNaturalNumbers(String input) {
boolean result = Arrays.stream(splitInput(input))
.mapToInt(this::inputToInteger)
.allMatch(n -> n > 0);

if (!result) {
throw new IllegalArgumentException(NATURAL_NUMBERS_MESSAGE);
}
}

private Integer inputToInteger(String s) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(NATURAL_NUMBERS_MESSAGE);
}
}

@Override
public void validateDistinctInput(String input) {
String[] splitInput = splitInput(input);

Set<String> distinctValues = Arrays.stream(splitInput)
.collect(Collectors.toSet());

if (distinctValues.size() != splitInput.length) {
throw new IllegalArgumentException(DISTINCT_INPUT_MESSAGE);
}
}

@Override
public void validateThreeInput(String input) {
if (input.length() != 3) {
throw new IllegalArgumentException(THREE_INPUT_MESSAGE);
}
}

@Override
public void validateOneOrTwo(String input) {
if (!input.equals("1") && !input.equals("2")) {
throw new IllegalArgumentException(ONE_OR_TWO_MESSAGE);
}
}

private String[] splitInput(String input) {
return input.split("");
}
}
23 changes: 23 additions & 0 deletions src/main/java/baseball/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package baseball.view;


import java.util.Scanner;

public class InputView {

private final Scanner scanner;

public InputView() {
this.scanner = new Scanner(System.in);
}

public String number() {
System.out.print("숫자를 입력해 주세요 : ");
return scanner.nextLine();
}

public String retry() {
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
return scanner.nextLine();
}
}
Loading