Example #1
0
 public void CombineAdd(CardCombine c, int point)
 {
     for (int i = 0; i < combines.Count; i++)
     {
         if (combines[i] == c)
         {
             Debug.Log("same");
             combines[i].bias += point;
             return;
         }
     }
     c.bias += point;
     combines.Add(c);
 }
Example #2
0
    public void Combine(Deck.CombineMethod method)
    {
        int               index   = 0;
        CardCombine       combine = deck.Combine(method);
        List <CardOnDeck> list    = deck.Sort();

        foreach (CardGroup group in combine.members)
        {
            if (index < 14 && (index + group.members.Count) > 13)
            {
                while (index < 14)
                {
                    deck.slots[index] = null;
                    index++;
                }
            }

            foreach (CardOnDeck card in group.members)
            {
                list.Remove(card);
                deck.slots[index] = card.card;
                index++;
            }
            deck.slots[index] = null;
            index++;
        }
        while (index < 28)
        {
            deck.slots[index] = null;
            index++;
        }

        while (list.Count > 0)
        {
            index--;
            CardOnDeck card = list.Last();
            list.Remove(card);
            deck.slots[index] = card.card;
        }
    }
Example #3
0
 // 카드 이름 입력 완료
 public void Typed()
 {
     // 카드 이름 저장하는 함수
     if (input.text == "" || input.text.Trim() == "")
     {
         Debug.Log("none of text");
     }
     else if (selectedCards.Count == 1)
     {
         // 선택한 카드가 하나일 경우 -> 카드의 조합형만 저장
         int i = System.Convert.ToInt32(selectedCards[0].name.Split('_')[1]), j = System.Convert.ToInt32(selectedCards[0].name.Split('_')[2]);
         if (GameManager.instance.cards[i - 1][j - 1].name == "")
         {
             GameManager.instance.cards[i - 1][j - 1].name = input.text;
         }
         CardCombine cc = new CardCombine(input.text, false, -1, false, input.text.Trim());
         GameManager.instance.cards[i - 1][j - 1].CombineAdd(cc, 3);
     }
     else
     {
         // 선택한 카드가 여러 개일 경우
         GameManager.instance.MultiCardLearning(selectedCards, input.text, false);
     }
     // 후처리
     foreach (var c in selectedCards)
     {
         c.GetComponent <Card>().Unselect();
     }
     selectedCards.Clear();
     input.gameObject.SetActive(false);
     message.text = "낱말카드를 선택하세요";
     message.GetComponent <TextBlinking>().enable = true;
     cardCam.gameObject.SetActive(false);
     input.text = "";
     GameManager.instance.SaveData();
 }
