print("숫자놀음 게임에 오신 것을 환영합니다! enter를 눌러 다음으로 넘어갑니다.")    #초기 세팅
import sys    #프로그램을 종료하기 위해 불러옵니다.
import random    #수를 무작위로 뽑기 위해 불러옵니다.
import itertools    #조합 명령어를 사용하기 위해 불러옵니다.
input()
연산자_모드='1'


def 처음_제시된_수_카드화(정수):    #각 자리의 수를 각각의 데이터로 한 리스트로 변환합니다. ex) 354 -> [3,4,5]
    정수=abs(정수)
    반환=[]
    while 정수>=1:
        반환.append(float(정수%10))
        정수//=10
    반환.sort()
    return 반환

def 목표수_설정():    #조건에 맞는적절한 목표수를 설정 할 수 있도록 구현합니다.
    while True:
        목표수=input()
        if not 목표수.lstrip('-').isdigit() and 목표수:
            print("목표수는 문자가 아닌 두 자리수 이상인 정수이어야 합니다. 다시 입력해 주세요.")
            목표수=None
            continue
        if not 목표수:
            목표수=random.choice(list(set(range(-1999,2000))-set(range(-9,10))))
        목표수=int(목표수)
        if -10<목표수<10:
            print("목표수는 한 자리수가 아닌 두 자리수 이상인 정수이어야 합니다. 다시 입력해 주세요.")
            목표수=None
            continue
        return 목표수, 처음_제시된_수_카드화(목표수)

def 명령어_오류테스트_1(부호,식):    #사용자가 입력한 명령어가 오류를 일으켰을때 팅기지 않게 합니다.
    try: list(map(float,식.split(부호)))
    except ValueError: print("잘못 입력하였습니다. 명령어를 다시 입력해주세요."); return True
    else: return False

def 명령어_오류테스트_2(부호,인수):    #사용자가 입력한 명령어가 오류를 일으켰을때 팅기지 않게 합니다.
    try:
        if 부호=="+":
            인수[0]+인수[1]
        elif 부호=="-":
            인수[0]-인수[1]
        elif 부호=="*":
            인수[0]*인수[1]
        elif 부호=="/":
            인수[0]/인수[1]
    except TypeError: print("잘못 입력하였습니다. 명령어를 다시 입력해주세요."); return True
    except ZeroDivisionError: print("0으로 나눌 수 없습니다! 다시 입력해주세요."); return True
    else: return False
    
def 명령어(가지고_있는_수,식):    #입력되는 명령어를 처리하여 하나의 데이터를 추가합니다.
    while True:
        while True:
            계산기_모드=False
            if 식.count('!')==1:
                식=식.lstrip("!")
                계산기_모드=True
                
            if 식=='뒤':
                print("방금 작성한 명령어를 지웁니다.")
                return "뒤"
            
            elif 식=='초기화':
                print("이때까지 작성한 명령어를 초기화합니다.")
                if input("모두 초기화하려면 '1'을 입력해주세요.")=='1':
                    return "초기화"
                else:
                    print("초기화를 하지 않습니다. 명령어를 입력해 주세요.")
                    식=input()
                    continue
                
            elif 식.count('+')==1 and not 식.count('-') and not 식.count('*') and not 식.count('/'):
                오류 = 명령어_오류테스트_1("+",식)
                if 오류:
                    식=input()
                    continue
                인수=list(map(float,식.split('+')))
                오류 = 명령어_오류테스트_2('+',인수)
                if 오류:
                    식=input()
                    continue
                새로운_수=인수[0]+인수[1]
                break
            
            elif not 식.count('+') and 식.count('-')==1 and not 식.count('*') and not 식.count('/'):
                오류 = 명령어_오류테스트_1('-',식)
                if 오류:
                    식=input()
                    continue
                인수=list(map(float,식.split('-')))
                오류 = 명령어_오류테스트_2('-',인수)
                if 오류:
                    식=input()
                    continue
                새로운_수=인수[0]-인수[1]
                break
            
            elif not 식.count('+') and not 식.count('-') and 식.count('*')==1 and not 식.count('/'):
                오류 = 명령어_오류테스트_1("*",식)
                if 오류:
                    식=input()
                    continue
                인수=list(map(float,식.split('*')))
                오류 = 명령어_오류테스트_2('*',인수)
                if 오류:
                    식=input()
                    continue
                새로운_수=인수[0]*인수[1]
                break
                
            elif not 식.count('+') and not 식.count('-') and not 식.count('*') and 식.count('/')==1:
                오류 = 명령어_오류테스트_1("/",식)
                if 오류:
                    식=input()
                    continue
                인수=list(map(float,식.split('/')))
                오류 = 명령어_오류테스트_2('/',인수)
                if 오류:
                    식=input()
                    continue
                새로운_수=인수[0]/인수[1]
                break
            else:
                print("잘못 입력하였습니다. 다시 명령어를 입력해주세요.")
                식=input()
                continue

        
        if 계산기_모드:
            print(새로운_수,"로 계산됩니다.")
            식=input()
            continue

        if 인수[0] in 가지고_있는_수 and 인수[1] in 가지고_있는_수:
            print(식,"을 통해 새로 추가할 수는",새로운_수,"입니다. 새로운 수를 넣으시겠습니까?")
            확인=input("1. 예,  그외) 아니오  ")
            if 확인=='1':
                return 새로운_수
            else:
                print("잘못된 선택입니다.")
                continue
                
        else:
            print("그 수를 가지고 있지 않습니다!! 명령어를 다시 입력해 주세요.")
            식=input()
            continue
        
    
