초보 개발자 코드 트레이닝, Part 4. TDD 수련 - 야구게임 3편

이번 테스트는  "사용자가 숫자를 등록하면 컴퓨터와 비교하고 결과를 리턴, 매번 시도 횟수도 출력해야한다" 입니다.

그간 기본 로직을 이용해서 사용자에게 입력을 받고 결과를 내보내고 다시 게임을 시작하는 것을 구현해야 되겠네요. 그냥 테스크 코드에 흐름을 적어보았습니다.  이구현을 나중에 실제 코드로 올리면 될것 같습니다.


테스트코드

    @Test
    public void endlessGame() {
   
        GameNumber[] userGameNumbers = {
                 new GameNumber(1,2,3)
                ,new GameNumber(1,2,4)
                ,new GameNumber(1,2,5)
                ,new GameNumber(1,2,6)
                ,new GameNumber(1,2,7)
                ,new GameNumber(1,2,8)
                ,new GameNumber(1,2,9)
                ,new GameNumber(1,3,2)
                ,new GameNumber(2,9,3)
                ,new GameNumber(3,8,1)
                ,new GameNumber(8,7,2)
                ,new GameNumber(7,8,2)
                ,new GameNumber(6,8,1)
        };
        int maxTryCount = 10;

        GenerateGameNumber generateGameNumber = new GenerateGameNumber();
        // 게임시작!
        while(true) {
            GameNumber computerGameNumber = generateGameNumber.generate();
            System.out.println("게임이 시작되었습니다.");
           
            Evaluatable evaluateGameNumber = new EvaluateGameNumber(computerGameNumber);
            for(GameNumber userGameNumber : userGameNumbers) {
                Evaluation evaluate = evaluateGameNumber.evaluate(maxTryCount, userGameNumber);
               
                System.out.println(evaluate.toString());
                // 아웃이 아니라면 다른 값을 내보낸다.
                if(evaluate.isOut()) {
                    break;
                } else if(evaluate.isHit()) {
                    break;
                }
            }
        }
    }


작성하고 나니 버그가 생겼습니다. 무한 생성을 하면 당연히 전에 넣어 두었던 NoMoreGenerateGameNumberException이 발생할줄 알았는데 그 이전에 다른 에러를 냈습니다. java.util에 있는 Random.nexInt 메소드를 이용했는데, 양의 정수가 아니면 에러를 내더군요. 그냥 0을주면 0이 나올꺼라 생각했는데, 까칠하게 시리 에러를 냈습니다. 고쳐야죠머. 그리고 새 게임이 시작했을때 간혹 시도 카운트가 잘 먹지를 않네요. 이런 생각치 못한 버그가 마구 나옵니다.(나중에 알고보니 완전 잘못 작성한 코드였네요)

GenerateGameNumber generate 패치

        int maxReachedIndex = (totalSize - 1) - generatedGameIndexs.size();
        int randIndex = 0;
        if(maxReachedIndex > 0)
            randIndex = new Random().nextInt((totalSize - 1) - generatedGameIndexs.size());


일단 버그의 원인은 딱 꼬집에 말하면 generate함수에 있었습니다. 이전에 한번 내놓았던 GameNumber를 다시 내놓아서 그렇더군요. 그렇다면 generate할때 이전에 사용한 숫자는 배제 한다는 테스트가 실패 한것입니다. 테스트가 허술했군요. 에러를 좀더 명확하게 도출하기 위해 generate메소드를 조금 수정했습니다.

        if(!generatedGameIndexs.contains(randIndex)) {
            generatedGameIndexs.add(randIndex);
        } else {
            throw new DuplicateGenerationNumberException();
        }
        Collections.sort(generatedGameIndexs);


난수로 index를 선택할때 문제가 있었던듯 싶습니다. 살펴보니 그냥 고치는 문제가 아니였습니다. GameNumber을 얻기위한 전략이 잘못되었습니다. 코드도 어렵고, 그래서 다시 작성했습니다.(클래스와 메소드는 건들지 않고, 생성자 코드약간과 geneate코드 전체를 다시 구현했습니다.

GenerateGameNumber

    private List<GameNumber> allGameNumbers;

    public GameNumber generate() {
        if(allGameNumbers.size() == 0) {
            throw new NoMoreGenerateGameNumberException();
        }
       
        System.out.println(String.format("--remainGameNumberSize %d", allGameNumbers.size()));
        int maxReachedIndex = allGameNumbers.size() - 1;
        int randIndex = 0;
        if(maxReachedIndex > 0)
            randIndex = new Random().nextInt(allGameNumbers.size() - 1);
       
        return allGameNumbers.remove(randIndex);
    }

모든 경우의 수에서 랜덤으로 하나씩 빼면 되는데, 복잡하게 생각했군요. 반성을 하며 다시 진행합니다.

@Test 코드를 보니 게임을 한번 실행해기위해 인스턴스들이 생성을 하고 Evaluatable 인스턴스를 주고 있습니다. 일정한 패턴이 생겼으니 정리를 해야겠네요. 일단 이번에는 여기까지!

by 소내기 | 2008/08/15 13:53 | TDD | 트랙백 | 덧글(0)

트랙백 주소 : http://sonegy.egloos.com/tb/4551471
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