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 }); } } } }
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 }); }
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); }