241023 개인과제2 진행

물고기가자라면어그로·2024년 10월 23일
0

좀처럼 떠오르지 않는 아이디어...

하루종일 생각했는데 여전히 숫자를 어떻게 비교할지 정하지 못했다.
(입력한 숫자 세 개가 랜덤숫자 내에 존재하는지와 그 자리가 맞는지를 비교해야함)

일단 생각해둔 건

  1. 프로그램이 만드는 랜덤 숫자 세 개를 따로 필드에 저장하고
  2. 사람이 입력한 숫자 세 개 역시 각각 필드에 따로 저장해서
    (이 과정에서 둘 다 중복이 있는지 확인하기 위해 Set에 넣었다가 뺀다)
  3. 비교

하는 것이다.

그런데 이 방법은 번거로운 형변환을 너무 많이 거쳐야하고 필드를 여러개 만드는 단순한 방법 같아서 마음에 들지 않는다.

하지만 일단 생각나는 아이디어가 없으니 이 방법을 사용하기로 치고 다른 것들을 좀 만졌다.

입력받은 숫자 저장하기

어처피 입력받을 때는 세 개의 숫자를 string의 형식으로 한 번에 입력받고 이를 Set에 넣었다 빼서 중복체크를 해야 하니 입력받은 값을 하나하나 메서드로 저장하기보다는 입력받은 숫자를 한 번에 중복체크하고 따로따로 필드에 저장하는 메서드를 만들기로 했다.

숫자를 일단 Scanner로 입력받고 나면 체크해야할 것이 두 가지이다.

  1. "세 개"의 숫자(0을 제외한) 인가?
  2. 세 숫자에 중복이 없는가?

그렇다면 우선 받은 인풋이 정수로 이루어진 문자열인지 확인하기 위해 matches 함수를 사용한다.

String input = sc.nextLine();
boolean match = input.matches("^[1-9]*$")

예를 들어 이런 식을 만드는 것이다. matches 함수는 문자열의 일치를 확인할 때 사용하는 것인데 [a-b]의 형태는 a부터 b 사이에 있는 하나의 문자를 의미한다. (a, b 포함) 이 식을 통해 0을 제외한 1부터 9까지의 숫자로 이루어진 문자열 인지를 확인 할 수 있다.

인풋은 세 자리 숫자여야하기 때문에 .length()를 사용해 문자열의 길이를 잴 수 있다.

그리고 중복인지를 확인하기 위해 이 문자열을 하나씩 뜯어 set에 넣어 그 사이즈를 잰다. (숫자가 중복이면 set의 사이즈가 1이나 2가 될 것이므로)
문자열을 뜯기 위해 charAt()을 사용해 character로 형변환한다.

 public void settingInput(String threeNumbers) {
        char firstNum = threeNumbers.charAt(0);
        char secondNum = threeNumbers.charAt(1);
        char thirdNum = threeNumbers.charAt(2);

        HashSet<Character> checkingSet  = new HashSet<Character>();
        checkingSet.add(firstNum);
        checkingSet.add(secondNum);
        checkingSet.add(thirdNum);
        
        int size = checkingSet.size()
 }

사이즈가 3일 경우, 이를 int으로 형변환하여 위의 필드에 정의해뒀던 속성들에 각각 저장해준다. 형변환할 때는 Character.getNumericValue(); 함수를 사용했다.


만약 위의 세 가지 경우에서 input.matches("^[1-9]*$")false일 경우, input.length()가 3이 아닐경우, 그리고 checkingSet.size()가 3이 아닐 경우 예외처리를 해주면 된다.

예외 처리하기

예외처리를 하기 위해 커스텀 예외 클래스를 하나 만들었다. java가 제공하는 RuntimeException을 상속받는 이 BadException은 오류가 발생했다는 메세지를 품고 있다.

예외를 처리할 때는 두 가지를 기억해야 한다.
메서드가 예외를 발생시킬 수 있다고 상위 메서드에 알리는 throws-throw문 와 이를 직접 처리하는 try-catch문이다.

처음에 throws-throw 문만 작성했다가 계속 오류가 나서 튜터님께 질문했더니 예외를 처리하는 try-catch문을 작성하지 않았다고 해답을 찾을 수 있었다.
(예외 처리 부분도 헷갈렸는데 이제 개념이 좀 잡혔으니 다음에 정리하겠다.)

아래는 예외처리를 넣은 숫자입력-저장 기능이다.

    public boolean play () throws BadException {
        System.out.println("숫자를 입력하세요.");
        Scanner sc = new Scanner(System.in);
        String input = sc.nextLine();
        while (!input.matches("^[1-9]*$") || input.length()!=3){
            throw new BadException();
        }
        settingInput(input);

settingInput 메서드는 다음과 같다.

public void settingInput(String threeNumbers) throws BadException{
        char firstNum = threeNumbers.charAt(0);
        char secondNum = threeNumbers.charAt(1);
        char thirdNum = threeNumbers.charAt(2);

        HashSet<Character> checkingSet  = new HashSet<Character>();
        checkingSet.add(firstNum);
        checkingSet.add(secondNum);
        checkingSet.add(thirdNum);

        while (checkingSet.size()!=3) {
            throw new BadException();
        }
        this.firstInput = Character.getNumericValue(firstNum);
        this.secondInput = Character.getNumericValue(secondNum);
        this.thirdInput = Character.getNumericValue(thirdNum);
    }

여기까지 하면 둘다 throws BadException을 하고 있기 때문에 예외를 발생시킨다는 것은 선언했다. 그러나 정작 예외를 처리하는 부분이 없다. 즉, 이 메서드를 사용하는 곳에 가서 예외를 처리해준다.

여기가 play() 메서드를 사용하는 메서드의 부분을 발췌한 것이다.

boolean gameWin = false;
 while (!gameWin){                   
      try {
          gameWin=baseballGame.play(); 
      } catch (BadException e) {
          System.out.println(e.getMessage());
      }

play 메서드를 실행하다가 안의 내용물들이 BadException을 발생시키면 이 BadException 클래스가 가지고 있는 getMessage()를 출력하는데 이는 BadException이 상속한 Exception 클래스가 가지고 있는 메서드로 Exception이 가지고 있는 메세지를 가져온다.

gameWin 이 예외 상황이 잡히면 gameWinboolean 값이 true로 바뀌지 않기 때문에 play()가 다시 실행된다. (try로)

0개의 댓글