def 게임시작():    #앞의 함수를 적절히 조합하여 하나의 게임을 구현합니다.
    print("\n게임을 시작합니다. 두 자리 이상의 정수를 입력하면 그 수를 목표하게 되고, \n아무것도 입력하지 않으면 랜덤으로 수를 목표하게 됩니다.")
    진행수 = 1
    목표수,가지고_있는_수=목표수_설정()

    while True:
        print("\n < ",진행수,"턴 입니다. >")
        print("\n목표수는",목표수,"이고, 현재 가지고 있는 수는",가지고_있는_수,"입니다.")
        print("명령어를 입력해 주세요.")
        가지고_있는_수.append(명령어(가지고_있는_수,input()))
        if 가지고_있는_수[-1]=='뒤':
            가지고_있는_수=가지고_있는_수[:len(가지고_있는_수)-2]
            진행수-=2
        elif 가지고_있는_수[-1]=='초기화':
            가지고_있는_수=처음_제시된_수_카드화(목표수)
            진행수=0
        elif 목표수 in 가지고_있는_수:
            return 목표수, 진행수
        진행수+=1

class 최단경로_찾기:
    def 초기설정(self):

def 최단경로_찾기(목표수):    #목표수에 대한 모든 경우를 조사하여 최단경로를 조사합니다. / 아직 개발중 입니다.
    가지고_있는_수=처음_제시된_수_카드화(목표수)
    선택된_수=list(itertools.combinations(가지고_있는_수,2))
    



