private void BtnExtraSearch_Click(object sender, RoutedEventArgs e)
        {
            ClearExtraResults();
            bool CanSearch = CollectEx();

            if (CanSearch)
            {
                if (!IsExtraCollating)
                {
                    IsExtraCollating = true;
                    tblStepInfo.Text = "";
                    SolverParam param = new SolverParam()
                    {
                        MaxStep     = stepLimits[cbMaxStepEx.SelectedIndex],
                        NeedShuffle = (bool)tgRandomInitEx.IsChecked,
                        Reuse       = false
                    };
                    worker                     = new BackgroundWorker();
                    worker.DoWork             += SearchExCollate;
                    worker.RunWorkerCompleted += SearchExDone;
                    worker.RunWorkerAsync(param);
                    SetCollating();
                    lblExtraProg.Content = "搜索中…";
                }
            }
            else
            {
                lblExtraProg.Content = "约束非法。";
            }
        }
        private void SolveCollate(object sender, DoWorkEventArgs e)
        {
            SolverParam param = e.Argument as SolverParam;

            backend.ClearUsedIndices();
            if (IsDoingOther)
            {
                SuperChar sc = problems[selectedCharIdx];
                if (param.Reuse)
                {
                    backend.ClearUsedIndices();
                }
                for (int nd = 0; nd < sc.descriptors.Count; ++nd)
                {
                    TagStroke desc = sc.descriptors[nd];
                    backend.ClearPuzzleData();
                    backend.MakePuzzleData(desc);
                    uint step = backend.Solve(MainLogic.Solver.BasicSearch, param);
                    sc.strokes.Add(backend.GetResult());
                    if (backend.SearchSuccess())
                    {
                        ShowResultOnScene(selectedCharIdx, nd);
                    }
                    Dispatcher.Invoke(new Action <int, int, uint>(PrintSteps), new object[] { selectedCharIdx, nd, step });
                }
            }
            else
            {
                for (int tsc = 0; tsc < 4; ++tsc)
                {
                    SuperChar sc = problems[tsc];
                    sc.strokes = new List <Stroke>();
                    for (int nd = 0; nd < sc.descriptors.Count; ++nd)
                    {
                        if (param.Reuse)
                        {
                            backend.ClearUsedIndices();
                        }
                        TagStroke desc = sc.descriptors[nd];
                        backend.ClearPuzzleData();
                        backend.MakePuzzleData(desc);
                        uint step = backend.Solve(MainLogic.Solver.BasicSearch, param);
                        sc.strokes.Add(backend.GetResult());
                        if (backend.SearchSuccess())
                        {
                            ShowResultOnScene(tsc, nd);
                        }
                        Dispatcher.Invoke(new Action <int, int, uint>(PrintSteps), new object[] { tsc, nd, step });
                    }
                }
            }
        }
Exemple #3
0
        public uint Solve(Solver solver, SolverParam param)
        {
            uint ns = 0;

            switch (solver)
            {
            case Solver.BasicSearch:
                ns = DoBasicSearch(param);
                break;

            case Solver.ExtraSearch:
                ns = DoExtraSearch(param);
                break;

            default:
                break;
            }
            return(ns);
        }
 private void BtnBeginSolve_Click(object sender, RoutedEventArgs e)
 {
     if (!IsCollating)
     {
         IsCollating      = true;
         tblStepInfo.Text = "";
         SolverParam param = new SolverParam()
         {
             MaxStep     = stepLimits[cbMaxSteps.SelectedIndex],
             NeedShuffle = (bool)tgShuffle.IsChecked,
             Reuse       = (bool)tgReuse.IsChecked
         };
         worker                     = new BackgroundWorker();
         worker.DoWork             += SolveCollate;
         worker.RunWorkerCompleted += WorkDone;
         worker.RunWorkerAsync(param);
         SetCollating();
         lblInfo.Content = "搜索中…";
     }
 }
        private void SearchExCollate(object sender, DoWorkEventArgs e)
        {
            SolverParam param = e.Argument as SolverParam;

            if (param.NeedShuffle)
            {
                backend.ClearUsedIndices();
            }
            backend.ClearPuzzleData();
            backend.MakePuzzleDataEx(extraDesc, extraConstraint);
            uint step = backend.Solve(MainLogic.Solver.ExtraSearch, param);

            Dispatcher.Invoke(
                new Action <int, int, uint>(PrintSteps),
                new object[] { StrokeTable[selectedStrokeIdx][0], StrokeTable[selectedStrokeIdx][1], step }
                );
            Stroke stroke  = backend.GetResult();
            bool   success = backend.SearchSuccess();

            Dispatcher.Invoke(new Action <bool, Stroke>(ShowExtraResult), new object[] { success, stroke });
        }