Example #4
0
    // 문장 학습 결과
    public void Result(int a)
    {
        switch (a)
        {
        case 0:                             // OK
            resultWindow.SetActive(false);
            for (int i = 0; i < selectedCards.Count; i++)
            {
                int m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
                int mf = -1, mr = -1;
                if (i != 0)
                {
                    mf = System.Convert.ToInt32(selectedCards[i - 1].name.Split('_')[1]);
                }
                else if (i != selectedCards.Count - 1)
                {
                    mr = System.Convert.ToInt32(selectedCards[i + 1].name.Split('_')[1]);
                }
                if (selectedCards.Count == 1)
                {
                    break;
                }

                if (i != 0)                                                             // 앞쪽
                {
                    CardCombine cc = new CardCombine(usedCombines[i].style, true, mf, i == selectedCards.Count - 1, usedCombines[i].root);
                    GameManager.instance.cards[m - 1][n - 1].CombineAdd(cc, 5);
                    string front = cc.style.Split(new[] { cc.root }, StringSplitOptions.None)[0].TrimStart();
                    // 형태소 추가
                    bool morpfound = false;
                    foreach (Morpheme morp in GameManager.instance.morphemes)
                    {
                        if (morp.name == cc.root)
                        {
                            morpfound = true;
                            if (front != "")
                            {
                                morp.Connects(front, mf, true);
                            }
                            break;
                        }
                    }
                    if (!morpfound)
                    {
                        GameManager.instance.morphemes.Add(new Morpheme(cc.root, m, n));
                        if (front != "")
                        {
                            GameManager.instance.morphemes[GameManager.instance.morphemes.Count - 1].Connects(front, mf, true);
                        }
                    }
                }
                if (i != selectedCards.Count - 1)                                       // 뒷쪽
                {
                    CardCombine cc = new CardCombine(usedCombines[i].style, false, mr, false, usedCombines[i].root);
                    GameManager.instance.cards[m - 1][n - 1].CombineAdd(cc, 5);
                    string rear = cc.style.Split(new[] { cc.root }, StringSplitOptions.None)[1].TrimEnd();
                    // 형태소 추가
                    bool morpfound = false;
                    foreach (Morpheme morp in GameManager.instance.morphemes)
                    {
                        if (morp.name == cc.root)
                        {
                            morpfound = true;
                            if (rear != "")
                            {
                                morp.Connects(rear, mr, false);
                            }
                            break;
                        }
                    }
                    if (!morpfound)
                    {
                        GameManager.instance.morphemes.Add(new Morpheme(cc.root, m, n));
                        if (rear != "")
                        {
                            GameManager.instance.morphemes[GameManager.instance.morphemes.Count - 1].Connects(rear, mr, false);
                        }
                    }
                }
            }
            EndofTesting();
            break;

        case 1:                             // SOSO
            for (int i = 0; i < selectedCards.Count; i++)
            {
                int m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
                int mf = -1, mr = -1;
                if (i != 0)
                {
                    mf = System.Convert.ToInt32(selectedCards[i - 1].name.Split('_')[1]);
                }
                else if (i != selectedCards.Count - 1)
                {
                    mr = System.Convert.ToInt32(selectedCards[i + 1].name.Split('_')[1]);
                }
                if (selectedCards.Count == 1)
                {
                    break;
                }

                if (i != 0)                                                             // 앞쪽
                {
                    CardCombine cc = new CardCombine(usedCombines[i].style, true, mf, i == selectedCards.Count - 1, usedCombines[i].root);
                    GameManager.instance.cards[m - 1][n - 1].CombineAdd(cc, 1);
                }
                if (i != selectedCards.Count - 1)                                       // 뒷쪽
                {
                    CardCombine cc = new CardCombine(usedCombines[i].style, false, mr, false, usedCombines[i].root);
                    GameManager.instance.cards[m - 1][n - 1].CombineAdd(cc, 1);
                }
            }
            decisions.SetActive(false);
            reorders.SetActive(true);
            break;

        case 2:                             // NO
            decisions.SetActive(false);
            reorders.SetActive(true);
            break;

        case 3:                             // Force Exit
            resultWindow.SetActive(false);
            EndofTesting();
            break;
        }
    }
Example #5
0
    void MakeSentence()
    {
        result = "";
        if (usedCombines.Count == 0)
        {
            for (int i = 0; i < selectedCards.Count; i++)
            {
                usedCombines.Add(new CardCombine());
            }
        }

        // 선택된 카드가 하나라면
        if (selectedCards.Count == 1)
        {
            int m = System.Convert.ToInt32(selectedCards[0].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[0].name.Split('_')[2]);
            resultWindow.transform.GetChild(1).GetComponent <Text>().text = GameManager.instance.cards[m - 1][n - 1].name;
            usedCombines[0] = new CardCombine(GameManager.instance.cards[m - 1][n - 1].name, true, -1, true, GameManager.instance.cards[m - 1][n - 1].name);
            return;
        }

        for (int i = 0; i < selectedCards.Count; i++)
        {
            // 맨 끝인 경우
            if (i == 0)
            {
                result         += orderedCombines[i][selectedCombines[i]].combine.style;
                usedCombines[i] = orderedCombines[i][selectedCombines[i]].combine;
            }
            else if (i == selectedCards.Count - 1)
            {
                result         += orderedCombines[i * 2 - 1][selectedCombines[i * 2 - 1]].combine.style;
                usedCombines[i] = orderedCombines[i * 2 - 1][selectedCombines[i * 2 - 1]].combine;
            }
            else
            {
                CardCombine f = orderedCombines[i * 2 - 1][selectedCombines[i * 2 - 1]].combine;                   // 앞
                CardCombine b = orderedCombines[i * 2][selectedCombines[i * 2]].combine;                           // 뒤
                // 모두 원형 = 둘이 같음
                if (f.combinedWith == -2 && b.combinedWith == -2)
                {
                    result         += f.style;
                    usedCombines[i] = f;
                }
                // 둘 중 하나가 원형 = 원형 아닌 쪽
                else if (f.combinedWith == -2 || b.combinedWith == -2)
                {
                    result         += f.combinedWith == -2 ? b.style : f.style;
                    usedCombines[i] = (f.combinedWith == -2 ? b : f);
                }
                else
                {
                    // 앞과 뒤가 같음
                    if (f == b)
                    {
                        result += f.style;
                        usedCombines.Add(f);
                    }
                    // 앞과 뒤가 다름 = 가중치가 큰 쪽
                    else
                    {
                        result         += f.bias > b.bias ? f.style : b.style;
                        usedCombines[i] = (f.bias > b.bias ? f : b);
                    }
                }
            }
        }
        resultWindow.transform.GetChild(1).GetComponent <Text>().text = result;
    }
