광주인력개발원

<김주김> 팀이 내주신 문제 풀이 완료 [2023-04-20 학습일지]

플광 2023. 5. 30. 08:50

 

"""

FILE_NAME : team_problem_akinator.py

출제팀 : 김주김

출제일자 : 2023-04-18

문제 이름 : <3분단 인물 맞추기(아키네이터)>

조건 :

김ㅇㅇ, 김ㅇㅇ, 주ㅇㅇ, 이ㅇㅇ, 박ㅇㅇ, 정ㅇㅇ, 송ㅇㅇ, 이ㅇㅇ

성별(남=T) F F F T T F F T

안경 O O O X O X X O

실무경험 X X X O X X O O

20대 O O X X O X X X

기숙사 거주 여부 X O X X O X X O

수강생 신분 여부 O O O O O O O X

 

1) 제시한 표를 참고하여 리스트 혹은 딕셔너리 자료형을 1회 이상 활용

2) 사용자에게 질문에 대한 답을 받아 인물을 맞추는 게임을 만드시오.(아키네이터 참조)

3) 최대 3개의 질문으로 누구인지 판별할 수 있도록 해야 합니다.

4) 3회의 질문 이전에 누구인지 판별된 경우 정답을 출력하고 종료

5) 3번의 질문으로 누구인지 정확히 판별이 불가능한 경우 사용자에게 추가질문 가능한지 물어봄

6) 사용자가 추가질문 허락할 경우 추가질문 한개로 최종 판별

7) 사용자가 추가질문을 불허한 경우 추측되는 후보들을 f스트링으로 한 문장에 출력

"""

import random

people_data_base = [
    # 이름 / 성별(남=T) / 안경 / 실무경험 / 20대 여부 / 기숙사 거주 여부 / 수강생 신분 여부
    ['김ㅇㅇ', False, True, False, True, False, True],
    ['김ㅇㅇ', False, True, False, True, True, True],
    ['주ㅇㅇ', False, True, False, False, False, True],
    ['이ㅇㅇ', True, False, True, False, False, True],
    ['박ㅇㅇ', True, True, False, True, False, True],
    ['송ㅇㅇ', False, False, True, False, False, True],
    ['정ㅇㅇ', False, False, False, False, False, True],
    ['이ㅇㅇ', True, True, True, False, True, False],
]

ask_list = [ # 질문과 각 해당되는 데이터베이스의 인덱스르르 튜플로 묶음
    ('성별이 남자입니까?', 1),
    ('안경을 썼습니까', 2),
    ('개발자 실무 경험이 있습니까?', 3),
    ('20대 입니까?', 4),
    ('기숙사에 살고 있습니까', 5),
    ('수강생 신분입니까?', 6)
]
# 랜덤 순서로 질문을 물어보도록 sample함수 사용, while내에서 사용할 인덱스 선언
ask_index = 0
ask_order_list = random.sample(ask_list, 6)
# 메시징 따로 저장 관리하기
ask_selection = {'text': '[1. 예] [2. 아니요] ', 'domain': ['1', '2']}

# while 반복 시킬 인자
is_game_going = True

# 승리 조건 인자
is_user_win = False

# 3회 이후 추가로 시행 여부 묻기
trial_want = None
cannot_find = False

people_index_list = list(range(0, len(people_data_base)))

while is_game_going:
    # Todo: 질문하고 검증하기
    user_answer = ''
    print(ask_order_list[ask_index][0])
    # Todo: 잘못 입력하는지 검증
    while True:
        user_answer = input(ask_selection['text'])
        if user_answer not in ask_selection['domain']:
            print('잘못된 입력입니다. 다시 입력해주세요.')
        else:
            break
    user_answer = int(user_answer)
    if user_answer == 1:
        i = 0
        while i < len(people_data_base):
            if people_data_base[i][ask_order_list[ask_index][1]] != True:
                people_index_list[i] = -1
            i += 1
    else:
        i = 0
        while i < len(people_data_base):
            if people_data_base[i][ask_order_list[ask_index][1]] != False:
                people_index_list[i] = -1
            i += 1
    match_people_count = people_index_list.count(-1)
    # Todo: 검증시 일치하는 결과 찾으면 결과 출력
    if match_people_count == (len(people_index_list) - 1):
        # clear
        i = 0
        while i < len(people_index_list):
            if people_index_list[i] != -1:
                print('찾았습니다! \n', people_data_base[i][0])
                is_user_win = True
                is_game_going = False
                break
            i += 1
    elif match_people_count == len(people_index_list):
        cannot_find = True
        is_user_win = False
        is_game_going = False
    ask_index += 1
    if trial_want == False:
        break
# Todo: 1번 더 물어봐도 되는지 입력 및 검증
    if is_game_going == True and ask_index == 3 and trial_want == None:
        print('아쉽지만 못 맞추었네요! 한 번 더 기회를 주시렵니까?')
        trial_want = False
# Todo: 물어봐도되면 물어보고 검증
        while True:
            user_answer = input(ask_selection['text'])
            if user_answer not in ask_selection['domain']:
                print('잘못된 입력입니다. 다시 입력해주세요.')
            else:
                break
        user_answer = int(user_answer)
        if user_answer == 1:
            pass
        else:
            is_game_going = False


# Todo: 최종 상태 실패 시, 패배 선언
if is_user_win:
    pass
else:
    if cannot_find:
        print('그런 사람 없습니다.')
    else:
        print('모르겠다!!')
 

오늘 while을 배웠으므로, 아키네이터를 만드는데 바로 활용해보았다. 송준혁님이 활용하였던 in [list] 문법을 활용하여 검증로직에 활용했고, 이에 더불어 출력할 메세지도 저장해놓고 계속 재활용 하였다. 또한 가급적 while을 반복시킬 때는 True나 False의 boolean 타입 변수를 이용했고, 특정 조건에 이르렀을 때만 스위치 사용하듯 값을 변경시켰다.

 

또한, 매번 똑같은 순서로 질문을 하는 것이 단조롭다고 느껴, 난이도를 올려 랜덤 순서로 다른 문제를 물어보도록 구성했다. 처음에 people_index_list  database 크기에 따라 인덱스 번호를 저장하도록 만들었고, 매 질문의 결과에 따라 해당 조건에서 걸러진다면 '-1'이 저장되도록 하였다. 그리고, 분기 끝에는 -1이 몇 개인지 세었고, 데이터셋의 크기보다 1작다면, 아직 안걸려진 단 한 사람이 있다는 뜻으로, 그 사람의 정보를 출력하도록 했다. -1로 덮어씌어지지 않은 리스트 요소에는 데이터베이스의 인덱스가 저장되어있다. 하지만 만일, people_index_list에 -1만 남게된다면, '그런 사람이 없다'고 출력하게 했고, 주어진 3번 또는 4번 기회에 해당 사람을 찾지 못한다면, "모르겠다!" 라고 출력을 하도록 하였다.

 

비겁하게 while을 썼지만, 대신 이렇게 로직을 구성할 경우, database_set과 질문 리스트에 자료만 추가해주면, 알아서 잘 작동하게 된다. 대신에 질문을 더 늘릴 수 있도록 또 변경해줘야하겠지만.. (제한점이 많아 아직 OOP력이 부족하다..)

 

반복문으로도 꽤 복잡한 로직이었는데, 이것을 순수 if로 풀어내신 분들은... 존경합니다.

 

감사합니다.