하루종일 생각했는데 여전히 숫자를 어떻게 비교할지 정하지 못했다.
(입력한 숫자 세 개가 랜덤숫자 내에 존재하는지와 그 자리가 맞는지를 비교해야함)
일단 생각해둔 건
- 프로그램이 만드는 랜덤 숫자 세 개를 따로 필드에 저장하고
- 사람이 입력한 숫자 세 개 역시 각각 필드에 따로 저장해서
(이 과정에서 둘 다 중복이 있는지 확인하기 위해Set
에 넣었다가 뺀다)- 비교
하는 것이다.
그런데 이 방법은 번거로운 형변환을 너무 많이 거쳐야하고 필드를 여러개 만드는 단순한 방법 같아서 마음에 들지 않는다.
하지만 일단 생각나는 아이디어가 없으니 이 방법을 사용하기로 치고 다른 것들을 좀 만졌다.
어처피 입력받을 때는 세 개의 숫자를 string
의 형식으로 한 번에 입력받고 이를 Set
에 넣었다 빼서 중복체크를 해야 하니 입력받은 값을 하나하나 메서드로 저장하기보다는 입력받은 숫자를 한 번에 중복체크하고 따로따로 필드에 저장하는 메서드를 만들기로 했다.
숫자를 일단 Scanner로 입력받고 나면 체크해야할 것이 두 가지이다.
- "세 개"의 숫자(0을 제외한) 인가?
- 세 숫자에 중복이 없는가?
그렇다면 우선 받은 인풋이 정수로 이루어진 문자열인지 확인하기 위해 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
이 예외 상황이 잡히면 gameWin
의 boolean
값이 true
로 바뀌지 않기 때문에 play()
가 다시 실행된다. (try로)