[플레이그라운드] TDD, 클린 코드 (2) - 숫자야구게임 구현



기능별 구현내용을 정리해보겠음


전체코드

https://github.com/Kyuyoung11/java-baseball-playground/tree/firstTry


[기능목록]

  1. 난수 3개 생성
  2. 입력 받고 정답 확인
    2-1. 볼인지 스트라이크인지 분류

1. 난수 3개 생성

처음 생각한 흐름

  • ArrayList의 .contains를 이용해 중복을 제거하려고 했음 -> while문안에 if가 들어가니 인덴트 1에서 막힘
    -> 자료구조 라이브러리를 이용해서 해결해보기로 결정

최종 흐름

  • HashSet을 사용하면 중복없이 들어갈테니 구현 → 순서가 보장되지않아서 안됨
  • 구글링해보니 LinkedHashSet이 중복x, 순서보장o라고 하길래 사용 → 됨!
    https://doompok.tistory.com/6

      private LinkedHashSet<Integer> _makeRandomNumbers() {
              LinkedHashSet<Integer> randomNums = new LinkedHashSet<Integer>();
              Random rd = new Random();
              while (randomNums.size()<3) {
                  randomNums.add(rd.nextInt(9));
              }
              return randomNums;
          }
    

2. 입력 받고 정답 확인

처음 생각한 흐름

while(true) {
  //1. 숫자 입력 받기
  //2. ball or strike 확인
	// 2-1. if) strike인지 확인, 카운트
    // 2-2. else) ball인지 확인, 카운트
  //3. 카운트 결과 print
  //4. 3 스트라이크이면, break
}

문제점

  1. 인덴트 1 못지킴
  2. else 사용


최종 흐름

  1. 인덴트 1 못지킴 -> 정답확인 부분 메소드 추출
  2. else 사용 -> strike/ball 분류 및 카운트 메소드 추출
public void init() {
        LinkedHashSet<Integer> randomNums = makeRandomNumbers();
        boolean flag = false;
        while(!flag) {
            //1. 숫자 입력 받기
            String numString = _getInputNumString();
            flag = tryAnswer(numString, randomNums);
        }

        ...
}

public boolean tryAnswer(String numString, LinkedHashSet<Integer> randomNums) {

        HashMap<String, Integer> count = new HashMap<>();
        count.put("ball", 0);
        count.put("strike", 0);

        for (int i=0; i<numString.length(); i++) {
            Integer num = Integer.parseInt(numString.substring(i,i+1));
            //2. ball or strike 확인
            _countBallOrStrike(count, randomNums, num, i);
        }
        
        //3. 카운트 결과 print
        _printResult(count);

        //4. 3 스트라이크 check
        return count.get("strike") == SIZE;
}



strike/ball 분류

고민 내용

  • 어떻게 하면 분류랑 카운트를 같이할 수 있을까
    → 카운트용 Map 활용하는 방법으로 가기로 결정 (call by reference 방식으로 하는게 썩 마음에 들진 않지만….)
  • strike를 체크하려면 index값이 필요
    → parameter가 너무 많아지는 것 같지만… 일단 이렇게 하고 피드백 강의를 보기로 결정
private void _countBallOrStrike(HashMap<String, Integer> count, LinkedHashSet<Integer> randomNums, Integer num, int index) {
        Integer[] randomNumArray = randomNums.toArray(new Integer[randomNums.size()]);
        if (randomNumArray[index] == num) {
            count.put("strike",count.get("strike")+1);
            return;
        }
        if (randomNums.contains(num)) {
            count.put("ball", count.get("ball")+1);
        }
}

개선할 점

  1. 상수를 사용할거면 final로 하기
  2. 재시작 입력도 메소드를 분리하기
  3. 의미있는 변수명을 사용하기
  4. 클래스 나누기

생활체조 지키는거 너무 어렵다… 흣차흣차

다른 글