Example #6
0
    // 카드 선택 완료
    public void Done()
    {
        // 미학습 카드 에러
        foreach (var c in selectedCards)
        {
            int m = System.Convert.ToInt32(c.name.Split('_')[1]), n = System.Convert.ToInt32(c.name.Split('_')[2]);
            if (GameManager.instance.cards[m - 1][n - 1].name == "")
            {
                cardCanvas.GetComponent <CardCanvas>().TestError();
                foreach (var d in selectedCards)
                {
                    d.GetComponent <Card>().Unselect();
                }
                OnDisable();
                return;
            }
        }
        done.SetActive(false);
        resultWindow.SetActive(true);
        // 우선순위 리스트 제작
        for (int i = 0; i < selectedCards.Count; i++)
        {
            // 리스트 생성 준비
            orderedCombines.Add(new List <TestCombine>());
            if (i > 0 && i < selectedCards.Count - 1)
            {
                orderedCombines.Add(new List <TestCombine>());
            }
            int    m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
            string originalName = GameManager.instance.cards[m - 1][n - 1].name;
            // 리스트에 넣고 정렬
            if (i * 2 - 1 != -1)
            {
                // 홀수 - 앞
                int mf = System.Convert.ToInt32(selectedCards[i - 1].name.Split('_')[1]);
                // 조합식들 투입
                for (int j = 0; j < GameManager.instance.cards[m - 1][n - 1].combines.Count; j++)
                {
                    if (GameManager.instance.cards[m - 1][n - 1].combines[j].position)
                    {
                        orderedCombines[i * 2 - 1].Add(new TestCombine(GameManager.instance.cards[m - 1][n - 1].combines[j], j));
                        // 만약 띄어쓰기가 있는 언어인 상황에서 현재 조합식에 띄어쓰기가 없는 경우, 띄어쓰기가 있는 버전도 투입
                        if (GameManager.instance.spacing && GameManager.instance.cards[m - 1][n - 1].combines[j].style[0] != ' ')
                        {
                            CardCombine c  = GameManager.instance.cards[m - 1][n - 1].combines[j];
                            CardCombine cc = new CardCombine(" " + c.style, c.position, c.combinedWith, c.isEnd, c.root);
                            orderedCombines[i * 2 - 1].Add(new TestCombine(cc, -1));
                        }
                    }
                }
                // 원래 이름(-2) 투입
                orderedCombines[i * 2 - 1].Add(new TestCombine(new CardCombine(
                                                                   GameManager.instance.GetSpacing() ? " " + originalName : originalName, true, -2, i == selectedCards.Count - 1 ? true : false, originalName), -1));
                orderedCombines[i * 2 - 1].Sort(delegate(TestCombine x, TestCombine y) {
                    // 맞는 -> 다른 -> -2
                    // end는 상황에 따라 최상위 or 최하위
                    if (x.combine.isEnd && !y.combine.isEnd)
                    {
                        return(i == selectedCards.Count - 1 ? -1 : 1);
                    }
                    else if (!x.combine.isEnd && y.combine.isEnd)
                    {
                        return(i == selectedCards.Count - 1 ? 1 : -1);
                    }
                    if (x.combine.combinedWith == -2 && x.combine.combinedWith != -2)
                    {
                        return(1);
                    }
                    else if (x.combine.combinedWith != -2 && x.combine.combinedWith == -2)
                    {
                        return(-1);
                    }
                    if (x.combine.combinedWith == mf && y.combine.combinedWith != mf)
                    {
                        return(-1);
                    }
                    else if (x.combine.combinedWith != mf && y.combine.combinedWith == mf)
                    {
                        return(1);
                    }
                    else
                    {
                        return(x.combine.bias.CompareTo(y.combine.bias) * -1);
                    }
                });
                // 현재 조합 관계가 아닌 것들 중에서 중복된 게 있을 경우 제거
                List <string>      exist  = new List <string>();
                List <TestCombine> remove = new List <TestCombine>();
                foreach (var tc in orderedCombines[i * 2 - 1])
                {
                    if (!exist.Contains(tc.combine.style))
                    {
                        exist.Add(tc.combine.style);
                    }
                    else
                    {
                        if (tc.combine.combinedWith != mf)
                        {
                            remove.Add(tc);
                        }
                    }
                }
                foreach (var r in remove)
                {
                    orderedCombines[i * 2 - 1].Remove(r);
                }
                foreach (var tc in orderedCombines[i * 2 - 1])
                {
                    print(tc.combine.ToString());
                }
            }
            if (i * 2 < (selectedCards.Count - 1) * 2)
            {
                // 짝수 - 뒤
                int mr = System.Convert.ToInt32(selectedCards[i + 1].name.Split('_')[1]);
                // 조합식들 투입
                for (int j = 0; j < GameManager.instance.cards[m - 1][n - 1].combines.Count; j++)
                {
                    if (!GameManager.instance.cards[m - 1][n - 1].combines[j].position)
                    {
                        orderedCombines[i * 2].Add(new TestCombine(GameManager.instance.cards[m - 1][n - 1].combines[j], j));
                    }
                }
                // 원래 이름(-2) 투입
                orderedCombines[i * 2].Add(new TestCombine(new CardCombine(
                                                               i != 0 && GameManager.instance.GetSpacing() ? " " + originalName : originalName, false, -2, false, originalName), -1));
                orderedCombines[i * 2].Sort(delegate(TestCombine x, TestCombine y) {
                    // 맞는 -> 다른 -> -2
                    if (x.combine.combinedWith == -2 && x.combine.combinedWith != -2)
                    {
                        return(1);
                    }
                    else if (x.combine.combinedWith != -2 && x.combine.combinedWith == -2)
                    {
                        return(-1);
                    }
                    if (x.combine.combinedWith == mr && y.combine.combinedWith != mr)
                    {
                        return(-1);
                    }
                    else if (x.combine.combinedWith != mr && y.combine.combinedWith == mr)
                    {
                        return(1);
                    }
                    else
                    {
                        return(x.combine.bias.CompareTo(y.combine.bias) * -1);
                    }
                });
                // 현재 조합 관계가 아닌 것들 중에서 중복된 게 있을 경우 제거
                List <string>      exist  = new List <string>();
                List <TestCombine> remove = new List <TestCombine>();
                foreach (var tc in orderedCombines[i * 2])
                {
                    if (!exist.Contains(tc.combine.style))
                    {
                        exist.Add(tc.combine.style);
                    }
                    else
                    {
                        if (tc.combine.combinedWith != mr)
                        {
                            remove.Add(tc);
                        }
                    }
                }
                foreach (var r in remove)
                {
                    orderedCombines[i * 2].Remove(r);
                }
                foreach (var tc in orderedCombines[i * 2])
                {
                    print(tc.combine.ToString());
                }
            }
            // 지난 우선순위 표시기 초기화
            reservedCombines.Add(new List <int>());
            for (int j = 0; j < 3; j++)
            {
                reservedCombines[i].Add(0);
            }
        }
        // 선택된 우선순위 표시기 초기화
        foreach (var p in orderedCombines)
        {
            selectedCombines.Add(0);
        }

        // 문장 만드는 함수
        MakeSentence();
    }
