-
[내배캠, Lv3] 단어 맞추기 게임알고리즘 문제/Java 2024. 6. 19. 19:14
문제
문제1 : 단어를 주어진 기회 안에 맞추는 게임을 만들어보기
- 컴퓨터가 랜덤으로 영어단어를 선택합니다 .
- 영어단어의 자리수를 알려줍니다 ( 7자리 = "_ _ _ _ _ _ _"
- 사용자는 A 부터 Z 까지의 알파벳 중에서 하나를 입력합니다.
- 입력값이 A-Z 사이의 알파벳이 아니라면 다시 입력을 받습니다.
- 입력값이 한 글자가 아니라면 다시 입력을 받습니다.
- 이미 입력했던 알파벳이라면 다시 입력을 받습니다.
- 입력값이 정답에 포함된 알파벳일 경우 해당 알파벳이 들어간 자리를 전부 보여주고, 다시 입력을 받습니다.
- 정답이 eyes 인 경우에 E 를 입력했을 때 ( "E _ E _ "
- 입력값이 정답에 포함되지 않은 알파벳일 경우 기회가 하나 차감되고, 다시 입력을 받습니다.
- 사용자가 9번 틀리면 게임오버됩니다.
- 게임오버 되기 전에 영어단어의 모든 자리를 알아내면 플레이어의 승리입니다.
문제 접근
계획
- List를 활용한 문제 관리
- 문제에 대해서는 문제의 알파벳 길이 만큼 '_' 삽입
- 정답을 맞출 수 있는 남은 기회가 0이거나 공란이 0이 될 때 까지 반복
- 플레이어가 알파벳을 제대로 입력했을 경우, 문자열을 앞에서부터 순차적으로 탐색
- 유저가 대/소문자 구분 없이 입력할 것을 감안하여, 대문자로 치환
- 정답인 경우 해당 위치를 _ 에서 알파벳으로 변경
- 정답이 아닌 경우 기회를 1 차감
필요 내용
해당 계획대로 구현하기 위해 나는 다음과 같은 내용을 학습해야할 필요가 있었다.
- 특정 문자가 반복적으로 나오는 문자열 생성
- char형 변수가 알파벳인지 판단 및 대문자로 치환
- String의 특정 인덱스 값 변경
구현 중 발생한 문제
1. 한글을 입력할 경우 예외처리가 되지 않고 기회가 차감되는 문제
문제 1 : isAlphabetic() 함수를 통하여 영어인 경우만 처리를 하게 하였지만, 한글을 입력해도 처리가 되는 현상
isAlphabetic()함수의 정의를 열어 보니, 영어/영어 이외의 문자로 구분 짓는 것이 아닌, 유니코드 표준에 의해 정의된 다른 나라 문자 또한 구분하고 있었다.
isAlphabetic 함수 내용
public static boolean isAlphabetic(int codePoint) { return (((((1 << Character.UPPERCASE_LETTER) | (1 << Character.LOWERCASE_LETTER) | (1 << Character.TITLECASE_LETTER) | (1 << Character.MODIFIER_LETTER) | (1 << Character.OTHER_LETTER) | (1 << Character.LETTER_NUMBER)) >> getType(codePoint)) & 1) != 0) || CharacterData.of(codePoint).isOtherAlphabetic(codePoint); }
해결 1 : 해당 문자가 영어 알파벳이 맞는지 확인하는 isAlpha함수를 별도로 구현
해당 문자가 'a' ~ 'z' 사이거나 'A' ~ 'Z'사이일 경우 True를 반환하는 함수를 별도로 구현하여,
입력받은 문자 길이가 1인 경우, 판단하게 하였다.
isAlpha 함수
public static boolean isAlpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ; }
2. Call by value / Call by reference
문제1. 함수내에 들어온 값을 변경하여도 실제 값은 변하지 않았던 문제
입력받은 문자가 정답에 있는지 확인하는 함수 match함수를 구현하였다.
해당 함수는 다음과 같은 동작을 했다.
- 해당 문자가 존재하는 위치 확인, 저장
- 문제에서 해당 위치에 존재하는 문자 '_'를 알파벳으로 변환
- 변환한 수 만큼, 공란의 수를 저장하는 변수 blankCount 감소
하지만, 해당 함수에서 값을 변경하여도 실제 main함수의 원본 값에는 아무런 변화가 일어나지 않았고,
정답을 맞춰도 문제는 여전히 '_ _ _ _ _ _'로 표시되었다.
해결1. 함수의 인자를 new를 통해 생성된 객체로 변환
C++에서 &가 있듯, C#에서 ref 키워드가 있듯이 Java 또한 Call By Reference를 사용할 수 있는 키워드가 존재할 줄 알았으나, Java에는 Call By Reference가 존재하지 않는다고 한다. 그와 비슷하게 동작을 할 뿐, 실제로는 Call By Value라고 한다.
그래서 match함수에서 값이 변경될 인자에 대해서는 int는 Integer[]로 String은 StringBuilder처럼 각 변수를 new 키워드를 사용하는 자료형으로 바꿔, 이 문제를 해결하였다.
match 함수
public static void match(StringBuilder word, String original, Character input, Integer[] chance, Integer[] blankCount) { int matchCount = 0; ArrayList<Integer> matchIndices = new ArrayList<>(); for(int i = 0; i < word.length(); ++i) { // 입력받은 알파벳이 정답에 존재할 경우 if(original.charAt(i) == input) { // 이미 체크된 문자열일 경우 if(original.charAt[i] == word.charAt[i]) return; ++matchCount; matchIndices.add(i); } } for (Integer i : matchIndices) { word.setCharAt(i, input); } blankCount[0] -= matchIndices.size(); if(matchCount == 0 ) { --chance[0]; } }
코드
전체 코드
java.app
더보기import java.util.ArrayList; import java.util.Random; import java.util.Scanner; public class App { public static void match(StringBuilder word, String original, Character input, Integer[] chance, Integer[] blankCount) { int matchCount = 0; ArrayList<Integer> matchIndices = new ArrayList<>(); for(int i = 0; i < word.length(); ++i) { if(original.charAt(i) == input) { ++matchCount; matchIndices.add(i); } } for (Integer i : matchIndices) { word.setCharAt(i, input); } blankCount[0] -= matchIndices.size(); if(matchCount == 0 ) { --chance[0]; } } public static boolean isAlpha(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ; } public static void main(String[] args) throws Exception { String[] words = {"PICTURE", "LIKE", "CREATIVE", "PROGRAMMER" }; Random rand = new Random(); int index = rand.nextInt(words.length); Integer[] chance = new Integer[]{ 9 }; Integer[] blankCount = new Integer[]{ words[index].length() }; StringBuilder word = new StringBuilder(new String("_").repeat(blankCount[0])); Scanner sc = new Scanner(System.in); while(chance[0] > 0 && blankCount[0] > 0) { System.out.println("현재 상태 : " + word.toString()); System.out.println("남은 기회 : " + chance[0]); System.out.print("정답 : "); String answer = sc.nextLine(); if(answer.length() == 1 && isAlpha(answer.charAt(0))) { match(word, words[index], Character.toUpperCase(answer.charAt(0)), chance, blankCount); } else { System.out.println("알파벳 한 글자만 입력해주세요 ! \n"); } } if(blankCount[0] == 0) { System.out.println("정답 : " + words[index]); } else { System.out.println("실패.. 정답은 " + words[index]); } sc.close(); } }
실행화면
그리고 코드를 실행한 결과 다음과 같이 동작하였다.
'알고리즘 문제 > Java' 카테고리의 다른 글
[프로그래머스, Lv1] 명예의 전당(1) (1) 2024.07.24 [프로그래머스, Lv1] K번째 수 (0) 2024.07.23 [프로그래머스, Lv1] 문자열 다루기 기초 (0) 2024.07.18 [내배캠, Lv2] 자판기 (0) 2024.06.14 [내배캠, Lv1] 랜덤 닉네임 생성기 (0) 2024.06.13 - 컴퓨터가 랜덤으로 영어단어를 선택합니다 .