Skip to content
Open
56 changes: 56 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# 📝설계 구조
- Application : 애플리케이션 실행을 관리한다.
- MainController : 데이터 전달 및 중계 역할을 한다.
- view
- InputView : 입력과 관련된 책임 관리한다.
- OutputView : 출력과 관련된 책임 관리한다.
- message
- ErrorMessage : 에러 메시지를 관리한다.
- ViewMessage : 출력 메시지를 관리한다.
- domain
- Computer : List<Integer>를 멤버변수로 갖는다
- User : List<Integer>를 멤버변수로 갖는다
- Numbers : List<Integer>를 관리하는 일급 컬렉션
# 💪 프로젝트 개요
숫자 야구 게임을 구현한다. <br>
서로 다른 3자리의 수를 맞춰야한다. 실패시 힌트가 나온다.
게임끝난경우 재시작 or 종료를 1,2 를 선택할수있다.

# 📝 구현 기능 목록
### 게임 초기화

- [x] 랜덤한 3자리 숫자 생성가눙

- [x] 사용자 입력받기
- [x] `출력 문구` : "숫자를 입력해주세요 : "
- [x] 서로 다른 3자리수 입력받기
- [x] `예외처리` : 빈 문자열 입력 검증
- [x] `예외처리` : 3자리 초과 입력 검증
- [x] `예외처리` : 숫자외 문자 입력 검증
- [x] `예외처리` : 음수 입력 검증
- [x] `예외처리` : 중복되는 숫자 검증


