Skip to content
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,30 @@ git checkout main // 기본 브랜치가 main인 경우
git checkout -b 브랜치이름
ex) git checkout -b apply-feedback
```
---
4. 기능 목록 - TDD 구현
- 1~9의 숫자 중 랜덤으로 3개의 숫자를 구한다
- 사용자로부터 입력 받는 3개 숫자 예외처리
- 1~9의 숫자인가?
- 중복 값이 있는가?
- 3자리인가?
- 위치와 숫자 값이 같은 경우 -> 스트라이크
- 위치는 다른데 숫자 값이 같은 경우 -> 볼
- 숫자 값이 다른 경우 -> 낫싱
- 사용자가 입력한 값에 대한 실행 결과를 구한다

```jsx
com / user
123 / 123 -> 3 strike
123 / 142 -> 1 strike, 1 ball

# step 1
1 2 / 1 2 -> strike
3 2 / 1 2 -> ball
1 3 / 1 2 -> nothing

# step 2
123 / 1 1 -> strike
123 / 1 2 -> ball
123 / 1 5 -> nothing
```
35 changes: 35 additions & 0 deletions src/main/java/baseball/Ball.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package baseball;

public class Ball {
// Step 1

private final int position;
private final int ballNum;

public Ball(int position, int ballNum) {
this.position = position;
this.ballNum = ballNum;
}


public BallStatus playBall(Ball ball) {
if(this.equals(ball)) return BallStatus.STRIKE;
if(matchBallNum(ball.ballNum)) return BallStatus.BALL;
return BallStatus.NOTHING;
}

private boolean matchBallNum(int ballNum) {
return this.ballNum == ballNum;
}

@Override
public boolean equals(Object o) {
if(this == o)return true;
if(o == null || this.getClass() != o.getClass()) return false; // 실행 중인 클래스 객체의 정보를 확인
Ball ball = (Ball) o;
return position == ball.position &&
ballNum == ball.ballNum;
}


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

public enum BallStatus {
NOTHING, STRIKE, BALL;

public boolean isNotNothing() {
return this != NOTHING;
}
public boolean isStrike() {
return this == STRIKE;
}
public boolean isBall() {
return this == BALL;
}
}
39 changes: 39 additions & 0 deletions src/main/java/baseball/Balls.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package baseball;

import java.util.ArrayList;
import java.util.List;

public class Balls {
private final List<Ball> balls; // computer balls

public Balls(List<Integer> computer) {
this.balls = getBalls(computer);
}


private static List<Ball> getBalls(List<Integer> computer) {
List<Ball> balls = new ArrayList<>();
for (int i = 0; i < 3; i++) {
balls.add(new Ball(i+1, computer.get(i)));
}
return balls;
}
public Score play(List<Integer> userInput) {
Balls userBalls = new Balls(userInput);
Score result = new Score();
// 비교 분석
for(Ball answer : balls){ // computerBall
BallStatus status = userBalls.playBalls(answer); // 앞 뒤에 들어갈 객체가 바뀌어도 strike,ball 판별에는 문제가 되지 않음
result.report(status);
}
return result;
}

public BallStatus playBalls(Ball userBall) {
return balls.stream()
.map(answer -> answer.playBall(userBall))
.filter(BallStatus::isNotNothing)
.findFirst()
.orElse(BallStatus.NOTHING);
}
}
48 changes: 48 additions & 0 deletions src/main/java/baseball/BallsNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package baseball;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BallsNumber {

public List<Integer> splitNumber(int userNumber) {
List<Integer> userNumList = new ArrayList<>();

while(userNumber > 0) {
userNumList.add(0, userNumber % 10);
userNumber /= 10;
}

return userNumList;
}
public static boolean validateNumber(List<Integer> ballNumbers) {
return areAllNumbersValid(ballNumbers) && areAllNumbersUnique(ballNumbers);
}

// 1~9사이 숫자인지 확인

private static boolean areAllNumbersValid(List<Integer> ballNumbers) {
return ballNumbers.stream().allMatch(BallsNumber::isValidNumber);
}
private static boolean isValidNumber(int x) {
if (!(0 < x && x < 10)) {
System.out.println("1~9 사이 숫자로 이루어진 수를 입력해주세요.");
return false;
}
return true;
}
// 숫자 중복 확인
private static boolean areAllNumbersUnique(List<Integer> ballNumbers) {
return ballNumbers.stream().allMatch(x -> isUniqueNumber(ballNumbers, x));
}
private static boolean isUniqueNumber(List<Integer> ballNumbers, int x) {
if (!(Collections.frequency(ballNumbers, x) == 1)) {
System.out.println("중복 숫자가 없는 수를 입력해주세요.");
return false;
}
return true;

}
}

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

import ui.InputView;
import ui.ResultView;
import utils.MakeRandomNum;

import java.util.List;
import java.util.Scanner;

import static baseball.BallsNumber.validateNumber;

public class BaseBall {
public void game(){
// computer num
MakeRandomNum randomNum = new MakeRandomNum();
Balls answer = new Balls(randomNum.makeRandomNum());

// user num
Scanner sc = new Scanner(System.in);
int strike = 0;

while(strike != 3) {
System.out.print("숫자를 입력해 주세요 : ");
int userInput = sc.nextInt();

// 유효성 검사
BallsNumber ball = new BallsNumber();

List<Integer> ballList = ball.splitNumber(userInput);
if(!validateNumber(ballList)) continue;

strike = ResultView.result(answer.play(ballList));
}

}
public BaseBall() {
while(true){
game();
if(InputView.inputNumber()!=1) return;
}
}

public static void main(String[] args) {
new BaseBall();
}
}
26 changes: 26 additions & 0 deletions src/main/java/baseball/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package baseball;

public class Score {
private int strike = 0;
private int ball = 0;


public int getStrike() {
return this.strike;
}
public int getBall() {
return this.ball;
}

public void report(BallStatus status) {
if(status.isBall()) this.ball += 1;
if(status.isStrike()) this.strike += 1;

}
public boolean isGameEnd() {
return strike == 3;
}
public boolean isNothing() {
return this.strike == 0 && this.ball == 0;
}
}
12 changes: 12 additions & 0 deletions src/main/java/ui/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ui;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class InputView {
public static int inputNumber() {
Scanner sc = new Scanner(System.in);
return sc.nextInt();
}
}
29 changes: 29 additions & 0 deletions src/main/java/ui/ResultView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ui;

import baseball.Score;

public class ResultView {
public static int result(Score score) {
StringBuilder sb = new StringBuilder();
int result = 0;

if(score.isNothing()) {
sb.append("낫싱");
}
if(score.getBall() > 0) {
sb.append(score.getBall()).append("볼 ");
}
if(score.getStrike() > 0){
sb.append(score.getStrike()).append("스트라이크");
result = score.getStrike();
}
if(score.isGameEnd()) {
sb.append("\n")
.append("3개의 숫자를 모두 맞히셨습니다! 게임 종료").append("\n")
.append("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
}
System.out.println(sb);

return result;
}
}
31 changes: 31 additions & 0 deletions src/main/java/utils/MakeRandomNum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MakeRandomNum {
private List<Integer> numList;
private static boolean[] check; // true이면 값이 들어가있다
public MakeRandomNum() {
check = new boolean[10]; // 1~9 사이의 수 파악
}
public List<Integer> makeRandomNum(){
numList = new ArrayList<>();
Random random = new Random();
int idx = 0;
while(idx != 3) {
int num = random.nextInt(9)+1; // 1 ~ 4 까지의 무작위 int 값 리턴
idx = checkDuplicate(idx, num);
}
return numList;
}
public int checkDuplicate(int idx, int num) {
if(!check[num]) {
idx++;
check[num] = true;
numList.add(num);
}
return idx;
}
}
29 changes: 29 additions & 0 deletions src/test/java/baseball/BallTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package baseball;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class BallTest {
// Step 1.
@Test
@DisplayName("userball과 computerball 각각 1개씩 비교 - strike")
void strike() {
Ball computerBall = new Ball(1, 5);

assertThat(computerBall.playBall(new Ball(1, 5))).isEqualTo(BallStatus.STRIKE);
}
@Test
@DisplayName("userball과 computerball 각각 1개씩 비교 - ball")
void ball() {
Ball computerBall = new Ball(1, 5);
assertThat(computerBall.playBall(new Ball(2, 5))).isEqualTo(BallStatus.BALL);
}
@Test
@DisplayName("userball과 computerball 각각 1개씩 비교 - nothing")
void nothing() {
Ball computerBall = new Ball(1, 5);
assertThat(computerBall.playBall(new Ball(2, 6))).isEqualTo(BallStatus.NOTHING);
}
}
Loading