void solver_OnSolutionStepCompleted(object sender, SolutionStepCompletedEventArgs e) { if (!e.Finished) { PictureBox currentStepImg = stepImgs[currentIndex]; Label currentStep = stepLabels[currentIndex]; if (currentStepImg.InvokeRequired) currentStepImg.Invoke((MethodInvoker)delegate() { currentStepImg.Image = Properties.Resources.ok; }); if (currentStep.InvokeRequired) currentStep.Invoke((MethodInvoker)delegate() { currentStep.Text = e.Type == SolutionStepType.Standard ? string.Format("{0} moves", e.Algorithm.Moves.Count) : string.Empty; }); currentIndex++; if (currentIndex < stepImgs.Count) { currentStepImg = stepImgs[currentIndex]; currentStep = stepLabels[currentIndex]; if (currentStepImg.InvokeRequired) currentStepImg.Invoke((MethodInvoker)delegate() { currentStepImg.Image = Properties.Resources.refresh; }); if (currentStep.InvokeRequired) currentStep.Invoke((MethodInvoker)delegate() { currentStep.Text = "In progress ..."; }); } } else { if (lblTimeHeader.InvokeRequired) lblTimeHeader.Invoke((MethodInvoker)delegate() { lblTime.Text = string.Format("{0:f2}s", e.Milliseconds / 1000.0); }); if (lblMovesHeader.InvokeRequired) lblMovesHeader.Invoke((MethodInvoker)delegate() { lblMoves.Text = string.Format("{0} moves", e.Algorithm.Moves.Count); }); if (lblHeader.InvokeRequired) lblHeader.Invoke((MethodInvoker)delegate() { lblHeader.Text = "Solution found."; }); if (btnAdd.InvokeRequired) btnAdd.Invoke((MethodInvoker)delegate() { btnAdd.Enabled = true; }); solver.OnSolutionStepCompleted -= solver_OnSolutionStepCompleted; this.Algorithm = e.Algorithm; } }
/// <summary> /// Transforms the algorithm /// </summary> /// <param name="rotationLayer">Transformation layer</param> /// <returns>Transformed algorithm</returns> public Algorithm Transform(CubeFlag rotationLayer) { var newAlgorithm = new Algorithm(); for (var i = 0; i < this.Moves.Count; i++) { newAlgorithm.Moves.Add(this.Moves[i].Transform(rotationLayer)); } return newAlgorithm; }
/// <summary> /// Transforms the algorithm /// </summary> /// <param name="rotationLayer">Transformation layer</param> /// <returns>Transformed algorithm</returns> public Algorithm Transform(CubeFlag rotationLayer) { Algorithm newAlgorithm = new Algorithm(); for (int i = 0; i < Moves.Count; i++) { newAlgorithm.Moves.Add(Moves[i].Transform(rotationLayer)); } return newAlgorithm; }
protected override void Solve(Rubik cube) { Rubik = cube.DeepClone(); _coordCube = ToCoordCube(cube); this.MaxDepth = 30; this.TimeOut = 10000; Algorithm = new Algorithm(); InitStandardCube(); GetSolution(); RemoveUnnecessaryMoves(); }
private void SolveCrossTopLayer() { // Step 1: Get edges with the color of the top face IEnumerable<Cube> topEdges = Rubik.Cubes.Where(c => c.IsEdge).Where(c => c.Position.HasFlag(CubeFlag.TopLayer)); // Step 2: Check if the cube is insoluble if (topEdges.Where(tE => tE.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor).Count() % 2 != 0) return; IEnumerable<Cube> correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor); Algorithm solveTopCrossAlgorithmI = new Algorithm("F R U R' U' F'"); Algorithm solveTopCrossAlgorithmII = new Algorithm("F S R U R' U' F' S'"); // Step 3: Solve the cross on the top layer if (Rubik.CountEdgesWithCorrectOrientation() == 0) { SolverAlgorithm(solveTopCrossAlgorithmI); correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor); } if (Rubik.CountEdgesWithCorrectOrientation() == 2) { Cube firstCorrect = correctEdges.First(); Cube secondCorrect = correctEdges.First(f => f != firstCorrect); bool opposite = false; foreach (CubeFlag flag in firstCorrect.Position.GetFlags()) { CubeFlag pos = CubeFlagService.GetOppositeFlag(flag); if (secondCorrect.Position.HasFlag(pos) && pos != CubeFlag.None) { opposite = true; break; } } if (opposite) { while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice)) != 1) SolverMove(CubeFlag.TopLayer, true); SolverAlgorithm(solveTopCrossAlgorithmI); } else { while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice) || c.Position.HasFlag(CubeFlag.FrontSlice)) != 2) SolverMove(CubeFlag.TopLayer, true); SolverAlgorithm(solveTopCrossAlgorithmII); } } // Step 4: Move the edges of the cross to their target positions while (topEdges.Where(c => c.Position.Flags == GetTargetFlags(c)).Count() < 4) { IEnumerable<Cube> CorrectEdges = topEdges.Where(c => c.Position.Flags == GetTargetFlags(c)); while (CorrectEdges.Count() < 2) SolverMove(CubeFlag.TopLayer, true); CubeFlag rightSlice = CubeFlagService.FromFacePosition(CorrectEdges.First().Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position); SolverMove(CubeFlag.TopLayer, false); if (CorrectEdges.Count(c => c.Position.HasFlag(rightSlice)) == 0) SolverMove(CubeFlag.TopLayer, true); else { SolverMove(CubeFlag.TopLayer, true); rightSlice = CubeFlagService.FromFacePosition(CorrectEdges.First(cE => !cE.Position.HasFlag(rightSlice)).Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position); } // Algorithm: R U Ri U R U U Ri SolverAlgorithm("{0} U {0}' U {0} U U {0}'", CubeFlagService.ToNotationString(rightSlice)); while (CorrectEdges.Count() < 2) SolverMove(CubeFlag.TopLayer, true); } }
private void SolveCrossTopLayer() { // Step 1: Get edges with the color of the top face var topEdges = this.Rubik.Cubes.Where(c => c.IsEdge).Where(c => c.Position.HasFlag(CubeFlag.TopLayer)); // Step 2: Check if the cube is insoluble if (topEdges.Count(tE => tE.Faces.First(f => f.Position == FacePosition.Top).Color == this.Rubik.TopColor) % 2 != 0) return; var correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == this.Rubik.TopColor); var solveTopCrossAlgorithmI = new Algorithm("F R U R' U' F'"); var solveTopCrossAlgorithmII = new Algorithm("F S R U R' U' F' S'"); // Step 3: Solve the cross on the top layer if (this.Rubik.CountEdgesWithCorrectOrientation() == 0) { this.SolverAlgorithm(solveTopCrossAlgorithmI); correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == this.Rubik.TopColor); } if (this.Rubik.CountEdgesWithCorrectOrientation() == 2) { var firstCorrect = correctEdges.First(); var secondCorrect = correctEdges.First(f => f != firstCorrect); var opposite = (from CubeFlag flag in firstCorrect.Position.GetFlags() select CubeFlagService.GetOppositeFlag(flag)).Any(pos => secondCorrect.Position.HasFlag(pos) && pos != CubeFlag.None); if (opposite) { while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice)) != 1) this.SolverMove(CubeFlag.TopLayer, true); this.SolverAlgorithm(solveTopCrossAlgorithmI); } else { while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice) || c.Position.HasFlag(CubeFlag.FrontSlice)) != 2) this.SolverMove(CubeFlag.TopLayer, true); this.SolverAlgorithm(solveTopCrossAlgorithmII); } } // Step 4: Move the edges of the cross to their target positions while (topEdges.Count(c => c.Position.Flags == this.GetTargetFlags(c)) < 4) { var CorrectEdges = topEdges.Where(c => c.Position.Flags == this.GetTargetFlags(c)); while (CorrectEdges.Count() < 2) this.SolverMove(CubeFlag.TopLayer, true); var rightSlice = CubeFlagService.FromFacePosition(CorrectEdges.First().Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position); this.SolverMove(CubeFlag.TopLayer, false); if (CorrectEdges.Count(c => c.Position.HasFlag(rightSlice)) == 0) this.SolverMove(CubeFlag.TopLayer, true); else { this.SolverMove(CubeFlag.TopLayer, true); rightSlice = CubeFlagService.FromFacePosition(CorrectEdges.First(cE => !cE.Position.HasFlag(rightSlice)).Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position); } // Algorithm: R U Ri U R U U Ri this.SolverAlgorithm("{0} U {0}' U {0} U U {0}'", CubeFlagService.ToNotationString(rightSlice)); while (CorrectEdges.Count() < 2) this.SolverMove(CubeFlag.TopLayer, true); } }
private void solver_OnSolutionStepCompleted(object sender, SolutionStepCompletedEventArgs e) { if (!e.Finished) { var currentStepImg = this.stepImgs[this.currentIndex]; var currentStep = this.stepLabels[this.currentIndex]; if (currentStepImg.InvokeRequired) { var img = currentStepImg; currentStepImg.Invoke((MethodInvoker)delegate { img.Image = Properties.Resources.ok; }); } if (currentStep.InvokeRequired) { var step = currentStep; currentStep.Invoke((MethodInvoker)delegate { step.Text = e.Type == SolutionStepType.Standard ? $"{e.Algorithm.Moves.Count} moves" : string.Empty; }); } this.currentIndex++; if (this.currentIndex >= this.stepImgs.Count) { return; } currentStepImg = this.stepImgs[this.currentIndex]; currentStep = this.stepLabels[this.currentIndex]; if (currentStepImg.InvokeRequired) currentStepImg.Invoke((MethodInvoker)delegate { currentStepImg.Image = Properties.Resources.refresh; }); if (currentStep.InvokeRequired) currentStep.Invoke((MethodInvoker)delegate { currentStep.Text = "In progress ..."; }); } else { if (this.lblTimeHeader.InvokeRequired) this.lblTimeHeader.Invoke((MethodInvoker)delegate { lblTime.Text = $"{e.Milliseconds / 1000.0:f2}s"; }); if (this.lblMovesHeader.InvokeRequired) this.lblMovesHeader.Invoke((MethodInvoker)delegate { lblMoves.Text = $"{e.Algorithm.Moves.Count} moves"; }); if (this.lblHeader.InvokeRequired) this.lblHeader.Invoke((MethodInvoker)delegate { lblHeader.Text = "Solution found."; }); if (this.btnAdd.InvokeRequired) this.btnAdd.Invoke((MethodInvoker)delegate { btnAdd.Enabled = true; }); this.solver.OnSolutionStepCompleted -= this.solver_OnSolutionStepCompleted; this.Algorithm = e.Algorithm; } }