private CoordCube ToCoordCube(Rubik rubik) { // get corner perm and orientation string[] corners = new string[N_CORNER] { "UFR", "UFL", "UBL", "URB", "DFR", "DFL", "DBL", "DRB" }; byte[] cornerPermutation = new byte[N_CORNER]; byte[] cornerOrientation = new byte[N_CORNER]; for (int i = 0; i < N_CORNER; i++) { CubeFlag pos = CubeFlagService.Parse(corners[i]); Cube matchingCube = rubik.Cubes.First(c => c.Position.Flags == pos); CubeFlag targetPos = rubik.GetTargetFlags(matchingCube); cornerOrientation[i] = (byte)Solvability.GetOrientation(rubik, matchingCube); for (int j = 0; j < N_CORNER; j++) { if (corners[j] == CubeFlagService.ToNotationString(targetPos)) { cornerPermutation[i] = (byte)(j + 1); } } } // get edge perm and orientation string[] edges = new string[N_EDGE] { "UR", "UF", "UL", "UB", "DR", "DF", "DL", "DB", "FR", "FL", "BL", "RB" }; byte[] edgePermutation = new byte[N_EDGE]; byte[] edgeOrientation = new byte[N_EDGE]; for (int i = 0; i < N_EDGE; i++) { CubeFlag pos = CubeFlagService.Parse(edges[i]); Cube matchingCube = rubik.Cubes.Where(c => c.IsEdge).First(c => c.Position.Flags.HasFlag(pos)); CubeFlag targetPos = rubik.GetTargetFlags(matchingCube); edgeOrientation[i] = (byte)Solvability.GetOrientation(rubik, matchingCube); for (int j = 0; j < N_EDGE; j++) { if (CubeFlagService.ToNotationString(targetPos).Contains(edges[j])) { edgePermutation[i] = (byte)(j + 1); } } } byte[] cornerInv = CoordCube.ToInversions(cornerPermutation); byte[] edgeInv = CoordCube.ToInversions(edgePermutation); return(new CoordCube(cornerPermutation, edgePermutation, cornerOrientation, edgeOrientation)); }
public DialogParityCheckResult(Rubik rubik, Form parent = null) { InitializeComponent(); this.ShowInTaskbar = false; if (parent != null) { this.Owner = parent; this.StartPosition = FormStartPosition.CenterParent; } // Color test bool colors = Solvability.CorrectColors(rubik); lblColorTest.Text = colors ? "Passed" : "Failed"; pbColorTest.Image = colors ? Properties.Resources.ok : Properties.Resources.cross_icon; if (!colors) { lblPermutationTest.Text = "Not tested"; lblCornerTest.Text = "Not tested"; lblEdgeTest.Text = "Not tested"; pbCornerTest.Image = Properties.Resources.questionmark; pbEdgeTest.Image = Properties.Resources.questionmark; pbPermutationTest.Image = Properties.Resources.questionmark; lblHeader.Text = "This cube is unsolvable."; } else { // Permutation parity test bool permutation = Solvability.PermutationParityTest(rubik); lblPermutationTest.Text = permutation ? "Passed" : "Failed"; pbPermutationTest.Image = permutation ? Properties.Resources.ok : Properties.Resources.cross_icon; // Corner parity test bool corner = Solvability.CornerParityTest(rubik); lblCornerTest.Text = corner ? "Passed" : "Failed"; pbCornerTest.Image = corner ? Properties.Resources.ok : Properties.Resources.cross_icon; // Edge parity test bool edge = Solvability.EdgeParityTest(rubik); lblEdgeTest.Text = edge ? "Passed" : "Failed"; pbEdgeTest.Image = edge ? Properties.Resources.ok : Properties.Resources.cross_icon; lblHeader.Text = permutation && corner && edge && colors ? "This cube is solvable." : "This cube is unsolvable."; } }
void ValidateBoard() { Solvability solvability = logic.CheckSolvability(dots); if (solvability == Solvability.UNSOLVABLE) { InitBoard(); } else { while (solvability == Solvability.NO_MOVES) { ShuffleBoard(); solvability = logic.CheckSolvability(dots); } } }
private void SolveAsync(Rubik rubik) { bool solvable = Solvability.FullTest(rubik); if (solvable) { Stopwatch sw = new Stopwatch(); sw.Start(); Solve(rubik); sw.Stop(); Algorithm = Algorithm.RemoveUnnecessaryMoves(Algorithm); var args = new SolutionStepCompletedEventArgs(Name, true, Algorithm, (int)sw.ElapsedMilliseconds); OnSolutionStepCompleted?.Invoke(this, args); solvingThread.Abort(); } else { this.BroadcastOnSolutionError(this.Name, "Unsolvable cube"); } }
private void SolveFirstCross() { // Step 1: Get the edges with target position on the bottom layer IEnumerable <Cube> bottomEdges = Rubik.Cubes.Where(c => c.IsEdge && GetTargetFlags(c).HasFlag(CubeFlag.BottomLayer)); // Step 2: Rotate a correct orientated edge of the bottom layer to target position IEnumerable <Cube> solvedBottomEdges = bottomEdges.Where(bE => bE.Position.Flags == GetTargetFlags(bE) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom); if (bottomEdges.Count(bE => bE.Position.HasFlag(CubeFlag.BottomLayer) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom) > 0) { while (solvedBottomEdges.Count() < 1) { SolverMove(CubeFlag.BottomLayer, true); solvedBottomEdges = bottomEdges.Where(bE => bE.Position.Flags == GetTargetFlags(bE) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom); } } // Step 3: Solve incorrect edges of the bottom layer while (solvedBottomEdges.Count() < 4) { IEnumerable <Cube> unsolvedBottomEdges = bottomEdges.Except(solvedBottomEdges); Cube e = (unsolvedBottomEdges.FirstOrDefault(c => c.Position.HasFlag(CubeFlag.TopLayer)) != null) ? unsolvedBottomEdges.FirstOrDefault(c => c.Position.HasFlag(CubeFlag.TopLayer)) : unsolvedBottomEdges.First(); Color secondColor = e.Colors.First(co => co != Rubik.BottomColor && co != Color.Black); if (e.Position.Flags != GetTargetFlags(e)) { // Rotate to top layer CubeFlag layer = CubeFlagService.FromFacePosition(e.Faces.First(f => (f.Color == Rubik.BottomColor || f.Color == secondColor) && f.Position != FacePosition.Top && f.Position != FacePosition.Bottom).Position); CubeFlag targetLayer = CubeFlagService.FromFacePosition(StandardCube.Cubes.First(cu => CollectionMethods.ScrambledEquals(cu.Colors, e.Colors)) .Faces.First(f => f.Color == secondColor).Position); if (e.Position.HasFlag(CubeFlag.MiddleLayer)) { if (layer == targetLayer) { while (!e.Position.HasFlag(CubeFlag.BottomLayer)) { SolverMove(layer, true); } } else { SolverMove(layer, true); if (e.Position.HasFlag(CubeFlag.TopLayer)) { SolverMove(CubeFlag.TopLayer, true); SolverMove(layer, false); } else { for (int i = 0; i < 2; i++) { SolverMove(layer, true); } SolverMove(CubeFlag.TopLayer, true); SolverMove(layer, true); } } } if (e.Position.HasFlag(CubeFlag.BottomLayer)) { for (int i = 0; i < 2; i++) { SolverMove(layer, true); } } // Rotate over target position while (!e.Position.HasFlag(targetLayer)) { SolverMove(CubeFlag.TopLayer, true); } //Rotate to target position for (int i = 0; i < 2; i++) { SolverMove(targetLayer, true); } CubeFlag targetPos = GetTargetFlags(e); } // Flip the incorrect orientated edges with the algorithm: Fi D Ri Di if (Solvability.GetOrientation(Rubik, e) != 0) { CubeFlag frontSlice = CubeFlagService.FromFacePosition(e.Faces.First(f => f.Color == Rubik.BottomColor).Position); SolverMove(frontSlice, false); SolverMove(CubeFlag.BottomLayer, true); CubeFlag rightSlice = CubeFlagService.FromFacePosition(e.Faces.First(f => f.Color == secondColor).Position); SolverMove(rightSlice, false); SolverMove(CubeFlag.BottomLayer, false); } List <Face> faces = e.Faces.ToList(); solvedBottomEdges = bottomEdges.Where(bE => bE.Position.Flags == GetTargetFlags(bE) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom); } }
private void CompleteF2L() { List <Tuple <Cube, Cube> > unsolvedPairs = GetPairs(this.Rubik).ToList(); while (unsolvedPairs.Count > 0) // 4 pairs { Tuple <Cube, Cube> currentPair = unsolvedPairs.First(); Cube edge = currentPair.Item1; Cube corner = currentPair.Item2; CubePosition target = new CubePosition(Rubik.GetTargetFlags(corner)); if (!corner.Position.HasFlag(CubeFlag.TopLayer) && Rubik.GetTargetFlags(corner) != corner.Position.Flags) { CubeFlag rotationLayer = CubeFlagService.FirstNotInvalidFlag(corner.Position.Flags, CubeFlag.BottomLayer); bool direction = new TestScenario(Rubik, new LayerMove(rotationLayer)).TestCubePosition(corner, CubeFlag.TopLayer); SolverMove(rotationLayer, direction); SolverMove(CubeFlag.TopLayer, true); SolverMove(rotationLayer, !direction); } // move edge to top position if necessary if (!edge.Position.HasFlag(CubeFlag.TopLayer) && Rubik.GetTargetFlags(edge) != edge.Position.Flags) { CubeFlag rotationLayer = CubeFlagService.FirstNotInvalidFlag(edge.Position.Flags, CubeFlag.MiddleLayer); bool direction = new TestScenario(Rubik, new LayerMove(rotationLayer)).TestCubePosition(edge, CubeFlag.TopLayer); SolverMove(rotationLayer, direction); while ((corner.Position.HasFlag(rotationLayer) && !corner.Position.HasFlag(CubeFlag.BottomLayer)) || edge.Position.HasFlag(rotationLayer)) { SolverMove(CubeFlag.TopLayer, true); } SolverMove(rotationLayer, !direction); } // detect right and front slice CubeFlag rightSlice = CubeFlagService.ToInt(target.X) == CubeFlagService.ToInt(target.Z) ? target.Z : target.X; CubeFlag frontSlice = CubeFlagService.FirstNotInvalidFlag(target.Flags, CubeFlag.YFlags | rightSlice); while (!corner.Position.HasFlag(target.Flags & ~CubeFlag.BottomLayer)) { SolverMove(CubeFlag.TopLayer, true); } PatternFilter filter = new PatternFilter(new Func <Pattern, Pattern, bool>(delegate(Pattern p1, Pattern p2) { PatternItem item = new PatternItem(corner.Position, Solvability.GetOrientation(this.Rubik, corner), target.Flags); return(p2.Items.Any(i => i.Equals(item))); }), true); Algorithm algo = null; for (int i = 0; i < 4; i++) { F2LPattern pattern = new F2LPattern(Rubik.GetTargetFlags(edge), Rubik.GetTargetFlags(corner), rightSlice, frontSlice); algo = pattern.FindBestMatch(Pattern.FromRubik(Rubik), CubeFlag.None, filter); if (algo != null) { SolverAlgorithm(algo); break; } SolverMove(CubeFlag.TopLayer, true); } int count = unsolvedPairs.Count; unsolvedPairs = GetPairs(this.Rubik).ToList(); if (unsolvedPairs.Count == count) { this.BroadcastOnSolutionError("Complete first two layers", "Wrong algorithm"); return; } } }
private void SolveFirstCross() { // Step 1: Get the edges with target position on the bottom layer IEnumerable <Cube> bottomEdges = Rubik.Cubes.Where(c => c.IsEdge // target position on bottom layer && GetTargetFlags(c).HasFlag(CubeFlag.BottomLayer) ); // Step 2: Rotate a correct orientated edge of the bottom layer to target position IEnumerable <Cube> bottomEdgesInBottomLayerCorrectlyOriented = bottomEdges.Where(bottomEdge => // is in bottom layer bottomEdge.Position.Flags == GetTargetFlags(bottomEdge) // is oriented correctly && bottomEdge.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ); var anyEdgesAreSolvableWithDMoves = bottomEdges.Count(bE => bE.Position.HasFlag(CubeFlag.BottomLayer) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ) > 0; if (anyEdgesAreSolvableWithDMoves) { while (!bottomEdgesInBottomLayerCorrectlyOriented.Any()) { // turn the bottom layer until at least one is SolverMove(CubeFlag.BottomLayer, true); bottomEdgesInBottomLayerCorrectlyOriented = bottomEdges.Where(bE => bE.Position.Flags == GetTargetFlags(bE) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ); } } // Step 3: Solve incorrect edges of the bottom layer while (bottomEdgesInBottomLayerCorrectlyOriented.Count() < 4) { IEnumerable <Cube> unsolvedBottomEdges = bottomEdges.Except(bottomEdgesInBottomLayerCorrectlyOriented); Cube e = unsolvedBottomEdges.FirstOrDefault(c => c.Position.HasFlag(CubeFlag.TopLayer)) ?? unsolvedBottomEdges.First(); Color secondColor = e.Colors.First(co => co != Rubik.BottomColor && co != Color.Black ); if (e.Position.Flags != GetTargetFlags(e)) { // Rotate to top layer CubeFlag layer = CubeFlagService.FromFacePosition( e.Faces.First(f => (f.Color == Rubik.BottomColor || f.Color == secondColor) && f.Position != FacePosition.Top && f.Position != FacePosition.Bottom ).Position ); CubeFlag targetLayer = CubeFlagService.FromFacePosition( StandardCube.Cubes.First(cu => CollectionMethods.ScrambledEquals(cu.Colors, e.Colors) ) .Faces .First(f => f.Color == secondColor) .Position ); if (e.Position.HasFlag(CubeFlag.MiddleLayer)) { if (layer == targetLayer) { while (!e.Position.HasFlag(CubeFlag.BottomLayer)) { SolverMove(layer, true); } } else { SolverMove(layer, true); if (e.Position.HasFlag(CubeFlag.TopLayer)) { SolverMove(CubeFlag.TopLayer, true); SolverMove(layer, false); } else { for (int i = 0; i < 2; i++) { SolverMove(layer, true); } SolverMove(CubeFlag.TopLayer, true); SolverMove(layer, true); } } } if (e.Position.HasFlag(CubeFlag.BottomLayer)) { for (int i = 0; i < 2; i++) { SolverMove(layer, true); } } // Rotate over target position while (!e.Position.HasFlag(targetLayer)) { SolverMove(CubeFlag.TopLayer, true); } //Rotate to target position for (int i = 0; i < 2; i++) { SolverMove(targetLayer, true); } } // Flip the incorrect orientated edges with the algorithm: F' D R' D' if (Solvability.GetOrientation(Rubik, e) != 0) { CubeFlag frontSlice = CubeFlagService.FromFacePosition(e.Faces.First(f => f.Color == Rubik.BottomColor).Position); SolverMove(frontSlice, false); SolverMove(CubeFlag.BottomLayer, true); CubeFlag rightSlice = CubeFlagService.FromFacePosition(e.Faces.First(f => f.Color == secondColor).Position); SolverMove(rightSlice, false); SolverMove(CubeFlag.BottomLayer, false); } bottomEdgesInBottomLayerCorrectlyOriented = bottomEdges.Where(bE => bE.Position.Flags == GetTargetFlags(bE) && bE.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ); } }
public bool IsCorrect(Cube cube) { return(cube.Position.Flags == GetTargetFlags(cube) && Solvability.GetOrientation(this, cube) == 0); }
// **** METHODS **** public static Rubik FromPattern(Pattern pattern) { Rubik rubik = new Rubik(); foreach (PatternItem item in pattern.Items) { if (CubePosition.IsCorner(item.CurrentPosition.Flags)) { bool xyzCorrect = !((item.CurrentPosition.Y == CubeFlag.TopLayer ^ (item.CurrentPosition.X == CubeFlag.RightSlice ^ item.CurrentPosition.Z == CubeFlag.FrontSlice)) ^ (CubeFlagService.FirstYFlag(item.TargetPosition) == CubeFlag.TopLayer ^ (CubeFlagService.FirstXFlag(item.TargetPosition) == CubeFlag.RightSlice ^ CubeFlagService.FirstZFlag(item.TargetPosition) == CubeFlag.FrontSlice))); if (item.CurrentOrientation == Orientation.Correct) { rubik.SetFaceColor(item.CurrentPosition.Flags, CubeFlagService.ToFacePosition(item.CurrentPosition.Y), rubik.GetSliceColor(CubeFlagService.FirstYFlag(item.TargetPosition))); FacePosition x = xyzCorrect ? CubeFlagService.ToFacePosition(item.CurrentPosition.X) : CubeFlagService.ToFacePosition(item.CurrentPosition.Z); FacePosition z = xyzCorrect ? CubeFlagService.ToFacePosition(item.CurrentPosition.Z) : CubeFlagService.ToFacePosition(item.CurrentPosition.X); rubik.SetFaceColor(item.CurrentPosition.Flags, x, rubik.GetSliceColor(CubeFlagService.FirstXFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, z, rubik.GetSliceColor(CubeFlagService.FirstZFlag(item.TargetPosition))); } else { bool corr = (item.CurrentPosition.X == CubeFlag.RightSlice ^ item.CurrentPosition.Z == CubeFlag.BackSlice) ^ item.CurrentPosition.Y == CubeFlag.BottomLayer; FacePosition x = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.X) : CubeFlagService.ToFacePosition(item.CurrentPosition.Y); FacePosition y = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.Z) : CubeFlagService.ToFacePosition(item.CurrentPosition.X); FacePosition z = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.Y) : CubeFlagService.ToFacePosition(item.CurrentPosition.Z); rubik.SetFaceColor(item.CurrentPosition.Flags, x, rubik.GetSliceColor(CubeFlagService.FirstXFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, y, rubik.GetSliceColor(CubeFlagService.FirstYFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, z, rubik.GetSliceColor(CubeFlagService.FirstZFlag(item.TargetPosition))); } } if (CubePosition.IsEdge(item.CurrentPosition.Flags)) { CubeFlag flagOne = CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); FacePosition faceOne = CubeFlagService.ToFacePosition(flagOne); FacePosition faceTwo = CubeFlagService.ToFacePosition(CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | flagOne)); CubeFlag tFlagOne = CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); rubik.SetFaceColor(item.CurrentPosition.Flags, faceOne, rubik.GetSliceColor(tFlagOne)); rubik.SetFaceColor(item.CurrentPosition.Flags, faceTwo, rubik.GetSliceColor(CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | tFlagOne))); if (Solvability.GetOrientation(rubik, rubik.Cubes.First(c => c.Position.Flags == item.CurrentPosition.Flags)) != item.CurrentOrientation) { rubik.SetFaceColor(item.CurrentPosition.Flags, faceTwo, rubik.GetSliceColor(tFlagOne)); rubik.SetFaceColor(item.CurrentPosition.Flags, faceOne, rubik.GetSliceColor(CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | tFlagOne))); } } if (CubePosition.IsCenter(item.CurrentPosition.Flags)) { CubeFlag flag = CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); CubeFlag tFlag = CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); rubik.SetFaceColor(item.CurrentPosition.Flags, CubeFlagService.ToFacePosition(flag), rubik.GetSliceColor(tFlag)); } } return(rubik); }