Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
4 changes: 4 additions & 0 deletions src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package baseball;

import baseball.game.Game;

public class Application {
public static void main(String[] args) {
//TODO: 숫자 야구 게임 구현
Game game = new Game();
game.start();
}
}
133 changes: 133 additions & 0 deletions src/main/java/baseball/game/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package baseball.game;

import camp.nextstep.edu.missionutils.Console;
import camp.nextstep.edu.missionutils.Randoms;

public class Game {

public void start(){

while(true){
//랜덤 숫자 배열 생성
int[] question = makeQuestion();

//3스트라이크면 중단
boolean result = false;
while(!result){

System.out.print("숫자를 입력해주세요 : ");
// 예외처리 필요
int[] inputNumbers = inputNumbers();

// 스트라이크, 볼 체크
String check = checkResult(question, inputNumbers);

// 결과처리
result = printResult(check);
}

// restart or not
System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
String resume = Console.readLine();
if(resume.equals("2")){
break;
}
}



}

public int[] makeQuestion(){
int[] question = new int[3];
for(int i = 0; i<3; i++){
int n = Randoms.pickNumberInRange(1, 9);
Copy link

Choose a reason for hiding this comment

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

range가 2-7, 1-7로 바뀌어도 큰 변동이 없도록 수정해보세요.

question[i] = n;
}

// 중복체크 필요
boolean flag = duplicateCheck(question);
if(flag){
return question;
}
return makeQuestion();
Copy link
Collaborator

Choose a reason for hiding this comment

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

변수명을 flag라고 지었을 때 어떤 역할을 하는지 파악하기 어렵습니다. isDuplicated로 바꾸면 가독성이 향상될 것 같습니다.

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

질문의 개수가 4개로 바뀌어도 유지보수가 용이하게 리팩토링 해봅시다.


public boolean duplicateCheck(int[]question){
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(question[i]==question[j]&&i!=j){
return false;
}
}
}
return true;
}

public int[] inputNumbers(){
int[] arr = new int[3];
String str = Console.readLine();
String[] split = str.split("");

if(str.length()==3){
for(int i = 0; i<3; i++){
int temp = Integer.parseInt(split[i]);
if(temp==0){
throw new IllegalArgumentException();
}
arr[i] = temp;
}

boolean duplicate = duplicateCheck(arr);
if(duplicate){
return arr;
}
throw new IllegalArgumentException();
}
throw new IllegalArgumentException();
Copy link

Choose a reason for hiding this comment

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

아래 비교 예시를 보고 이 함수를 리팩토링 해보세요.

AS IS

if (con1) {
   if (con2) {
       // 조건이 많아질 수 록 depth가 깊어져서 가독성이 떨어짐
       return result;
   }
   throw new IllegalArgumentException();
}
throw new IllegalArgumentException();

TO BE

if (!con1) {
   throw new IllegalArgumentException();
}
if (!con2) {
   throw new IllegalArgumentException();
}
return result;

}

public String checkResult(int[] question, int[] inputNumbers){

int strike = 0;
int ball = 0;

// 존재여부 동일성, 위치 동일성 판별
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(question[i]==inputNumbers[j]&&i==j){
strike++;
}
else if(question[i]==inputNumbers[j]&&i!=j){
ball++;
Copy link

Choose a reason for hiding this comment

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

question[i]==inputNumbers[j] 조건이 중복되는데 중복되지 않도록 수정해보세요

}
}
}

// 결과를 어떻게 return 해줘야할까
return Integer.toString(strike)+(ball);
Copy link

Choose a reason for hiding this comment

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

객체로 만들어서 리턴하면 어떨까요?

}

public boolean printResult(String check){
Copy link

Choose a reason for hiding this comment

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

이 함수는 3개의 역할을 하고 있습니다. 모두 분리해보세요.

  • ball/strike 개수에 따라서 어떤 메세지를 출력해야하는지 결정
  • 메세지 출력
  • 종료 조건 판단

String[] split = check.split("");

if(split[0].equals("3")){
System.out.println("3스트라이크");
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
Copy link
Collaborator

Choose a reason for hiding this comment

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

출력관련 로직을 분리해봅시다. 출력메시지를 변경하라는 요구사항이 주어졌을 때 해당 메시지가 어디 있었는지 코드 전체를 뒤져야할 수 있습니다.

return true;
}
else if(split[0].equals("0")&&split[1].equals("0")){
System.out.println("낫싱");
return false;
}else if(split[0].equals("0")){
System.out.println(split[1]+"볼");
return false;
}else if(split[1].equals("0")){
System.out.println(split[0]+"스트라이크");
return false;
}else{
System.out.println(split[1]+"볼 "+split[0]+"스트라이크");
return false;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

early return을 하기 때문에 else ifelse가 없어도 정상적으로 동작합니다.

else if -> if
else -> 제거

}
33 changes: 32 additions & 1 deletion src/test/java/baseball/ApplicationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,47 @@ class ApplicationTest extends NsTest {
);
}

@Test
void 모든_경우의_수() {
assertRandomNumberInRangeTest(
() -> {
run("456",
"416", "412", "312",
"136", "132",
"145", "124", "123",
"2"
);
assertThat(output()).contains(
"낫싱",
"1볼", "2볼", "3볼",
"1볼 1스트라이크", "2볼 1스트라이크",
"1스트라이크", "2스트라이크", "3스트라이크",
"게임 종료");
},
1, 2, 3
);
}

@Test
void 예외_테스트() {
assertSimpleTest(() ->
assertThatThrownBy(() -> runException("1234"))
.isInstanceOf(IllegalArgumentException.class)
);

assertSimpleTest(() ->
assertThatThrownBy(() -> runException("023"))
.isInstanceOf(IllegalArgumentException.class)
);

assertSimpleTest(() ->
assertThatThrownBy(() -> runException("112"))
.isInstanceOf(IllegalArgumentException.class)
);
}

@Override
public void runMain() {
Application.main(new String[]{});
}
}
}