while True:    #메인 메뉴
    print("\n무엇을 할지 숫자로 입력해 주세요.")
    메뉴=input("1. 게임 플레이,  2.게임 규칙,  3. 명령어 및 플레이 방법,  4.더 많은 연산자 모드,  5. 나가기  ")

    
    if 메뉴=='1':    #게임을 시작합니다.
        목표수,찾은_경로_수=게임시작()
        print("축하합니다.",찾은_경로_수,"턴 만에 문제를 해결하셨군요!\n\n\n")
        if input("1을 입력하여 최단경로를 찾아 볼 수 있습니다. 시간이 다소 걸릴 수 있습니다.")=='1':
            최단경로=최단경로_찾기(목표수)
            
        
    elif 메뉴=='2':    #이 게임에 대한 튜토리얼을 글로 표현합니다.
        print("\n============================================게임 규칙==========================================\n")
        print("숫자놀음은 '가지고 있는 수'를 가지고 연산하여 '새로운 수'를 만들어 '목표하는 수'에 맞추면 되는 게임입니다.",end=''); input()
        print("7과 8라는 숫자를 가지고 있고 목표하는 수가 72이라면 7*8을 취해 56을 맞추면 승리합니다."); input()
        print("처음에 제시된 수들은 각각 목표하는 수 한 자리를 취합니다.",end=''); input()
        print("789를 목표하는 수가 있으면 처음 제시되는 수는 7,8,9 세 개입니다. 777이며 7,7,7 세 개를 가지게 됩니다."); input()
        print("한번에 목표하는 수를 만들 수 없다면 가지고 있는 수를 연산하여 새로운 수를 만들어야 합니다.",end=''); input()
        print("예를 들어서 24라는 수가 있으면 초기에 2,4라는 수를 가지게 되고,\n2+4=6식을 통해 6이라는 새로운 수를 불러오고, 6*4=24을 통해 목표를 도달하면 되는 게임입니다."); input()
        print("참고로 새로운 수를 만들 때마다 하나씩 카운트 셉니다. 게임을 끝냈을 때, 최소로 셀 수 있도록 해 보세요!",end=''); input()
        print("\n=============================================================================================\n")

    elif 메뉴=='3':    #이 게임에 대한 방법을 글로 표현합니다.
        print("\n======================================명령어 및 플레이 방법======================================\n")
        print("첫번째로 목표수를 정합니다. 482라고 입력하면 목표수는 482가 되고 가지게 되는 수는 4,8,2입니다."); input()
        print("식을 입력하는 문장이 나오면 식을 입력해 줍니다. \n더 많은 연산자 모드를 끄면 이용 할 수 있는 연산명령어는 +,-,*,/ 4가지 입니다.",end=''); input()
        print("더 많은 연산자 모드를 키면 이용 할 수 있는 연산명령어는 +,-,*,**,/,//,% 7가지 입니다.",end=''); input()
        print("연산명령어는 다음과 같이 씁니다. '3+4', '4//2', '300*7', '10*0',  3개 이상의 연산명령어는 사용할 수 없습니다."); input() #개발중. 아마 안 만들지 않을까 생각됨
        print("'4*8'이렇게 식 입력을 하면 자동으로 32를 분석해 주고 그 수를 넣을지 물어봅니다. \n하지만 가지고 있는 수에 포함되지 않으면 실행되지 않습니다.",); input()
        print("연산명령어 앞에 !를 붙이면 단순히 계산 결과만 알려줍니다. 꼭 수를 가지지 않아도 계산이 됩니다.",AttributeErrorend=''); input()
        print("'!42*3'이렇게 식 입력을 하면 126을 보여준 뒤 다시 명령어를 받게 됩니다.");input()
        print("'뒤' 라고 입력하면 최근에 생성한 수를 지워줍니다. 카운트가 하나 줄어듭니다.",end=''); input() 
        print("'초기화' 라고 입력하면 다시 초기 상태로 돌아가게 됩니다. 카운트가 초기화됩니다."); input()
        print("\n=============================================================================================\n")

    elif 메뉴=='4':    #설정: 연산자 모드
        if 연산자_모드=='1':    print("현재 더 많은 연산자 모드는 비활성화되어 있습니다.")
        else:    print("\n현재 더 많은 연산자 모드는 활성화 되어 있습니다.") #개발중. 아마 안 만들지 않을까 생각
        print("더 많은 연산자 모드를 활성화 시키면 제곱, 몫, 나머지 모두 사용할 수 있으며 비활성화하면 사칙연산만 사용 할 수 있습니다.")
        print("\n연산자 모드를 어떻게 하시겠습니까?")
        연산자_모드=input("1. 비활성화,  2. 활성화  ")
        while 연산자_모드!='1' and 연산자_모드!='2':
            print("잘못 입력하였습니다 다시 입력해 주세요.")
            연산자_모드=input("1. 비활성화,  2. 활성화  ")
        if 연산자_모드=='1':    print("더 많은 연산자 모드를 비활성화합니다."); input()
        else:    print("더 많은 연산자 모드를 활성화합니다."); input()

    elif 메뉴=='5':    #종료
        print("엔터키를 눌러 프로그램을 종료합니다. 취소하고 싶으면 '취소'를 입력하세요")
        if input()=='취소':    sys.exit()
        else:    print("취소하여 초기메뉴로 돌아갑니다.\n"); input()
        
    else:
        print("잘못된 값을 입력하여 초기메뉴로 돌아갑니다.\n"); input()
