ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [내배캠, Lv1] 랜덤 닉네임 생성기
    알고리즘 문제/Java 2024. 6. 13. 21:06

     

    문제

    문제1 : 랜덤한 닉네임을 생성하는 자바/코틀린 코드를 작성해보세요.

    1. 사용자는 최소 27가지 이상의 닉네임 중 하나를 랜덤으로 출력 할 수 있습니다. (아래의 키워드를 사용해주세요!)
      • 기철초풍, 멋있는, 재미있는
      • 도전적인, 노란색의, 바보같은
      • 돌고래, 개발자, 오랑우탄

    문제 접근 

    문제를 풀기전 나는 다음과 같은 계획을 세웠다.

    1. 3가지 키워드를 각각 List에 삽입한다.
    2. Random 객체를 활용하여 0 ~ 2사이의 난수를 생성한다.
    3. 해당 난수에 해당하는 문자열을 연결하여 출력한다.

    해당 계획대로 구현하기 위해 나는 다음과 같은 내용을 학습해야할 필요가 있었다.

    1. 문자열 출력
    2. Java의 List 객체 생성 및 초기화
    3. Random 객체 사용법

    계획대로 구현한 코드

    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    import java.util.Scanner;
    
    public class App {
        static final int MAXIMUM_COUNT = 3;
    
        public static void main(String[] args) throws Exception {
            List<String> firstModifier = Arrays.asList(new String[]{"기절초풍 ", "멋있는 ", "재미있는 "}) ;
            List<String> secondModifier = Arrays.asList(new String[]{"도전적인 ", "노란색의 ", "바보같은 "}) ;
            List<String> nickName = Arrays.asList(new String[]{"돌고래", "개발자", "오랑우탄"});
    
            Random rand = new Random();
    
            int firstIndex = rand.nextInt(MAXIMUM_COUNT);
            int secondIndex = rand.nextInt(MAXIMUM_COUNT);
            int ninkNameIndex = rand.nextInt(MAXIMUM_COUNT);
    		
            System.out.println(firstModifier.get(firstIndex) + secondModifier.get(secondIndex) + nickName.get(ninkNameIndex));
        }
    }

     

    그리고 설레이는 마음을 안고 돌려본 결과는 다음과 같았다

     

    재미있고, 도전적이라는 키워드는 마음에 들지만 오랑우탄이라는 마지막 문구가 너무 마음에 들지 않았고

    해당 문구만 바꾸고 싶다는 생각을 하던 중 한가지 방법이 떠올랐다.

    [ 전략적 팀 전투에 존재하는 시스템인 '증강체와 재설정(리롤)' ]

     

    전략적 팀 전투에 존재하는 '리롤'이라는 아이디어를 사용하면 '내가 원하는 별명을 얻을 수 있겠다.' 라는 생각이 들었다.

     

    그와 동시에 낮은 확률로 '당첨'을 제공한다면 돌릴 때 마다, 소소한 재미 또 한 제공할 수 있으리라 생각이 들었고,

    낮은 확률로 당첨되는 "코딩을 잘하는 ", "논리적인 ", "코린이" 라는 키워드를 추가 하기로 했다.

     

    해당 기능을 추가하는 과정에서 2가지 문제를 추가적으로 해결해야할 필요가 있었다.

    1. 사용자의 input을 어떻게 받을 것인가
    2. 확률을 어떻게 구현할 것인가

    해결 방법

    사용자의 input 처리

    GUI를 사용할 수 없기에 cin, scanf처럼 사용자로 부터 문자를 입력 받아, 해당 입력에 대한 결과를 보여주는 것이

    현재 내가 사용할 수 있는 최선의 방법이라 생각이 들었다.

     

    개인적으로는 민망하지만 이 부분에서 제일 오래 해맸는데, System.Out.println을 자세히 알기 전

    ln을 in으로 착각하여 해당 함수를 통해, 입력받은 값을 가져오는 것인 줄 알았다.

     

    결과는 당연하게도 input값을 받는 command변수의 숫자인 0으로 터미널은 도배가 되어 있었고,

    그 후, 검색을 통해 scanner라는 객체를 통해 데이터를 입력 받을 수 있다는 것을 확인하고 수정하였다.

     

    확률 구현

    Random과 구간을 잘 활용하면 확률 기능을 추가 할 수 있을 것이라 생각이 들었다.

     

    별도의 dice라는 함수를 만들어, 전체 아이템 수, 당첨 아이템 수, 각 당첨 확률을 받게 만들었고,

    각 당첨 확률을 0 ~ 100사이의 구간으로 변경,

     

    random을 사용해 얻은 난수가 해당 구간에 존재 한다면 해당 구간에 해당하는 결과를 반환,

    random을 통해 얻은 난수가 아이템 당첨 구간에 존재하지 않는다면

    기존과 동일하게 0 ~ 기존 아이템 수( 전체 아이템 수 - 당첨 아이템 수 ) 중 무작위 숫자를 반환하게 구현하였다.

     

    예시)   당첨1 = 20%, 당첨 2 = 40%, random 결과 값 = 40

    당첨1 ( 0 ~ 19 )
    당첨2 ( 20 ~ 59 )                   당첨 ! 꽝 ( 60 ~ 99 )

     

    최종 코드

    더보기
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    import java.util.Scanner;
    
    public class App {
    
        static final int MAXIMUM_COUNT = 4;
    
        //                      전체 항목           당첨 개수       각 확률     random 객체
        public static int dice(int totalCount, int winningCount, int[] rate, Random engine)
        {
            int normalCount = totalCount - winningCount;   // 일반 닉네임 개수 = 전체 개수 - 당첨 개수
            
            // 당첨이 존재할 경우
            if(winningCount > 0)   
            {
                // 0 ~ 99사이의 난수 생성
                int randNum = engine.nextInt(100);
                int accumulate = 0;
    
                // 당첨 항목 별로 구간을 생성하여 난수가 해당 범위에 존재할 경우 당첨!
                for(int i = 0; i < rate.length; ++i)
                {
                    accumulate += rate[i];
    
                    if(randNum < accumulate)
                    {
                        return normalCount + i;
                    }
                }
            }
            return engine.nextInt(normalCount);
        }
        public static void main(String[] args) throws Exception {
            List<String> firstModifier = Arrays.asList(new String[]{"기절초풍 ", "멋있는 ", "재미있는 ", "코딩을 잘하는 "}) ;
            List<String> secondModifier = Arrays.asList(new String[]{"도전적인 ", "노란색의 ", "바보같은 ", "논리적인 "}) ;
            List<String> nickName = Arrays.asList(new String[]{"돌고래", "개발자", "오랑우탄", "코린이"});
    
            Random rand = new Random();
            Scanner sc = new Scanner(System.in);
            
            int reroll = 3;
    
            // 첫 무작위 닉네임 결과 
            int firstIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 1 }, rand);
            int secondIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 10 }, rand);
            int ninkNameIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 20 }, rand);
    
            // 
            while(reroll > 0) {
                System.out.println(firstModifier.get(firstIndex) + secondModifier.get(secondIndex) + nickName.get(ninkNameIndex));
                System.out.println(String.format("남은 재설정 횟수 : %d", reroll));
                System.out.println("1. 재설정 2. 확정");
    
                int command = sc.nextInt();
    
                if(command == 1)
                {
                    System.out.println("1. 1번만 변환 2. 2번만 변환 3. 3번만 변환 4. 전체 변환 그외. 취소");
    
                    int nextCommand = sc.nextInt();
                    switch(nextCommand)
                    {
                        case 1:     
                            firstIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 1 }, rand);
                            --reroll;
                            break;
                            
                        case 2:
                            secondIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 10 }, rand);
                            --reroll;
                            break;
    
                        case 3:
                            ninkNameIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 20 }, rand);
                            --reroll;
                            break;
    
                        case 4:
                            firstIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 1 }, rand);
                            secondIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 10 }, rand);
                            ninkNameIndex = dice(MAXIMUM_COUNT, 1, new int[]{ 20 }, rand);
                            reroll -= 3;
                            break;
                    }
                }
                else if(command == 2)
                {
                    break;
                }
                else
                {
                    System.out.println("숫자를 다시 한 번 확인해 주세요.");
                }
            }
    
            System.out.println("\n최종 닉네임 : " + firstModifier.get(firstIndex) + secondModifier.get(secondIndex) + nickName.get(ninkNameIndex));
        }
    }

     

    결과

    [ 1번, 2번, 3번 키워드를 순서대로 바꾼 결과 ]

     

     

Designed by Tistory.