Exemple #6
0
        private uint DoExtraSearch(SolverParam param)
        {
            uint   walk   = 0;
            Random rnd    = new Random();
            Stroke stroke = puzzleData;

            int         nbVerses  = stroke.Verses.Count;
            Stack <int> proposal  = new Stack <int>(),
                        candidate = new Stack <int>(Enumerable.Reverse(Enumerable.Range(0, nbVerses)));
            List <Verse> result   = new List <Verse>();

            List <int>[] visited = new List <int> [nbVerses];
            for (int vv = 0; vv < nbVerses; ++vv)
            {
                visited[vv] = new List <int>();
            }
            while (candidate.Count > 0)
            {
                int        curIdx      = candidate.Pop();
                List <int> curVisisted = visited[curIdx];
                // Existing verses construct the constraints.
                List <int[]> constraints    = stroke.Anchors;
                int          requiredLength = stroke.Verses[curIdx].Length;
                bool         foundOne       = true;
                // Look up in the data.
                int   s = 0;
                Verse v = new Verse();
                if (stroke.Verses[curIdx].Content[0] != 0xFF)
                {
                    // Fixed verse.
                    s = dictDataMatrices[requiredLength].FindIndex(
                        (x) =>
                    {
                        bool found = true;
                        for (int i = 0; i < requiredLength; ++i)
                        {
                            if (x[i] != stroke.Verses[curIdx].Content[i])
                            {
                                found = false;
                                break;
                            }
                        }
                        return(found);
                    });
                }
                else
                {
                    // Variant verse.
                    for (s = 0; s < dictDataMatrices[requiredLength].Count; ++s)
                    {
                        if (param.MaxStep > 0 && walk > param.MaxStep)
                        {
                            return(walk);
                        }
                        // Prevent replicate verses.
                        foundOne = true;
                        if (usedIndices[requiredLength].Contains(s) || curVisisted.Contains(s))
                        {
                            foundOne = false;
                            continue;
                        }
                        ++walk;
                        ushort[] content = dictDataMatrices[requiredLength][s];
                        foreach (int[] a in constraints)
                        {
                            if (a[4] == 0xFF)
                            {
                                // Variant anchor.
                                if (proposal.Contains(a[0]) && curIdx == a[2])
                                {
                                    ushort trait = content[a[3]],
                                       check     = result[a[0]].Content[a[1]];
                                    if (trait != check)
                                    {
                                        foundOne = false;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                // Fixed anchor.
                                if (a[0] == curIdx && content[a[1]] != a[4])
                                {
                                    foundOne = false;
                                    break;
                                }
                                if (a[2] == curIdx && content[a[3]] != a[4])
                                {
                                    foundOne = false;
                                    break;
                                }
                            }
                            // For each search, check the constraints.
                        }
                        if (foundOne)
                        {
                            break;
                        }
                    }
                }
                if (foundOne)
                {
                    // Next step.
                    curVisisted.Add(s);
                    v.Length  = requiredLength;
                    v.Content = dictDataMatrices[requiredLength][s];
                    result.Add(v);
                    proposal.Push(curIdx);
                }
                else
                {
                    // Trace back.
                    curVisisted.Clear();
                    result.RemoveAt(result.Count - 1);
                    int lastIdx = proposal.Pop();
                    candidate.Push(curIdx);
                    candidate.Push(lastIdx);
                }
            }
            // Get result.
            stroke.Verses = result;
            for (int i = 0; i < nbVerses; ++i)
            {
                int requiredLength = stroke.Verses[i].Length;
                int usedIdx        = visited[i][visited[i].Count - 1];
                if (!param.Reuse)
                {
                    usedIndices[requiredLength].Add(usedIdx);
                }
            }
            stroke.IsCompleted = true;
            return(walk);
        }