### 게임 진행
- [x] 게임시작 문구 출력
- [x] `출력문구' : "숫자 야구 게임을 시작합니다."

- [x] 매 실행결과 출력 한다.


- [x] 게임 기능
- [x] 사용자가 입력과 컴퓨터 입력 숫자 비교
- [x] 같은 수가 같은 자리에 있으면 스트라이크
- [x] 다른 자리에 있으면 볼
- [x] 같은 수가 전혀 없으면 낫싱
- [x] 실패시 힌트 제공




### 게임 종료
- [x] `출력문구` : 3개의 숫자를 모두 맞히셨습니다! 게임 종료
게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.

- [x] 재시작 기능
- [ ] 1 또는 2 이외의 값입력시 예외처리
3 changes: 2 additions & 1 deletion src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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

import baseball.domain.Computer;
import baseball.domain.Numbers;
import baseball.domain.User;
import baseball.view.OutputView;
import camp.nextstep.edu.missionutils.Console;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MainController {
public void run() {
Computer computerNumbers = gameInit();
gameProceed(computerNumbers);
askForRestart(computerNumbers);
}


private static void gameProceed(Computer computerNumbers) {
boolean isCorrect;
do {
User userNumbers = new User(readUserNumbers());
isCorrect = computerNumbers.compareNumbers(userNumbers);
} while (!isCorrect);


}


private static Computer gameInit() {
Computer computerNumbers = new Computer(Numbers.createRandomNumber());
System.out.println("숫자 야구 게임을 시작합니다.");
return computerNumbers;
}
private static void askForRestart(Computer computerNumbers) {
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
String input = Console.readLine();

if (input.equals("1")) {
computerNumbers.resetNumbers();
gameProceed(computerNumbers);
}
if (input.equals("2")) {
System.out.println("게임 종료");
}
}


private static Numbers readUserNumbers() {
System.out.printf("숫자를 입력해주세요 : ");
String userInput = Console.readLine();

validateisPositiveInteger(userInput);

validateStringBlank(userInput);
validateStringLegnth(userInput);
validateDuplicatedInput(userInput);

return readStringToNumbers(userInput);
}

private static Numbers readStringToNumbers(String userInput) {
List<Integer> userNumbers = new ArrayList<>();

for (int i = 0; i < userInput.length(); i++) {
int number = Integer.parseInt(String.valueOf(userInput.charAt(i)));
userNumbers.add(number);
}
return new Numbers(userNumbers);
}

private static void validateisPositiveInteger(String userInput) {
// 문자열이 정확히 3자여야 함을 확인
if (userInput.length() != 3) {
throw new IllegalArgumentException("입력은 반드시 3개를 초과할수없습니다.");
}

// 문자열의 모든 문자가 '1'에서 '9' 사이의 숫자인지 확인
for (char c : userInput.toCharArray()) {
if (c < '1' || c > '9') {
throw new IllegalArgumentException("문자열은 1부터 9까지의 숫자만 포함해야 합니다.");
}
}
}

private static void validateDuplicatedInput(String userInput) {
Set<Character> uniqueChar = new HashSet<>();
for (int i = 0; i < userInput.length(); i++) {
char currentChar = userInput.charAt(i);

if (uniqueChar.contains(currentChar)) {
throw new IllegalArgumentException("중복된 숫자가 포함되어 있습니다.");
}
uniqueChar.add(currentChar);
}

}

private static void validateStringBlank(String userInput) {
if (userInput.isBlank()) {
throw new IllegalArgumentException("빈값은 입력할 수 없습니다.");
}
}

private static void validateStringLegnth(String userInput) {
if (userInput.length() != 3) {
throw new IllegalArgumentException("입력은 반드시 3개의 숫자여야 합니다.");
}
}


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

import baseball.view.OutputView;
import camp.nextstep.edu.missionutils.Console;
import java.util.List;

public class Computer {

private static Numbers computerNumbers;

public Computer(Numbers computerNumbers) {
Computer.computerNumbers = computerNumbers;
}

public List<Integer> getComputerNumbers() {
return computerNumbers.getNumbers();
}

public static boolean compareNumbers(User userNumbers) {
List<Integer> computerNumberList = computerNumbers.getNumbers();
List<Integer> userNumberList = userNumbers.getUserNumbers();

int strikes = 0;
int balls = 0;
boolean result = false;

//스트라이크, 볼 체크로직
for (int i = 0; i < userNumberList.size(); i++) {
int userNumber = userNumberList.get(i);

if (computerNumberList.contains(userNumber) && computerNumberList.indexOf(userNumber) != i) {
balls++; // 값은 일치하지만 위치가 다르면 볼
}
if (userNumberList.get(i) == computerNumberList.get(i)) {
strikes++; // 값과 위치가 모두 일치하면 스트라이크
}
}
if (strikes == 3){
result = true;
}
OutputView.printGameResult(strikes,balls);
return result;
}

public void resetNumbers() {
computerNumbers =Numbers.createRandomNumber();
}
}
25 changes: 25 additions & 0 deletions src/main/java/baseball/domain/Numbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package baseball.domain;

import camp.nextstep.edu.missionutils.Randoms;
import java.util.ArrayList;
import java.util.List;

public record Numbers(List<Integer> numbers) {
public List<Integer> getNumbers() {
return numbers;
}
public static Numbers createRandomNumber() {
List<Integer> numbers = new ArrayList<>();

while (true) {
int randomNumber = Randoms.pickNumberInRange(1, 9);
if (!numbers.contains(randomNumber)) {
numbers.add(randomNumber);
}
if (numbers.size() == 3) {
break;
}
}
return new Numbers(numbers);
}
}
14 changes: 14 additions & 0 deletions src/main/java/baseball/domain/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package baseball.domain;

import java.util.List;

public class User {
private final Numbers userNumbers;

public User(Numbers userNumbers) {
this.userNumbers = userNumbers;
}
public List<Integer> getUserNumbers() {
return userNumbers.getNumbers();
}
}
4 changes: 4 additions & 0 deletions src/main/java/baseball/message/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package baseball.message;

public enum ErrorMessage {
}
4 changes: 4 additions & 0 deletions src/main/java/baseball/message/ViewMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package baseball.message;

public enum ViewMessage {
}
4 changes: 4 additions & 0 deletions src/main/java/baseball/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package baseball.view;

public class InputView {
}
26 changes: 26 additions & 0 deletions src/main/java/baseball/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package baseball.view;

import baseball.domain.Computer;

public class OutputView {


public static void printGameResult(int strikes, int balls) {
if (strikes == 3) {
System.out.println("3스트라이크");
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
}
if (strikes == 0 && balls == 0) {
System.out.println("낫싱");
}
if (balls !=0 && strikes ==0 ) {
System.out.println(balls+"볼");
}
if (balls ==0 && strikes !=0 ) {
System.out.println(strikes+"스트라이크");
}
if (balls != 0 && strikes != 0) {
System.out.println(balls +"볼 "+ strikes + "스트라이크");
}
}
}
57 changes: 57 additions & 0 deletions src/test/java/baseball/domain/ComputerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package baseball.domain;

import static baseball.domain.Computer.compareNumbers;
import static org.junit.jupiter.api.Assertions.*;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;

class ComputerTest {
private static Computer computerNumbers;
private static User user;

@BeforeEach
void setUp() {
// 예시로 컴퓨터가 선택한 3자리 숫자를 설정
computerNumbers = new Computer(new Numbers(Arrays.asList(1, 2, 3)));
}

@Test
@DisplayName("3 스트라이크 테스트")
void compareNumbersIsTrueTest() {
user = new User(new Numbers(Arrays.asList(1, 2, 3)));
assertTrue(compareNumbers(user));
}


@DisplayName("3볼, 스트라이크,볼 혼합, 전혀다른경우 테스트")
@ParameterizedTest
@MethodSource("provideUserNumbers")
void compareNumbersIsFalseTest() {
user = new User(new Numbers(Arrays.asList(3, 1, 2)));
assertFalse(compareNumbers(user));
}
static Stream<List<Integer>> provideUserNumbers() {
return Stream.of(
Arrays.asList(3, 1, 2), // 3 볼
Arrays.asList(1, 3, 2), // 2 스트라이크, 1 볼
Arrays.asList(4, 5, 6) // 전혀 다른 경우.
);
}




@Test
@Disabled
void resetNumbers() {
}
}
Loading