Example #7
0
 public TestCombine(CardCombine c, int idx)
 {
     combine = c; index = idx;
 }
    // 카드 데이터 불러오기
    public void CardLoad()
    {
        cards.Clear();
        morphemes.Clear();
        spacing = false;
        CardCheck();
        FileInfo fi = new FileInfo("cardData" + slot + ".data");

        if (!fi.Exists)
        {
            FileStream fs = File.Create("cardData" + slot + ".data");
            fs.Close();
            StreamWriter sw = new StreamWriter("cardData" + slot + ".data");
            sw.WriteLine("--------");
            sw.Close();
        }
        else
        {
            StreamReader sr = new StreamReader("cardData" + slot + ".data");
            string       s;
            int          g = 0, n = 0;
            // 카드와 조합식 저장
            while ((s = sr.ReadLine()) != "--------")
            {
                // 숫자면 해당 번호에 (줄바꿈) 이름 저장
                if (char.IsDigit(s[0]))
                {
                    g = Convert.ToInt32(s.Split(' ')[0]);
                    n = Convert.ToInt32(s.Split(' ')[1]);
                    s = sr.ReadLine();
                    cards[g - 1][n - 1].name = s;
                }
                // "면 지금 번호에 조합식 저장
                else if (s[0] == '"')
                {
                    CardCombine c = new CardCombine();
                    c.style = s.Split('"')[1];
                    if (!spacing && c.style[0] == ' ')
                    {
                        spacing = true;
                    }
                    string p = s.Split('"')[2];
                    c.position     = p.Split(' ')[0] == "f" ? true : false;
                    c.combinedWith = Convert.ToInt32(p.Split(' ')[1]);
                    c.bias         = Convert.ToInt32(p.Split(' ')[2]);
                    c.position     = p.Split(' ')[3] == "e" ? true : false;
                    c.root         = p.Split('#')[1];
                    cards[g - 1][n - 1].combines.Add(c);
                }
                // §면 다음 번호로
                else if (s[0] == '§')
                {
                    continue;
                }
            }
            // 형태소 저장
            while ((s = sr.ReadLine()) != null)
            {
                // §면 다음 번호로
                if (s[0] == '§')
                {
                    continue;
                }
                // "면 지금 형태소에 조합 저장
                else if (s[0] == '"')
                {
                    string          p  = s.Split('"')[1];
                    string          q  = s.Split('"')[2];
                    int             b  = Convert.ToInt32(q.Split(' ')[1]);
                    MorphemeConnect mc = new MorphemeConnect();
                    mc.bias = b;
                    string[] k = sr.ReadLine().Split(' ');
                    foreach (string kk in k)
                    {
                        if (kk != "")
                        {
                            mc.connectWith.Add(Convert.ToInt32(kk));
                        }
                    }
                    if (q.Split(' ')[0] == "f")
                    {
                        morphemes[morphemes.Count - 1].fronts.Add(p, mc);
                    }
                    else
                    {
                        morphemes[morphemes.Count - 1].backs.Add(p, mc);
                    }
                }
                // 아니면 새로운 형태소로 저장
                else
                {
                    string   name  = s;
                    string   c     = sr.ReadLine();
                    int      group = Convert.ToInt32(c.Split(' ')[0]);
                    int      num   = Convert.ToInt32(c.Split(' ')[1]);
                    Morpheme mm    = new Morpheme(name, group, num);
                    morphemes.Add(mm);
                }
            }
            sr.Close();
        }
    }
    // 어근 변형 자동학습
    void AutoRoot(int main, int num, int sub, bool dir)
    {
        // 현재 카드에서 생성된 어근이 다른 모든 조합식 추출
        List <CardCombine> currentCombines = new List <CardCombine>();
        // 같은 카드군의 다른 카드에서 현재 카드군 조합의 어근이 다른 조합식 추출
        List <CardCombine> otherSameCombines = new List <CardCombine>();
        // 같은 카드군의 다른 카드에서 현재 카드군 조합이 아닌 어근이 다른 조합식 추출
        List <CardCombine> otherDiffCombines = new List <CardCombine>();

        // 조건에 맞는 조합식 추출
        // 그 과정에서 현재 카드의 붙는 카드군, 방향이 같은 조합식을 발견하면 모두 가중치를 올려주고 학습 중단
        for (int i = 0; i < cards[main - 1].Count; i++)
        {
            bool find = false;
            foreach (CardCombine c in cards[main - 1][i].combines)
            {
                if (c.root != cards[main - 1][i].name && c.position == dir)
                {
                    if (i == num - 1)
                    {
                        if (c.combinedWith == sub)
                        {
                            c.bias++;
                            find = true;
                        }
                        else
                        {
                            currentCombines.Add(c);
                        }
                    }
                    else
                    {
                        if (c.combinedWith == sub)
                        {
                            otherSameCombines.Add(c);
                        }
                        else
                        {
                            otherDiffCombines.Add(c);
                        }
                    }
                }
            }
            if (find)
            {
                return;
            }
        }
        // 만약 현재 카드의 어근 변화 사례 또는 다른 카드의 어근 변화 사례가 없으면 학습 미진행
        if (otherDiffCombines.Count == 0 || currentCombines.Count == 0)
        {
            return;
        }

        // 자동학습
        // 같은 카드군의 다른 카드에서 생성된 어근 변화 사례 중 현재 카드군과의 조합식 형태가 다른 카드군과의 조합에도 등장하는 경우를 뽑아 리스트를 만들고,
        // 현재 카드의 어근 변화 사례 중 리스트의 조합식과 조합되는 카드군이 같은 것이 발견될 경우 그 조합식을 현재 카드군 조합으로 학습
        List <CardCombine> matchedCombines = new List <CardCombine>();

        foreach (CardCombine os in otherSameCombines)
        {
            foreach (CardCombine od in otherDiffCombines)
            {
                if (os.style == od.style)
                {
                    matchedCombines.Add(od);
                }
            }
        }
        foreach (CardCombine mc in matchedCombines)
        {
            foreach (CardCombine cc in currentCombines)
            {
                if (mc.combinedWith == cc.combinedWith)
                {
                    CardCombine cn = new CardCombine(cc.style, dir, sub, cc.isEnd, cc.root);
                    cards[main - 1][num - 1].CombineAdd(cn, 1);
                }
            }
        }
    }
