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
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ version = '1.0.0'
sourceCompatibility = '1.8'

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
testImplementation "org.junit.jupiter:junit-jupiter:5.7.2"
testImplementation "org.assertj:assertj-core:3.19.0"
implementation 'org.openjdk.jol:jol-core:0.16'
}

test {
useJUnitPlatform()
useJUnitPlatform()
}
17 changes: 17 additions & 0 deletions src/main/java/baseball/console/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package baseball.console;

import baseball.core.Game;
import baseball.core.InputView;
import baseball.core.OutputView;
import baseball.core.RandomBallsGenerator;

public class Application {
public static void main(String[] args) {
InputView inputView = new ConsoleInputView();
OutputView outputView = new ConsoleOutputView();
RandomBallsGenerator randomBallsGenerator = new DefaultRandomBallsGenerator();
Game game = new Game(inputView, outputView, randomBallsGenerator);

game.play();
}
}
43 changes: 43 additions & 0 deletions src/main/java/baseball/console/ConsoleInputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package baseball.console;

import baseball.core.Balls;
import baseball.core.InputView;

import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class ConsoleInputView implements InputView {
private final Scanner scanner = new Scanner(System.in);

@Override
public Balls getBalls(String message) {
Balls result = null;
do {
System.out.print(message);
String input = scanner.nextLine();
List<Integer> numbers = input.chars().boxed().map(c -> c - '0').collect(Collectors.toList());

try {
result = new Balls(numbers);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
} while (result == null);
return result;
}

@Override
public boolean shouldRetry(String message) {
while (true) {
System.out.print(message);
String input = scanner.nextLine().trim();
if (input.equals("1")) {
return true;
}
if (input.equals("2")) {
return false;
}
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/baseball/console/ConsoleOutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package baseball.console;

import baseball.core.OutputView;

public class ConsoleOutputView implements OutputView {
@Override
public void write(String message) {
System.out.print(message);
}
}
23 changes: 23 additions & 0 deletions src/main/java/baseball/console/DefaultRandomBallsGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package baseball.console;

import baseball.core.Balls;
import baseball.core.RandomBallsGenerator;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;

public class DefaultRandomBallsGenerator implements RandomBallsGenerator {
private static final Random random = new Random();

@Override
public Balls generateBalls() {
Set<Integer> numbers = new LinkedHashSet<>();

while (numbers.size() != Balls.BALL_COUNT) {
numbers.add(random.nextInt(9) + 1);
}
return new Balls(new ArrayList<>(numbers));
}
}
46 changes: 46 additions & 0 deletions src/main/java/baseball/core/Ball.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package baseball.core;

import java.util.Objects;

public class Ball {
private static final int VALUE_MIN = 1;
private static final int VALUE_MAX = 9;
private static final int POSITION_MIN = 1;
private static final int POSITION_MAX = 3;
private final int value;
private final int position;

public Ball(int value, int position) {
if (value < VALUE_MIN || VALUE_MAX < value) {
throw new IllegalArgumentException(String.format("value should be between %d to %d", VALUE_MIN, VALUE_MAX));
}
if (position < POSITION_MIN || POSITION_MAX < position) {
throw new IllegalArgumentException(String.format("position should be between %d to %d", POSITION_MIN, POSITION_MAX));
}
this.value = value;
this.position = position;
}

public BallStatus play(Ball other) {
if (this.equals(other)) {
return BallStatus.STRIKE;
}
if (this.value == other.value) {
return BallStatus.BALL;
}
return BallStatus.NOTHING;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Ball ball = (Ball) o;
return value == ball.value && position == ball.position;
}

@Override
public int hashCode() {
return Objects.hash(value, position);
}
}
13 changes: 13 additions & 0 deletions src/main/java/baseball/core/BallStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package baseball.core;

public enum BallStatus {
BALL, NOTHING, STRIKE;

public boolean isStrike() {
return this.equals(BallStatus.STRIKE);
}

public boolean isBall() {
return this.equals(BallStatus.BALL);
}
}
67 changes: 67 additions & 0 deletions src/main/java/baseball/core/Balls.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package baseball.core;

import java.util.*;

public class Balls {
public static final int BALL_COUNT = 3;
private final List<Ball> balls;

public Balls(List<Integer> numbers) {
if (numbers == null || numbers.size() != BALL_COUNT) {
throw new IllegalArgumentException("Balls의 크기는 " + BALL_COUNT + "이어야 합니다.");
}
this.balls = convertIntegerToBall(numbers);
}

private static List<Ball> convertIntegerToBall(List<Integer> numbers) {
List<Ball> balls = new ArrayList<>();
int position = 1;
for (int number : numbers) {
balls.add(new Ball(number, position++));
}
return balls;
}

public PlayResult play(Balls other) {
int strikeCount = 0;
int ballCount = 0;
for (Ball ball : other.balls) {
BallStatus ballStatus = this.play(ball);
if (ballStatus.isStrike()) {
strikeCount += 1;
}
if (ballStatus.isBall()) {
ballCount += 1;
}
}

return new PlayResult(strikeCount, ballCount);
}

private BallStatus play(Ball other) {
Set<BallStatus> result = new HashSet<>();
for (Ball ball : this.balls) {
result.add(ball.play(other));
}
if (result.contains(BallStatus.STRIKE)) {
return BallStatus.STRIKE;
}
if (result.contains(BallStatus.BALL)) {
return BallStatus.BALL;
}
return BallStatus.NOTHING;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Balls balls1 = (Balls) o;
return Objects.equals(balls, balls1.balls);
}

@Override
public int hashCode() {
return Objects.hash(balls);
}
}
38 changes: 38 additions & 0 deletions src/main/java/baseball/core/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package baseball.core;

public class Game {
private static final String NEW_LINE = System.lineSeparator();
private static final String ENTER_INPUT_MESSAGE = "숫자를 입력해 주세요 : ";
private static final String WIN_MESSAGE = "3개의 숫자를 모두 맞히셨습니다! 게임 종료" + NEW_LINE;
private static final String RETRY_MESSAGE = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요." + NEW_LINE;

private final InputView inputView;
private final OutputView outputView;
private final RandomBallsGenerator randomBallsGenerator;
private Balls answer;

public Game(InputView inputView, OutputView outputView, RandomBallsGenerator randomBallsGenerator) {
this.inputView = inputView;
this.outputView = outputView;
this.randomBallsGenerator = randomBallsGenerator;
this.answer = randomBallsGenerator.generateBalls();
}

public void play() {
while (true) {
Balls balls = this.inputView.getBalls(ENTER_INPUT_MESSAGE);
PlayResult playResult = this.answer.play(balls);
this.outputView.write(playResult.getResultMessage() + NEW_LINE);

if (!playResult.isFinished()) {
continue;
}

this.outputView.write(WIN_MESSAGE);
if (!this.inputView.shouldRetry(RETRY_MESSAGE)) {
return;
}
this.answer = this.randomBallsGenerator.generateBalls();
}
}
}
7 changes: 7 additions & 0 deletions src/main/java/baseball/core/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package baseball.core;

public interface InputView {
Balls getBalls(String message);

boolean shouldRetry(String message);
}
5 changes: 5 additions & 0 deletions src/main/java/baseball/core/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package baseball.core;

public interface OutputView {
void write(String message);
}
43 changes: 43 additions & 0 deletions src/main/java/baseball/core/PlayResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package baseball.core;

import java.util.Objects;

public class PlayResult {
private final int strikeCount;
private final int ballCount;

public PlayResult(int strikeCount, int ballCount) {
this.strikeCount = strikeCount;
this.ballCount = ballCount;
}

public boolean isFinished() {
return this.strikeCount == Balls.BALL_COUNT;
}

public String getResultMessage() {
if (0 < this.ballCount && 0 < this.strikeCount) {
return this.ballCount + "볼 " + this.strikeCount + "스트라이크";
}
if (0 < this.strikeCount) {
return this.strikeCount + "스트라이크";
}
if (0 < this.ballCount) {
return this.ballCount + "볼";
}
return "낫싱";
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlayResult that = (PlayResult) o;
return strikeCount == that.strikeCount && ballCount == that.ballCount;
}

@Override
public int hashCode() {
return Objects.hash(strikeCount, ballCount);
}
}
5 changes: 5 additions & 0 deletions src/main/java/baseball/core/RandomBallsGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package baseball.core;

public interface RandomBallsGenerator {
Balls generateBalls();
}
Loading