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
125 changes: 124 additions & 1 deletion src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,130 @@
package baseball;

import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
try {
playBaseballGame();
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
}
}

public static void playBaseballGame() {
Scanner scanner = new Scanner(System.in);

System.out.println("숫자 야구 게임을 시작합니다.");
do {
int computerNumber = createRandomNumber();
boolean gameFinished = false;
while (!gameFinished) {
int userNumber = inputNumber(scanner);
validateNumber(userNumber);
gameFinished = checkNumber(userNumber, computerNumber);
}
} while (askForRestart(scanner));
System.out.println("종료되었습니다.");
}

private static final int RESTART = 1;
private static final int END = 2;
public static boolean askForRestart(Scanner scanner) {
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
try {
int restart = scanner.nextInt();
if (restart == RESTART) {
return true;
} else if (restart == END) {
return false;
} else {
throw new IllegalArgumentException("잘못된 입력입니다. 1 또는 2를 입력해주세요.");
}
} catch (InputMismatchException e) {
throw new IllegalArgumentException("숫자만 입력해주세요.");
}
}

//숫자 비교하는 함수
public static boolean checkNumber(int userNumber, int computerNumber) {
// System.out.println("robot: " + computerNumber);

String userNumberToString = String.valueOf(userNumber);
String computerNumberToString = String.valueOf(computerNumber);

int strikes = 0;
int balls = 0;
for (int i = 0; i < 3; i++) {
if (userNumberToString.charAt(i) == computerNumberToString.charAt(i)) {
strikes++;
} else if (computerNumberToString.contains(String.valueOf(userNumberToString.charAt(i)))) {
balls++;
}
}
if (balls > 0 && strikes > 0) {
System.out.println(balls + "볼 " + strikes + "스트라이크");
} else if (balls > 0) {
System.out.println(balls + "볼");
} else if (strikes > 0) {
System.out.println(strikes + "스트라이크");
} else {
System.out.println("낫싱");
}

if (strikes == 3) {
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
return true;
}

return false;
}

//컴퓨터의 랜덤한 수 생성 함수
public static int createRandomNumber() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for문이나, while문으로 작성하는 방법을 생각해보시면 더 좋을 것 같습니다!

Random random = new Random();
int firstDigit = random.nextInt(9) + 1;
int secondDigit, thirdDigit;

do {
secondDigit = random.nextInt(9) + 1;
} while (secondDigit == firstDigit);

do {
thirdDigit = random.nextInt(9) + 1;
} while (thirdDigit == firstDigit || thirdDigit == secondDigit);

return firstDigit * 100 + secondDigit * 10 + thirdDigit;
}

// 숫자 입력 받는 함수
public static int inputNumber(Scanner scanner) {
System.out.print("숫자를 입력해주세요 : ");
try {
return scanner.nextInt();
} catch (InputMismatchException e ) {
throw new IllegalArgumentException("입력한 값이 숫자가 아닙니다.");
}
}

// 잘못된 입력 예외 처리 함수
public static void validateNumber(int number) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate를 꼼꼼히 잘 하셨네요👍

if (number < 100 || number > 999) {
throw new IllegalArgumentException("입력한 숫자는 3자리 숫자가 아닙니다.");
}

String numberToString = String.valueOf(number);
char firstDigit = numberToString.charAt(0);
char secondDigit = numberToString.charAt(1);
char thirdDigit = numberToString.charAt(2);

if (firstDigit == secondDigit || secondDigit == thirdDigit || thirdDigit == firstDigit) {
throw new IllegalArgumentException("입력한 숫자는 각 자리가 중복됩니다.");
}

if (firstDigit == '0' || secondDigit == '0' || thirdDigit == '0') {
throw new IllegalArgumentException("1부터 9까지 숫자를 입력해주세요.");
}
}
}
98 changes: 74 additions & 24 deletions src/test/java/baseball/ApplicationTest.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,85 @@
package baseball;

import camp.nextstep.edu.missionutils.test.NsTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest;
import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

class ApplicationTest extends NsTest {
@Test
void 게임종료_후_재시작() {
assertRandomNumberInRangeTest(
() -> {
run("246", "135", "1", "597", "589", "2");
assertThat(output()).contains("낫싱", "3스트라이크", "1볼 1스트라이크", "3스트라이크", "게임 종료");
},
1, 3, 5, 5, 8, 9
);
import static org.junit.jupiter.api.Assertions.*;

class ApplicationTest {

private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;

@BeforeEach
void setUpStreams() {
System.setOut(new PrintStream(outContent));
}

@Test
void 예외_테스트() {
assertSimpleTest(() ->
assertThatThrownBy(() -> runException("1234"))
.isInstanceOf(IllegalArgumentException.class)
);
@DisplayName("createRandomNumber 메서드는 3자리 숫자를 반환해야 한다")
void testCreateRandomNumber() {
for (int i = 0; i < 100; i++) {
int number = Application.createRandomNumber();
assertTrue(number >= 100 && number <= 999);
String numberStr = String.valueOf(number);
assertEquals(3, numberStr.chars().distinct().count());
assertFalse(numberStr.contains("0"));
}
}

@Override
public void runMain() {
Application.main(new String[]{});
@ParameterizedTest
@ValueSource(ints = {123, 456, 789})
@DisplayName("validateNumber 메서드는 유효한 입력을 받아들여야 한다")
void testValidateNumberWithValidInput(int number) {
assertDoesNotThrow(() -> Application.validateNumber(number));
}
}

@ParameterizedTest
@ValueSource(ints = {100, 999, 12, 1000, 111, 990})
@DisplayName("validateNumber 메서드는 잘못된 입력에 대해 예외를 발생시켜야 한다")
void testValidateNumberWithInvalidInput(int number) {
assertThrows(IllegalArgumentException.class, () -> Application.validateNumber(number));
}

@Test
@DisplayName("checkNumber 메서드는 정확한 결과를 반환해야 한다")
void testCheckNumber() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3경우를 따로 만들면 더 좋을 것 같아요!

assertTrue(Application.checkNumber(123, 123));
assertFalse(Application.checkNumber(123, 456));

Application.checkNumber(123, 145);
assertTrue(outContent.toString().contains("1스트라이크"));

outContent.reset();
Application.checkNumber(123, 321);
assertTrue(outContent.toString().contains("2볼 1스트라이크"));

outContent.reset();
Application.checkNumber(123, 456);
assertTrue(outContent.toString().contains("낫싱"));
}

// 입력을 숫자로 받는 법을 모르겠음
// @Test
// @DisplayName("게임이 정상적으로 종료되어야 한다")
// void testGameFlow() {
// int input = 123;
// System.setIn(new ByteArrayInputStream(input.get()));
//
// int input2 = 2;
//
// Application.playBaseballGame();
//
// String output = outContent.toString();
// assertTrue(output.contains("숫자 야구 게임을 시작합니다."));
// assertTrue(output.contains("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."));
// assertTrue(output.contains("게임 종료"));
// }
}