Example #10
0
    // 구문/문장 학습
    public void MultiCardLearning(List <GameObject> selectedCards, string input, bool mode)
    {
        int[,] cardRange     = new int[selectedCards.Count, 2];         // 조합식 영역
        int[,] originalRange = new int[selectedCards.Count, 2];         // 원래 단어 영역
        bool[] isOriginal = new bool[selectedCards.Count];              // 조합된 형태가 원본인가?(카드군 자동 학습에 필요)

        // 2-1. 단어 원본 찾기 - V
        for (int i = 0; i < selectedCards.Count; i++)
        {
            cardRange[i, 0] = -1; cardRange[i, 1] = -1; isOriginal[i] = false;                                                                       // 초기 상태
            int    m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]); // 카드군-번호 따기
            string currentName = cards[m - 1][n - 1].name;                                                                                           // 현재 카드 단어 원본
            if (currentName == "")                                                                                                                   // 이름이 없으면 패스
            {
                continue;
            }
            for (int j = cardRange[i == 0 ? i : i - 1, 1] + 1; j <= input.Length - currentName.Length; j++)
            {
                if (input.Substring(j, currentName.Length) == currentName)                      // 원본 발견?
                {
                    cardRange[i, 0] = j; cardRange[i, 1] = j + currentName.Length - 1;
                    isOriginal[i]   = true;
                    break;
                }
            }
        }
        // 2-3. 조합식으로 탐색 - V
        for (int i = 0; i < selectedCards.Count; i++)
        {
            if (cardRange[i, 0] == -1)
            {
                int m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
                foreach (var c in cards[m - 1][n - 1].combines)                         // 조합식 순회
                {
                    string currentName = c.style;                                       // 현재 조합식
                    if (currentName == "")
                    {
                        continue;
                    }
                    for (int j = cardRange[i == 0 ? i : i - 1, 1] + 1; j <= input.Length - currentName.Length; j++)
                    {
                        if (input.Substring(j, currentName.Length) == currentName)                              // 조합식 발견?
                        {
                            cardRange[i, 0] = j; cardRange[i, 1] = j + currentName.Length - 1;
                            break;
                        }
                    }
                    if (cardRange[i, 0] != -1)
                    {
                        break;
                    }
                }
            }
        }
        // 2-4. 한글 종성 체크(맨앞글자) - V
        for (int i = 0; i < selectedCards.Count; i++)
        {
            if (cardRange[i, 0] == -1)
            {
                int m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
                if (cards[m - 1][n - 1].name.Length > 1 && (cards[m - 1][n - 1].name[0] - 44032) % 28 == 0)                     // 카드 이름이 한 글자 이상이고 맨 앞글자가 받침 없는 한글인가?
                {
                    string currentName = cards[m - 1][n - 1].name;
                    for (int j = cardRange[i == 0 ? i : i - 1, 1] + 1; j <= input.Length - currentName.Length; j++)
                    {
                        string p = input.Substring(j, currentName.Length);
                        p = ((char)(p[0] - ((p[0] - 44032) % 28))).ToString() + p.Substring(1);
                        if (p == currentName)
                        {
                            cardRange[i, 0] = j; cardRange[i, 1] = j + currentName.Length - 1;
                            break;
                        }
                    }
                }
            }
        }
        // 2-5. 앞 글자들만 검색 - V
        for (int i = 0; i < selectedCards.Count; i++)
        {
            if (cardRange[i, 0] == -1)
            {
                int    m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);
                string origin = cards[m - 1][n - 1].name;                   // 원래 단어
                if (origin.Length > 1)
                {
                    for (int k = 1; k < origin.Length; k++)                                     // 단어 길이 줄여가기
                    {
                        string cut = origin.Substring(0, origin.Length - k);
                        // 알파벳 1글자면 패스
                        if (cut.Length == 1 && cut[0] < 256)
                        {
                            break;
                        }
                        for (int j = cardRange[i == 0 ? i : i - 1, 1] + 1; j <= input.Length - cut.Length; j++)
                        {
                            if (input.Substring(j, cut.Length) == cut)
                            {
                                cardRange[i, 0] = j; cardRange[i, 1] = j + cut.Length - 1;
                                break;
                            }
                        }
                    }
                }
            }
        }
        // 2-6. 전 단어 다음 글자 - V
        for (int i = 0; i < selectedCards.Count; i++)
        {
            if (cardRange[i, 0] == -1)
            {
                if (i == 0)
                {
                    cardRange[i, 0] = cardRange[i, 1] = 0;
                }
                else
                {
                    cardRange[i, 0] = cardRange[i, 1] = cardRange[i - 1, 1] + 1;
                }
            }
        }
        // 겹친 구역 최종 보정(앞쪽 우선)
        for (int i = 1; i < selectedCards.Count; i++)
        {
            if (cardRange[i, 0] < cardRange[i - 1, 1])
            {
                cardRange[i, 0] = cardRange[i - 1, 1] + 1;
                if (cardRange[i, 0] > cardRange[i, 1])
                {
                    cardRange[i, 1] = cardRange[i, 0];
                }
            }
        }
        cardRange[0, 0] = 0;
        cardRange[selectedCards.Count - 1, 1] = input.Length - 1;
        // 3-1. 조합형 우측 확장
        for (int i = 0; i < selectedCards.Count - 1; i++)
        {
            while (input[cardRange[i, 1] + 1] != ' ' && cardRange[i, 1] + 1 != cardRange[i + 1, 0])
            {
                cardRange[i, 1]++;
            }
            //if (cardRange[i, 1] > cardRange[i, 0])
            //	cardRange[i, 1] = cardRange[i, 0];
        }
        // 3-3. 조합형 좌측 확장
        for (int i = 1; i < selectedCards.Count; i++)
        {
            cardRange[i, 0] = cardRange[i - 1, 1] + 1;
        }
        // 저장
        for (int i = 0; i < selectedCards.Count; i++)
        {
            Debug.LogFormat("{0}:{1}-{2}", i, cardRange[i, 0], cardRange[i, 1]);
            int s = cardRange[i, 0], l = cardRange[i, 1] - cardRange[i, 0] + 1;
            if (l <= 0)
            {
                continue;
            }
            int m = System.Convert.ToInt32(selectedCards[i].name.Split('_')[1]), n = System.Convert.ToInt32(selectedCards[i].name.Split('_')[2]);

            // 어근 확정
            originalRange[i, 0] = originalRange[i, 1] = -1;
            string origin = cards[m - 1][n - 1].name;
            bool   get    = false;
            if (origin.Length > 1)
            {
                for (int k = 0; k < origin.Length; k++)                                 // 단어 길이 줄여가기
                {
                    string cut = origin.Substring(0, origin.Length - k);
                    for (int j = originalRange[i == 0 ? i : i - 1, 1] + 1; j <= input.Length - cut.Length; j++)
                    {
                        if (input.Substring(j, cut.Length) == cut)
                        {
                            originalRange[i, 0] = j; originalRange[i, 1] = j + cut.Length - 1;
                            get = true;
                            break;
                        }
                    }
                    if (get)
                    {
                        break;
                    }
                }
            }
            if (originalRange[i, 0] == -1)                      // 단어로 어근을 찾지 못했다면 전 조합식 뒤의 공백 이후 첫 글자로 찾기
            {
                int ss = s;
                while (input[ss] == ' ')
                {
                    ss++;
                }
                originalRange[i, 0] = originalRange[i, 1] = ss;
            }
            string combine = input.Substring(s, l);                                                                                 // 조합
            string root    = input.Substring(originalRange[i, 0], originalRange[i, 1] - originalRange[i, 0] + 1);                   // 어근
            string front   = combine.Split(new[] { root }, StringSplitOptions.None)[0].TrimStart();                                 // 앞쪽 형태소
            string rear    = combine.Split(new[] { root }, StringSplitOptions.None)[1].TrimEnd();                                   // 뒤쪽 형태소

            // 조합식 및 형태소 저장
            // 없는 이름 등록
            if (cards[m - 1][n - 1].name == "")
            {
                cards[m - 1][n - 1].name = (combine[0] == ' ' ? combine.Substring(1) : combine);
            }
            // 띄어쓰기 탐지
            if (!spacing && combine[0] == ' ')
            {
                spacing = true;
            }
            // 앞쪽으로 저장
            if (i != 0)
            {
                int mf = System.Convert.ToInt32(selectedCards[i - 1].name.Split('_')[1]);
                // 조합식
                CardCombine c = new CardCombine(combine, true, mf, mode && i == selectedCards.Count - 1 ? true : false, root);
                cards[m - 1][n - 1].CombineAdd(c, 2);
                if (isOriginal[i])                               // 유사 형태 형태소 자동학습 - 지금 조합하려는 카드가 원본으로 사용된다면
                {
                    for (int j = 0; j < cards[m - 1].Count; j++) // 카드군의 카드 순회하기
                    {
                        if (j == n - 1 || cards[m - 1][j].name == "")
                        {
                            continue;
                        }

                        string am        = AutoMorpheme(m, mf, cards[m - 1][j].name, true);                                     // 붙는 어근에 자동학습 알고리즘 적용
                        string newstring = (combine[0] == ' ' ? " " : "") + am + cards[m - 1][j].name;
                        if (am == "§")
                        {
                            newstring = combine.Replace(cards[m - 1][n - 1].name, cards[m - 1][j].name);                                                  // 초기 학습 상태라면 입력된 조합식을 이용해 초기 자동학습
                        }
                        CardCombine cn = new CardCombine(newstring, true, mf, mode && i == selectedCards.Count - 1 ? true : false, cards[m - 1][j].name); // 새로운 조합식
                        cards[m - 1][j].CombineAdd(cn, 1);                                                                                                // 저장
                    }
                }
                else                                            // 변형 어근 자동학습 - 원본으로 사용되지 않는다면
                {
                    for (int j = 0; j < cards[m - 1].Count; j++)
                    {
                        if (j != n - 1)
                        {
                            AutoRoot(m, j, mf, true);
                        }
                    }
                }
                // 형태소
                bool morpfound = false;
                foreach (Morpheme morp in morphemes)
                {
                    if (morp.name == root)
                    {
                        morpfound = true;
                        if (front != "")
                        {
                            morp.Connects(front, mf, true);
                        }
                    }
                }
                if (!morpfound)
                {
                    morphemes.Add(new Morpheme(root, m, n));
                    if (front != "")
                    {
                        morphemes[morphemes.Count - 1].Connects(front, mf, true);
                    }
                }
            }
            // 뒷쪽으로 저장
            if (i != selectedCards.Count - 1)
            {
                int mr = System.Convert.ToInt32(selectedCards[i + 1].name.Split('_')[1]);
                // 조합식
                CardCombine c = new CardCombine(combine, false, mr, false, root);
                cards[m - 1][n - 1].CombineAdd(c, 2);
                if (isOriginal[i])                              // 유사 형태 형태소 자동학습
                {
                    for (int j = 0; j < cards[m - 1].Count; j++)
                    {
                        if (j == n - 1 || cards[m - 1][j].name == "")
                        {
                            continue;
                        }

                        string am        = AutoMorpheme(m, mr, cards[m - 1][j].name, false);                                     // 붙는 어근에 자동학습 알고리즘 적용
                        string newstring = (combine[0] == ' ' ? " " : "") + cards[m - 1][j].name + am;
                        if (am == "§")
                        {
                            newstring = combine.Replace(cards[m - 1][n - 1].name, cards[m - 1][j].name);                              // 초기 학습 상태라면 입력된 조합식을 이용해 초기 자동학습
                        }
                        CardCombine cn = new CardCombine(newstring, false, mr, false, cards[m - 1][j].name);
                        cards[m - 1][j].CombineAdd(cn, 1);
                    }
                }
                else                                            // 변형 어근 자동학습
                {
                    for (int j = 0; j < cards[m - 1].Count; j++)
                    {
                        if (j != n - 1)
                        {
                            AutoRoot(m, j, mr, false);
                        }
                    }
                }
                // 형태소
                bool morpfound = false;
                foreach (Morpheme morp in morphemes)
                {
                    if (morp.name == root)
                    {
                        morpfound = true;
                        if (rear != "")
                        {
                            morp.Connects(rear, mr, false);
                        }
                    }
                }
                if (!morpfound)
                {
                    morphemes.Add(new Morpheme(root, m, n));
                    if (rear != "")
                    {
                        morphemes[morphemes.Count - 1].Connects(rear, mr, false);
                    }
                }
            }
        }
    }