Skip to content

Commit 4adc604

Browse files
committed
숫자야구게임 구현
1 parent bd693f1 commit 4adc604

File tree

10 files changed

+274
-0
lines changed

10 files changed

+274
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.github.gunkim.baseball;
2+
3+
import io.github.gunkim.baseball.application.ConsoleInput;
4+
import io.github.gunkim.baseball.application.ConsoleOutput;
5+
import io.github.gunkim.baseball.application.RandomNumberInput;
6+
import io.github.gunkim.baseball.domain.BaseBallGame;
7+
8+
public class Application {
9+
private static final int TOTAL_BALL_COUNT = 3;
10+
private static final boolean SHOULD_DISPLAY_ANSWER = true;
11+
12+
public static void main(final String[] args) {
13+
new BaseBallGame(
14+
new ConsoleInput(TOTAL_BALL_COUNT),
15+
new RandomNumberInput(TOTAL_BALL_COUNT),
16+
new ConsoleOutput(),
17+
TOTAL_BALL_COUNT,
18+
SHOULD_DISPLAY_ANSWER
19+
).start();
20+
}
21+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.github.gunkim.baseball.application;
2+
3+
import io.github.gunkim.baseball.domain.BallNumber;
4+
import io.github.gunkim.baseball.domain.BallNumbers;
5+
import io.github.gunkim.baseball.domain.Input;
6+
7+
import java.util.Scanner;
8+
9+
public class ConsoleInput implements Input {
10+
private static final Scanner SCANNER = new Scanner(System.in);
11+
12+
private final int ballCount;
13+
14+
public ConsoleInput(final int ballCount) {
15+
this.ballCount = ballCount;
16+
}
17+
18+
@Override
19+
public BallNumbers ballNumbers() {
20+
final String input = SCANNER.nextLine();
21+
if (input.length() != ballCount) {
22+
throw new IllegalArgumentException("3자리 숫자를 입력해주세요.");
23+
}
24+
if (input.chars().distinct().count() != ballCount) {
25+
throw new IllegalArgumentException("중복되지 않는 숫자를 입력해주세요.");
26+
}
27+
if (input.chars().anyMatch(c -> c < '1' || c > '9')) {
28+
throw new IllegalArgumentException("1부터 9까지의 숫자를 입력해주세요.");
29+
}
30+
return new BallNumbers(input.chars()
31+
.mapToObj(c -> (char) c)
32+
.map(String::valueOf)
33+
.map(Integer::parseInt)
34+
.map(BallNumber::of)
35+
.toList());
36+
}
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.github.gunkim.baseball.application;
2+
3+
import io.github.gunkim.baseball.domain.BallNumbers;
4+
import io.github.gunkim.baseball.domain.Output;
5+
import io.github.gunkim.baseball.domain.Result;
6+
7+
public class ConsoleOutput implements Output {
8+
@Override
9+
public void inputMessage() {
10+
System.out.println("숫자를 입력해주세요 : ");
11+
}
12+
13+
@Override
14+
public void computerBallNumbers(BallNumbers ballNumbers) {
15+
System.out.println("정답 : " + ballNumbers);
16+
}
17+
18+
@Override
19+
public void gameEndedMessage(int ballCount) {
20+
System.out.printf("%d개의 숫자를 모두 맞히셨습니다! 게임 종료%n", ballCount);
21+
}
22+
23+
@Override
24+
public void nothingMessage() {
25+
System.out.println("낫싱");
26+
}
27+
28+
@Override
29+
public void strikeAndBallMessage(Result result) {
30+
System.out.printf("%d 스트라이크 %d 볼%n", result.strike(), result.ball());
31+
}
32+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.github.gunkim.baseball.application;
2+
3+
4+
import io.github.gunkim.baseball.domain.BallNumber;
5+
import io.github.gunkim.baseball.domain.BallNumbers;
6+
import io.github.gunkim.baseball.domain.Input;
7+
8+
import java.util.ArrayList;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
import java.util.List;
12+
13+
public class RandomNumberInput implements Input {
14+
private final BallNumbers ballNumbers;
15+
16+
public RandomNumberInput(final BallNumbers ballNumbers) {
17+
this.ballNumbers = ballNumbers;
18+
}
19+
20+
public RandomNumberInput(final int ballCount) {
21+
this(new BallNumbers(generateRandomBallNumbers(ballCount)));
22+
}
23+
24+
private static List<BallNumber> generateRandomBallNumbers(final int ballCount) {
25+
List<BallNumber> ballNumbers = new ArrayList<>(Arrays.stream(BallNumber.values()).toList());
26+
Collections.shuffle(ballNumbers);
27+
return ballNumbers.subList(0, ballCount);
28+
}
29+
30+
@Override
31+
public BallNumbers ballNumbers() {
32+
return ballNumbers;
33+
}
34+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
public enum BallNumber {
4+
ONE(1),
5+
TWO(2),
6+
THREE(3),
7+
FOUR(4),
8+
FIVE(5),
9+
SIX(6),
10+
SEVEN(7),
11+
EIGHT(8),
12+
NINE(9);
13+
14+
private final int number;
15+
16+
BallNumber(final int number) {
17+
this.number = number;
18+
}
19+
20+
public static BallNumber of(final int number) {
21+
for (BallNumber ballNumber : values()) {
22+
if (ballNumber.number() == number) {
23+
return ballNumber;
24+
}
25+
}
26+
throw new IllegalArgumentException("Invalid BallNumber: " + number);
27+
}
28+
29+
public int number() {
30+
return number;
31+
}
32+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
import java.util.List;
4+
5+
import static java.util.stream.Collectors.joining;
6+
7+
public class BallNumbers {
8+
private final List<BallNumber> ballNumbers;
9+
10+
public BallNumbers(List<BallNumber> ballNumbers) {
11+
this.ballNumbers = ballNumbers;
12+
}
13+
14+
public Result match(final BallNumbers otherBalls) {
15+
int strike = 0, ball = 0;
16+
17+
for (int i = 0; i < this.ballNumbers.size(); i++) {
18+
final BallNumber userBall = this.ballNumbers.get(i);
19+
final BallNumber computerBall = otherBalls.ballNumbers.get(i);
20+
21+
if (userBall.equals(computerBall)) {
22+
strike++;
23+
} else if (this.hasBallNumber(userBall)) {
24+
ball++;
25+
}
26+
}
27+
28+
return new Result(strike, ball);
29+
}
30+
31+
private boolean hasBallNumber(BallNumber ballNumber) {
32+
return this.ballNumbers.contains(ballNumber);
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return ballNumbers.stream()
38+
.map(BallNumber::number)
39+
.map(String::valueOf)
40+
.collect(joining());
41+
}
42+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
public class BaseBallGame {
4+
5+
private final Input userInput;
6+
private final Input computerInput;
7+
private final Output output;
8+
private final int totalBallCount;
9+
private final boolean displayAnswer;
10+
11+
public BaseBallGame(Input userInput, Input computerInput, Output output, int totalBallCount, boolean displayAnswer) {
12+
this.userInput = userInput;
13+
this.computerInput = computerInput;
14+
this.output = output;
15+
this.totalBallCount = totalBallCount;
16+
this.displayAnswer = displayAnswer;
17+
}
18+
19+
public void start() {
20+
while (true) {
21+
if (displayAnswer) {
22+
output.computerBallNumbers(computerInput.ballNumbers());
23+
}
24+
output.inputMessage();
25+
final BallNumbers userBallNumbers = userInput.ballNumbers();
26+
final BallNumbers computerBallNumbers = computerInput.ballNumbers();
27+
final Result matchResult = userBallNumbers.match(computerBallNumbers);
28+
if (checkGameEnd(matchResult)) break;
29+
}
30+
}
31+
32+
private boolean checkGameEnd(final Result result) {
33+
if (result.isAllStrike()) {
34+
output.gameEndedMessage(totalBallCount);
35+
return true;
36+
}
37+
if (result.isNothing()) {
38+
output.nothingMessage();
39+
} else {
40+
output.strikeAndBallMessage(result);
41+
}
42+
return false;
43+
}
44+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
public interface Input {
4+
BallNumbers ballNumbers();
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
public interface Output {
4+
void inputMessage();
5+
6+
void computerBallNumbers(BallNumbers ballNumbers);
7+
8+
void gameEndedMessage(int ballCount);
9+
10+
void nothingMessage();
11+
12+
void strikeAndBallMessage(Result result);
13+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.github.gunkim.baseball.domain;
2+
3+
public record Result(
4+
int strike,
5+
int ball
6+
) {
7+
public boolean isAllStrike() {
8+
return ball == 0 && strike > 0;
9+
}
10+
11+
public boolean isNothing() {
12+
return strike == 0 && ball == 0;
13+
}
14+
}

0 commit comments

Comments
 (0)