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

[충남대 BE_이경빈] 미션 제출합니다. #149

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
# java-baseball-precourse
# 카테캠 미니과제 1 - 숫자 야구
## 개요
- 카카오 테크 캠퍼스 1차 미니과제
- 1부터 9까지 서로 다른 수로 이루어진 3자리 숫자를 맞히는 게임
- 사용자는 컴퓨터가 무작위로 선택한 숫자를 맞히기 위해 입력을 반복, 입력 결과에 따른 힌트 부여

## 기술 스택
- 언어: Java 17
- 테스트 라이브러리: JUnit 5, AssertJ

## 기능 목록
- [x] **숫자 생성** - 게임 시작 시 1부터 9까지 서로 다른 수 3개를 무작위로 생성
- [x] **사용자 입력** - 사용자는 3자리 숫자를 입력
- [x] **입력 검증** - 입력받은 숫자가 3자리이며, 각 숫자가 1부터 9까지이고, 중복되지 않는지 확인
- [x] **결과 반환** - 입력받은 숫자와 컴퓨터가 생성한 숫자를 비교하여 힌트/결과 반환
- [x] **게임 반복** - 숫자를 맞혔을 경우, 사용자는 게임을 새로 시작할지 또는 종료할지 선택

## 개발 규칙 및 스타일 가이드
- **코드 스타일**: Google Java Style Guide을 기반으로 하되, 들여쓰기는 4 spaces를 사용
- **커밋 메시지**: AngularJS Git Commit Message Conventions을 기반으로 함
68 changes: 68 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;

public class Application {
private NumberGenerator numberGenerator = new NumberGenerator();
private InputHandler inputHandler = new InputHandler();
private InputValidator inputValidator = new InputValidator();
private ResultCalculator resultCalculator = new ResultCalculator();
private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

public void startGame() {
boolean mainGameContinues = true;

while (mainGameContinues) {
Set<Integer> computerNumbers = numberGenerator.generateRandomNumbers();
boolean roundContinues = true;

while (roundContinues) {
roundContinues = playRound(computerNumbers);
}

mainGameContinues = askToContinue();
}
}

private boolean playRound(Set<Integer> computerNumbers) {
try {
String userInput = inputHandler.getUserInput();
inputValidator.validateInput(userInput);
String result = resultCalculator.calculateResult(computerNumbers, userInput);
System.out.println(result);

if ("3스트라이크".equals(result)) {
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
return false;
}
return true;
} catch (IllegalArgumentException | IOException e) {
System.out.println("에러: " + e.getMessage());
return false; // 에러 발생 시 게임 종료
}
}

private boolean askToContinue() {
System.out.print("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요: ");
try {
String decision = br.readLine();
if ("1".equals(decision)) {
return true;
} else if ("2".equals(decision)) {
return false;
} else {
System.out.println("잘못된 입력입니다. 게임을 종료합니다.");
return false;
}
} catch (IOException e) {
System.out.println("입력 도중 오류가 발생했습니다: " + e.getMessage());
return false;
}
}

public static void main(String[] args) {
Application game = new Application();
game.startGame();
}
}
12 changes: 12 additions & 0 deletions src/main/java/InputHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputHandler {
private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

public String getUserInput() throws IOException {
System.out.print("숫자를 입력해 주세요: ");
return br.readLine();
}
}
22 changes: 22 additions & 0 deletions src/main/java/InputValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import java.util.HashSet;
import java.util.Set;

public class InputValidator {
public void validateInput(String input) {
if (input == null || input.length() != 3) {
throw new IllegalArgumentException("입력은 정확히 3자리 숫자여야 합니다.");
}

Set<Character> seenDigits = new HashSet<>();

for (char ch : input.toCharArray()) {
if (!Character.isDigit(ch) || ch == '0') {
throw new IllegalArgumentException("입력은 1부터 9까지의 숫자여야 합니다.");
}

if (!seenDigits.add(ch)) {
throw new IllegalArgumentException("모든 숫자는 서로 달라야 합니다.");
}
}
}
}
16 changes: 16 additions & 0 deletions src/main/java/NumberGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;

public class NumberGenerator {
public Set<Integer> generateRandomNumbers() {
Set<Integer> numbers = new LinkedHashSet<>();
Random random = new Random();
while (numbers.size() < 3) {
int number = 1 + random.nextInt(9); // 1 to 9
numbers.add(number);
}
return numbers;
}
}
31 changes: 31 additions & 0 deletions src/main/java/ResultCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ResultCalculator {
public String calculateResult(Set<Integer> computerNumbers, String userInput) {
int strikes = 0;
int balls = 0;
List<Integer> computerList = new ArrayList<>(computerNumbers);
int[] userNumbers = userInput.chars().map(c -> c - '0').toArray();

for (int i = 0; i < 3; i++) {
if (userNumbers[i] == computerList.get(i)) {
strikes++;
} else if (computerList.contains(userNumbers[i])) {
balls++;
}
}

if (balls > 0 && strikes > 0) {
return balls + "볼 " + strikes + "스트라이크";
}
if (balls > 0) {
return balls + "볼";
}
if (strikes > 0) {
return strikes + "스트라이크";
}
return "낫싱";
}
}
19 changes: 19 additions & 0 deletions src/test/java/InputValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

class InputValidatorTest {
@Test
void validateInput_ValidInput_ShouldNotThrowException() {
InputValidator validator = new InputValidator();
assertThatCode(() -> validator.validateInput("123")).doesNotThrowAnyException();
}

@Test
void validateInput_InvalidInput_ShouldThrowIllegalArgumentException() {
InputValidator validator = new InputValidator();
assertThatThrownBy(() -> validator.validateInput("112")).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("모든 숫자는 서로 달라야 합니다.");
assertThatThrownBy(() -> validator.validateInput("abc")).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("1부터 9까지의 숫자여야 합니다.");
}
}
16 changes: 16 additions & 0 deletions src/test/java/NumberGeneratorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

import java.util.Set;

class NumberGeneratorTest {
@Test
void generateRandomNumbers_ShouldGenerateThreeUniqueNumbersBetweenOneAndNine() {
NumberGenerator generator = new NumberGenerator();
Set<Integer> numbers = generator.generateRandomNumbers();

assertThat(numbers).hasSize(3);
assertThat(numbers).allMatch(num -> num >= 1 && num <= 9);
assertThat(numbers).doesNotHaveDuplicates();
}
}
31 changes: 31 additions & 0 deletions src/test/java/ResultCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

import java.util.LinkedHashSet;
import java.util.Set;

class ResultCalculatorTest {
@Test
void calculateResult_WhenAllMatch_ShouldReturnThreeStrikes() {
ResultCalculator calculator = new ResultCalculator();
Set<Integer> computerNumbers = new LinkedHashSet<>();
computerNumbers.add(1);
computerNumbers.add(2);
computerNumbers.add(3);
String result = calculator.calculateResult(computerNumbers, "123");

assertThat(result).isEqualTo("3스트라이크");
}

@Test
void calculateResult_NoMatches_ShouldReturnNoting() {
ResultCalculator calculator = new ResultCalculator();
Set<Integer> computerNumbers = new LinkedHashSet<>();
computerNumbers.add(4);
computerNumbers.add(5);
computerNumbers.add(6);
String result = calculator.calculateResult(computerNumbers, "123");

assertThat(result).isEqualTo("낫싱");
}
}