/// <summary> /// Transforms the pattern item /// </summary> /// <param name="type">Transformation axis</param> public void Transform(CubeFlag rotationLayer) { if (CurrentPosition.HasFlag(rotationLayer)) { CubeFlag oldFlags = this.CurrentPosition.Flags; CurrentPosition.NextFlag(rotationLayer, true); Orientation newOrientation = this.CurrentOrientation; if (CubePosition.IsCorner(CurrentPosition.Flags) && !CubeFlagService.IsYFlag(rotationLayer)) { if (new CubePosition(oldFlags).Y == new CubePosition(CurrentPosition.Flags).Y) { newOrientation = (Orientation)(((int)newOrientation + 2) % 3); } else { newOrientation = (Orientation)(((int)newOrientation + 1) % 3); } } else if (CubePosition.IsEdge(CurrentPosition.Flags) && CubeFlagService.IsZFlag(rotationLayer)) { newOrientation = (Orientation)((int)newOrientation ^ 0x1); } this.CurrentOrientation = newOrientation; } if (TargetPosition.HasFlag(rotationLayer)) { TargetPosition = CubeFlagService.NextFlags(TargetPosition, rotationLayer, true); } }
/// <summary> /// Change the position of the cube by rotating it on the given layer and the given direction /// </summary> /// <param name="layer">Defines the layer the cube is to rotate on</param> /// <param name="direction">Defines the direction of the rotation (true == clockwise)</param> public void NextPos(CubeFlag layer, bool direction) { Cube oldCube = DeepClone(); Position.NextFlag(layer, direction); #region Colors if (this.IsCorner) { //Set colors Face layerFace = this.Faces.First(f => f.Position == CubeFlagService.ToFacePosition(layer)); Color layerColor = layerFace.Color; CubeFlag newFlag = CubeFlagService.FirstNotInvalidFlag(this.Position.Flags, oldCube.Position.Flags); CubeFlag commonFlag = CubeFlagService.FirstNotInvalidFlag(this.Position.Flags, newFlag | layer); CubeFlag oldFlag = CubeFlagService.FirstNotInvalidFlag(oldCube.Position.Flags, commonFlag | layer); Color colorNewPos = Faces.First(f => f.Position == CubeFlagService.ToFacePosition(commonFlag)).Color; Color colorCommonPos = Faces.First(f => f.Position == CubeFlagService.ToFacePosition(oldFlag)).Color; ResetColors(); SetFaceColor(layerFace.Position, layerColor); SetFaceColor(CubeFlagService.ToFacePosition(newFlag), colorNewPos); SetFaceColor(CubeFlagService.ToFacePosition(commonFlag), colorCommonPos); } if (this.IsCenter) { CubeFlag oldFlag = CubeFlagService.FirstNotInvalidFlag(oldCube.Position.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); Color centerColor = this.Faces.First(f => f.Position == CubeFlagService.ToFacePosition(oldFlag)).Color; CubeFlag newPos = CubeFlagService.FirstNotInvalidFlag(this.Position.Flags, CubeFlag.MiddleSliceSides | CubeFlag.MiddleSlice | CubeFlag.MiddleLayer); ResetColors(); SetFaceColor(CubeFlagService.ToFacePosition(newPos), centerColor); } if (this.IsEdge) { CubeFlag newFlag = CubeFlagService.FirstNotInvalidFlag(this.Position.Flags, oldCube.Position.Flags | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | CubeFlag.MiddleLayer); CubeFlag commonFlag = CubeFlagService.FirstNotInvalidFlag(this.Position.Flags, newFlag | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | CubeFlag.MiddleLayer); CubeFlag oldFlag = CubeFlagService.FirstNotInvalidFlag(oldCube.Position.Flags, commonFlag | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | CubeFlag.MiddleLayer); Color colorNewPos = this.Faces.First(f => f.Position == CubeFlagService.ToFacePosition(commonFlag)).Color; Color colorCommonPos = this.Faces.First(f => f.Position == CubeFlagService.ToFacePosition(oldFlag)).Color; ResetColors(); if (layer == CubeFlag.MiddleLayer || layer == CubeFlag.MiddleSlice || layer == CubeFlag.MiddleSliceSides) { SetFaceColor(CubeFlagService.ToFacePosition(newFlag), colorNewPos); SetFaceColor(CubeFlagService.ToFacePosition(commonFlag), colorCommonPos); } else { SetFaceColor(CubeFlagService.ToFacePosition(commonFlag), colorNewPos); SetFaceColor(CubeFlagService.ToFacePosition(newFlag), colorCommonPos); } } #endregion }
private void CompleteLastLayer() { // Step 1: Get edges with the color of the top face IEnumerable <Cube> topCorners = Rubik.Cubes.Where(c => c.IsCorner).Where(c => c.Position.HasFlag(CubeFlag.TopLayer)); // Step 2: Bring corners to their target position while (topCorners.Where(c => c.Position.Flags == GetTargetFlags(c)).Count() < 4) { IEnumerable <Cube> correctCorners = topCorners.Where(c => c.Position.Flags == GetTargetFlags(c)); CubeFlag rightSlice; if (correctCorners.Count() != 0) { Cube firstCube = correctCorners.First(); Face rightFace = firstCube.Faces.First(f => f.Color != Color.Black && f.Position != FacePosition.Top); rightSlice = CubeFlagService.FromFacePosition(rightFace.Position); if (!new TestScenario(Rubik, new LayerMove(rightSlice, true)).TestCubePosition(firstCube, CubeFlag.TopLayer)) { rightSlice = CubeFlagService.FromFacePosition(firstCube.Faces.First(f => f.Color != rightFace.Color && f.Color != Color.Black && f.Position != FacePosition.Top).Position); } } else { rightSlice = CubeFlag.RightSlice; } SolverAlgorithm("U {0} U' {1}' U {0}' U' {1}", CubeFlagService.ToNotationString(rightSlice), CubeFlagService.ToNotationString(CubeFlagService.GetOppositeFlag(rightSlice))); } // Step 3: Orientation of the corners on the top layer Face rightFac = topCorners.First().Faces.First(f => f.Color != Color.Black && f.Position != FacePosition.Top); CubeFlag rightSlic = !new TestScenario(Rubik, new LayerMove(CubeFlagService.FromFacePosition(rightFac.Position), true)).TestCubePosition(topCorners.First(), CubeFlag.TopLayer) ? CubeFlagService.FromFacePosition(rightFac.Position) : CubeFlagService.FromFacePosition(topCorners.First().Faces.First(f => f.Color != rightFac.Color && f.Color != Color.Black && f.Position != FacePosition.Top).Position);; foreach (Cube c in topCorners) { while (!c.Position.HasFlag(rightSlic)) { SolverMove(CubeFlag.TopLayer, true); } if (!new TestScenario(Rubik, new LayerMove(rightSlic, true)).TestCubePosition(c, CubeFlag.TopLayer)) { SolverMove(CubeFlag.TopLayer, true); } // Algorithm: Ri Di R D while (c.Faces.First(f => f.Position == FacePosition.Top).Color != Rubik.TopColor) { SolverAlgorithm("{0}' D' {0} D", CubeFlagService.ToNotationString(rightSlic)); } } while (topCorners.Count(tC => tC.Position.Flags == GetTargetFlags(tC)) != 4) { SolverMove(CubeFlag.TopLayer, true); } }
/// <summary> /// Generates 3D cubes from the Rubik cubes /// </summary> /// <returns>Cubes from the Rubik converted to 3D cubes</returns> private List <Cube3D> GenCubes3D() { List <Cube> cubes = this.Rubik.Cubes; List <Cube3D> cubes3D = new List <Cube3D>(); double d = 2.0 / 3.0; foreach (Cube c in cubes) { Cube3D cr = new Cube3D(new Point3D(d * CubeFlagService.ToInt(c.Position.X), d * CubeFlagService.ToInt(c.Position.Y), d * CubeFlagService.ToInt(c.Position.Z)), d / 2, c.Position.Flags, c.Faces); if (cr.Position.HasFlag(CubeFlag.TopLayer)) { cr = cr.Rotate(RotationType.Y, LayerRotation[CubeFlag.TopLayer], new Point3D(0, d, 0)); } if (cr.Position.HasFlag(CubeFlag.MiddleLayer)) { cr = cr.Rotate(RotationType.Y, LayerRotation[CubeFlag.MiddleLayer], new Point3D(0, 0, 0)); } if (cr.Position.HasFlag(CubeFlag.BottomLayer)) { cr = cr.Rotate(RotationType.Y, LayerRotation[CubeFlag.BottomLayer], new Point3D(0, -d, 0)); } if (cr.Position.HasFlag(CubeFlag.FrontSlice)) { cr = cr.Rotate(RotationType.Z, LayerRotation[CubeFlag.FrontSlice], new Point3D(0, 0, d)); } if (cr.Position.HasFlag(CubeFlag.MiddleSlice)) { cr = cr.Rotate(RotationType.Z, LayerRotation[CubeFlag.MiddleSlice], new Point3D(0, 0, 0)); } if (cr.Position.HasFlag(CubeFlag.BackSlice)) { cr = cr.Rotate(RotationType.Z, LayerRotation[CubeFlag.BackSlice], new Point3D(0, 0, -d)); } if (cr.Position.HasFlag(CubeFlag.LeftSlice)) { cr = cr.Rotate(RotationType.X, LayerRotation[CubeFlag.LeftSlice], new Point3D(-d, 0, 0)); } if (cr.Position.HasFlag(CubeFlag.MiddleSliceSides)) { cr = cr.Rotate(RotationType.X, LayerRotation[CubeFlag.MiddleSliceSides], new Point3D(0, 0, 0)); } if (cr.Position.HasFlag(CubeFlag.RightSlice)) { cr = cr.Rotate(RotationType.X, LayerRotation[CubeFlag.RightSlice], new Point3D(d, 0, 0)); } cr = cr.Rotate(RotationType.Y, this.Rotation[1], new Point3D(0, 0, 0)); cr = cr.Rotate(RotationType.Z, this.Rotation[2], new Point3D(0, 0, 0)); cr = cr.Rotate(RotationType.X, this.Rotation[0], new Point3D(0, 0, 0)); cubes3D.Add(cr); } return(cubes3D); }
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)); }
/// <summary> /// Parses a string to a pattern item /// </summary> /// <param name="s">The string to be parsed /// 1: "currentPos, targetPos, currentOrientation" /// 2: "currentPos, currentOrientation" => any target position /// 3: "currentPos, targetPos" => any orientation /// </param> public static PatternItem Parse(string s) { string[] split = s.Split(','); if (split.Length == 1) { CubeFlag currPos = CubeFlagService.Parse(split[0]); if (Pattern.Positions.Count(p => p.Flags == currPos) != 1) { throw new Exception("At least one orientation or position is not possible"); } return(new PatternItem(new CubePosition(currPos), 0, currPos)); } else if (split.Length == 2) { CubeFlag currPos = CubeFlagService.Parse(split[0]); CubeFlag pos = CubeFlagService.Parse(split[1]); int orientation = 0; if (Pattern.Positions.Count(p => p.Flags == currPos) != 1 || (!int.TryParse(split[1], out orientation) && Pattern.Positions.Count(p => p.Flags == pos) != 1)) { throw new Exception("At least one orientation or position is not possible"); } return(new PatternItem(new CubePosition(currPos), (Orientation)orientation, pos)); } else if (split.Length == 3) { // check valid cube position CubeFlag currPos = CubeFlagService.Parse(split[0]); CubeFlag targetPos = CubeFlagService.Parse(split[1]); if (!Pattern.Positions.Contains(new CubePosition(currPos)) || !Pattern.Positions.Contains(new CubePosition(targetPos))) { throw new Exception("At least one position does not exist"); } // check valid orientation int orientation = 0; if (!int.TryParse(split[2], out orientation)) { throw new Exception("At least one orientation is not possible"); } return(new PatternItem(new CubePosition(currPos), (Orientation)orientation, targetPos)); } else { throw new Exception("Parsing error"); } }
private void Update(int bufferIndex) { _renderHandle[bufferIndex].WaitOne(); if (this.Moves.Count > 0) { RotationInfo currentRotation = this.Moves.Peek(); foreach (AnimatedLayerMove rotation in currentRotation.Moves) { double step = (double)rotation.Target / (double)((double)(currentRotation.Milliseconds / 1000.0) * (double)(this.Fps)); this.LayerRotation[rotation.Move.Layer] += step; } if (RotationIsFinished(currentRotation.Moves)) { this.RotationFinished(this.Moves.Dequeue()); } } if (this.DrawingMode == RubiksCubeLib.CubeModel.DrawingMode.ThreeDimensional) { _buffer[bufferIndex] = this.GenFacesProjected(this.Screen, this.zoom); } else { List <Face3D> faces = new List <Face3D>(); foreach (Cube c in this.Rubik.Cubes) { faces.AddRange(c.Faces.Where(f => c.Position.Flags.HasFlag(CubeFlagService.FromFacePosition(f.Position))).Select(f => new Face3D(null, f.Color, f.Position, c.Position.Flags))); } _buffer[bufferIndex] = faces; } _updateHandle[bufferIndex].Set(); }
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 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.Count(tE => tE.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor) % 2 != 0) { return; } var correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == 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 (Rubik.CountEdgesWithCorrectOrientation() == 0) { SolverAlgorithm(solveTopCrossAlgorithmI); correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor); } if (Rubik.CountEdgesWithCorrectOrientation() == 2) { var firstCorrect = correctEdges.First(); var 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.Count(c => c.Position.Flags == GetTargetFlags(c)) < 4) { IEnumerable <Cube> correctEdges2 = topEdges.Where(c => c.Position.Flags == GetTargetFlags(c)); while (correctEdges2.Count() < 2) { SolverMove(CubeFlag.TopLayer, true); } CubeFlag rightSlice = CubeFlagService.FromFacePosition(correctEdges2.First().Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position); SolverMove(CubeFlag.TopLayer, false); if (correctEdges2.Count(c => c.Position.HasFlag(rightSlice)) == 0) { SolverMove(CubeFlag.TopLayer, true); } else { SolverMove(CubeFlag.TopLayer, true); rightSlice = CubeFlagService.FromFacePosition( correctEdges2 .First(cE => !cE.Position.HasFlag(rightSlice)) .Faces .First(f => f.Position != FacePosition.Top && f.Color != Color.Black ) .Position ); } // Algorithm: R U R' U R U U R' SolverAlgorithm( "{0} U {0}' U {0} U U {0}'", CubeFlagService.ToNotationString(rightSlice) ); while (correctEdges2.Count() < 2) { SolverMove(CubeFlag.TopLayer, true); } } }
private void CompleteMiddleLayer() { // Step 1: Get the egdes of the middle layer List <Cube> middleEdges = Rubik.Cubes .Where(c => c.IsEdge) .Where(c => GetTargetFlags(c).HasFlag(CubeFlag.MiddleLayer)) .ToList(); List <Face> coloredFaces = new List <Face>(); Rubik.Cubes.Where(cu => cu.IsCenter) .ToList() .ForEach(cu => coloredFaces.Add(cu.Faces.First(f => f.Color != Color.Black)) ); IEnumerable <Cube> solvedMiddleEdges = middleEdges .Where(mE => mE.Position.Flags == GetTargetFlags(mE) && mE.Faces.Count(f => coloredFaces.Count(cf => cf.Color == f.Color && cf.Position == f.Position) == 1) == 2 ); // Step 2: solve incorrect middle edges while (solvedMiddleEdges.Count() < 4) { IEnumerable <Cube> unsolvedMiddleEdges = middleEdges.Except(solvedMiddleEdges); Cube c = (unsolvedMiddleEdges.FirstOrDefault(cu => !cu.Position.HasFlag(CubeFlag.MiddleLayer)) != null) ? unsolvedMiddleEdges.First(cu => !cu.Position.HasFlag(CubeFlag.MiddleLayer)) : unsolvedMiddleEdges.First(); // Rotate to top layer if (!c.Position.HasFlag(CubeFlag.TopLayer)) { Face frontFace = c.Faces.First(f => f.Color != Color.Black); CubeFlag frontSlice = CubeFlagService.FromFacePosition(frontFace.Position); Face face = c.Faces.First(f => f.Color != Color.Black && f.Color != frontFace.Color); CubeFlag slice = CubeFlagService.FromFacePosition(face.Position); if (new TestScenario(Rubik, new LayerMove(slice, true, false)).TestCubePosition(c, CubeFlag.TopLayer)) { // Algorithm to the right: U R Ui Ri Ui Fi U F SolverAlgorithm( "U {0} U' {0}' U' {1}' U {1}", CubeFlagService.ToNotationString(slice), CubeFlagService.ToNotationString(frontSlice) ); } else { // Algorithm to the left: Ui Li U L U F Ui Fi SolverAlgorithm( "U' {0}' U {0} U {1} U' {1}'", CubeFlagService.ToNotationString(slice), CubeFlagService.ToNotationString(frontSlice) ); } } // Rotate to start position for the algorithm List <Cube> centers = Rubik.Cubes .Where(m => m.IsCenter) .Where(m => { var thing2 = m.Colors.First(co => co != Color.Black) == c.Faces.First(f => f.Color != Color.Black && f.Position != FacePosition.Top).Color; var thing3 = (m.Position.Flags & ~CubeFlag.MiddleLayer) == (c.Position.Flags & ~CubeFlag.TopLayer); return(thing2 && thing3); }) .ToList(); while (!centers.Any()) { SolverMove(CubeFlag.TopLayer, true); centers = Rubik.Cubes .Where(cu => cu.IsCenter) .Where(m => m.Colors.First(co => co != Color.Black) == c.Faces.First(f => f.Color != Color.Black && f.Position != FacePosition.Top).Color && (m.Position.Flags & ~CubeFlag.MiddleLayer) == (c.Position.Flags & ~CubeFlag.TopLayer) ) .ToList(); } // Rotate to target position Face frontFac = c.Faces.First(f => f.Color != Color.Black && f.Position != FacePosition.Top); CubeFlag frontSlic = CubeFlagService.FromFacePosition(frontFac.Position); CubeFlag slic = CubeFlagService.FirstNotInvalidFlag(GetTargetFlags(c), CubeFlag.MiddleLayer | frontSlic); if (!new TestScenario(Rubik, new LayerMove(CubeFlag.TopLayer, true, false)).TestCubePosition(c, slic)) { // Algorithm to the right: U R Ui Ri Ui Fi U F SolverAlgorithm( "U {0} U' {0}' U' {1}' U {1}", CubeFlagService.ToNotationString(slic), CubeFlagService.ToNotationString(frontSlic) ); } else { // Algorithm to the left: Ui Li U L U F Ui Fi SolverAlgorithm( "U' {0}' U {0} U {1} U' {1}'", CubeFlagService.ToNotationString(slic), CubeFlagService.ToNotationString(frontSlic) ); } solvedMiddleEdges = middleEdges.Where(mE => mE.Faces.Count(f => coloredFaces.Count(cf => cf.Color == f.Color && cf.Position == f.Position) == 1 ) == 2 ); } }
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 ); } }
private void CompleteFirstLayer() { // Step 1: Get the corners with target position on bottom layer IEnumerable <Cube> bottomCorners = Rubik.Cubes.Where(c => c.IsCorner && GetTargetFlags(c).HasFlag(CubeFlag.BottomLayer) ); IEnumerable <Cube> solvedBottomCorners = bottomCorners.Where(bC => bC.Position.Flags == GetTargetFlags(bC) && bC.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ); // Step 2: Solve incorrect edges while (solvedBottomCorners.Count() < 4) { IEnumerable <Cube> unsolvedBottomCorners = bottomCorners.Except(solvedBottomCorners); // here. Cube c = (unsolvedBottomCorners.FirstOrDefault(bC => bC.Position.HasFlag(CubeFlag.TopLayer)) != null) ? unsolvedBottomCorners.First(bC => bC.Position.HasFlag(CubeFlag.TopLayer)) : unsolvedBottomCorners.First(); if (c.Position.Flags != GetTargetFlags(c)) { // Rotate to top layer if (c.Position.HasFlag(CubeFlag.BottomLayer)) { Face leftFace = c.Faces.First(f => f.Position != FacePosition.Bottom && f.Color != Color.Black); CubeFlag leftSlice = CubeFlagService.FromFacePosition(leftFace.Position); SolverMove(leftSlice, false); if (c.Position.HasFlag(CubeFlag.BottomLayer)) { SolverMove(leftSlice, true); leftFace = c.Faces.First(f => f.Position != FacePosition.Bottom && f.Color != leftFace.Color && f.Color != Color.Black ); leftSlice = CubeFlagService.FromFacePosition(leftFace.Position); SolverMove(leftSlice, false); } SolverAlgorithm("U' {0} U", CubeFlagService.ToNotationString(leftSlice)); } // Rotate over target position CubeFlag targetPos = CubeFlagService.ExceptFlag(GetTargetFlags(c), CubeFlag.BottomLayer); while (!c.Position.HasFlag(targetPos)) { SolverMove(CubeFlag.TopLayer, true); } } // Rotate to target position with the algorithm: Li Ui L U Face leftFac = c.Faces.First(f => f.Position != FacePosition.Top && f.Position != FacePosition.Bottom && f.Color != Color.Black ); CubeFlag leftSlic = CubeFlagService.FromFacePosition(leftFac.Position); SolverMove(leftSlic, false); if (!c.Position.HasFlag(CubeFlag.TopLayer)) { SolverMove(leftSlic, true); leftFac = c.Faces.First(f => f.Position != FacePosition.Top && f.Position != FacePosition.Bottom && f.Color != leftFac.Color && f.Color != Color.Black ); leftSlic = CubeFlagService.FromFacePosition(leftFac.Position); } else { SolverMove(leftSlic, true); } while (c.Faces.First(f => f.Color == Rubik.BottomColor).Position != FacePosition.Bottom) { if (c.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Top) { SolverAlgorithm("{0}' U U {0} U", CubeFlagService.ToNotationString(leftSlic)); } else { Face frontFac = c.Faces.First(f => f.Position != FacePosition.Top && f.Position != FacePosition.Bottom && f.Color != Color.Black && f.Position != CubeFlagService.ToFacePosition(leftSlic) ); var thingA = c.Faces.First(f => f.Color == Rubik.BottomColor).Position == frontFac.Position; var thingB = !c.Position.HasFlag(CubeFlag.BottomLayer); if (thingA && thingB) { SolverAlgorithm("U' {0}' U {0}", CubeFlagService.ToNotationString(leftSlic)); } else { SolverAlgorithm("{0}' U' {0} U", CubeFlagService.ToNotationString(leftSlic)); } } } solvedBottomCorners = bottomCorners.Where(bC => bC.Position.Flags == GetTargetFlags(bC) && bC.Faces.First(f => f.Color == Rubik.BottomColor).Position == FacePosition.Bottom ); } }
/// <summary> /// Detection and execution of mouse-controlled layer rotations /// </summary> protected override void OnMouseClick(MouseEventArgs e) { if (this.MouseHandling) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (_oldSelection.IsDefault) { if (_currentSelection.IsDefault) { _selections.Reset(); _oldSelection = PositionSpec.Default; _currentSelection = PositionSpec.Default; } else { if (!CubePosition.IsCorner(_currentSelection.CubePosition)) { _oldSelection = _currentSelection; this.Rubik.Cubes.ForEach(c => c.Faces.Where(f => f.Color != Color.Black).ToList().ForEach(f => { PositionSpec pos = new PositionSpec() { CubePosition = c.Position.Flags, FacePosition = f.Position }; if (_currentSelection.CubePosition != c.Position.Flags && !CubePosition.IsCenter(c.Position.Flags) && _currentSelection.FacePosition == f.Position) { CubeFlag assocLayer = CubeFlagService.FromFacePosition(_currentSelection.FacePosition); CubeFlag commonLayer = CubeFlagService.GetFirstNotInvalidCommonFlag(_currentSelection.CubePosition, c.Position.Flags, assocLayer); if (commonLayer != CubeFlag.None && c.Position.HasFlag(commonLayer)) { _selections[pos] |= Selection.Possible; } else { _selections[pos] |= Selection.NotPossible; } } else { _selections[pos] |= Selection.NotPossible; } })); this.State = string.Format("First selection [{0}] | {1}", _currentSelection.CubePosition, _currentSelection.FacePosition); } else { _selections.Reset(); this.State = "Error: Invalid first selection, must not be a corner"; } } } else { if (_currentSelection.IsDefault) { this.State = "Ready"; } else { if (_currentSelection.CubePosition != _oldSelection.CubePosition) { if (!CubePosition.IsCenter(_currentSelection.CubePosition)) { if (_oldSelection.FacePosition == _currentSelection.FacePosition) { CubeFlag assocLayer = CubeFlagService.FromFacePosition(_oldSelection.FacePosition); CubeFlag commonLayer = CubeFlagService.GetFirstNotInvalidCommonFlag(_oldSelection.CubePosition, _currentSelection.CubePosition, assocLayer); bool direction = true; if (commonLayer == CubeFlag.TopLayer || commonLayer == CubeFlag.MiddleLayer || commonLayer == CubeFlag.BottomLayer) { if (((_oldSelection.FacePosition == FacePosition.Back) && _currentSelection.CubePosition.HasFlag(CubeFlag.RightSlice)) || ((_oldSelection.FacePosition == FacePosition.Left) && _currentSelection.CubePosition.HasFlag(CubeFlag.BackSlice)) || ((_oldSelection.FacePosition == FacePosition.Front) && _currentSelection.CubePosition.HasFlag(CubeFlag.LeftSlice)) || ((_oldSelection.FacePosition == FacePosition.Right) && _currentSelection.CubePosition.HasFlag(CubeFlag.FrontSlice))) { direction = false; } if (commonLayer == CubeFlag.TopLayer || commonLayer == CubeFlag.MiddleLayer) { direction = !direction; } } if (commonLayer == CubeFlag.LeftSlice || commonLayer == CubeFlag.MiddleSliceSides || commonLayer == CubeFlag.RightSlice) { if (((_oldSelection.FacePosition == FacePosition.Bottom) && _currentSelection.CubePosition.HasFlag(CubeFlag.BackSlice)) || ((_oldSelection.FacePosition == FacePosition.Back) && _currentSelection.CubePosition.HasFlag(CubeFlag.TopLayer)) || ((_oldSelection.FacePosition == FacePosition.Top) && _currentSelection.CubePosition.HasFlag(CubeFlag.FrontSlice)) || ((_oldSelection.FacePosition == FacePosition.Front) && _currentSelection.CubePosition.HasFlag(CubeFlag.BottomLayer))) { direction = false; } if (commonLayer == CubeFlag.LeftSlice) { direction = !direction; } } if (commonLayer == CubeFlag.BackSlice || commonLayer == CubeFlag.MiddleSlice || commonLayer == CubeFlag.FrontSlice) { if (((_oldSelection.FacePosition == FacePosition.Top) && _currentSelection.CubePosition.HasFlag(CubeFlag.RightSlice)) || ((_oldSelection.FacePosition == FacePosition.Right) && _currentSelection.CubePosition.HasFlag(CubeFlag.BottomLayer)) || ((_oldSelection.FacePosition == FacePosition.Bottom) && _currentSelection.CubePosition.HasFlag(CubeFlag.LeftSlice)) || ((_oldSelection.FacePosition == FacePosition.Left) && _currentSelection.CubePosition.HasFlag(CubeFlag.TopLayer))) { direction = false; } if (commonLayer == CubeFlag.FrontSlice || commonLayer == CubeFlag.MiddleSlice) { direction = !direction; } } if (commonLayer != CubeFlag.None) { RotateLayerAnimated(commonLayer, direction); } else { this.State = "Error: Invalid second selection, does not specify distinct layer"; } } else { this.State = "Error: Invalid second selection, must match orientation of first selection"; } } else { this.State = "Error: Invalid second selection, must not be a center"; } } else { this.State = "Error: Invalid second selection, must not be first selection"; } } _selections.Reset(); _oldSelection = PositionSpec.Default; _currentSelection = PositionSpec.Default; } } } base.OnMouseClick(e); }
public PositionSpec Render2D(Graphics g, IEnumerable <Face3D> frame, Point mousePos) { g.SmoothingMode = SmoothingMode.AntiAlias; PositionSpec pos = PositionSpec.Default; int square = 0, borderX = 5, borderY = 5; if (((double)(this.Screen.Width - 10) / (double)(this.Screen.Height - 10)) > (4.0 / 3.0)) { square = (int)(this.Screen.Height / 9.0); borderX = (this.Screen.Width - 12 * square) / 2; } else { square = (int)(this.Screen.Width / 12.0); borderY = (this.Screen.Height - 9 * square) / 2; } List <Face3D> faces = new List <Face3D>(); foreach (Cube c in this.Rubik.Cubes) { faces.AddRange(c.Faces.Where(f => c.Position.Flags.HasFlag(CubeFlagService.FromFacePosition(f.Position))).Select(f => new Face3D(null, f.Color, f.Position, c.Position.Flags))); } frame = faces; foreach (Face3D face in frame) { #region CalculatePoints int x = 0, y = 0; int xOffs = borderX, yOffs = borderY; if (face.Position.HasFlag(FacePosition.Front)) { xOffs += 3 * square; yOffs += 3 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.X) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Y) * (-1) + 1) * square; } if (face.Position.HasFlag(FacePosition.Top)) { xOffs += 3 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.X) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Z) + 1) * square; } if (face.Position.HasFlag(FacePosition.Bottom)) { xOffs += 3 * square; yOffs += 6 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.X) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Z) * (-1) + 1) * square; } if (face.Position.HasFlag(FacePosition.Left)) { yOffs += 3 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.Z) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Y) * (-1) + 1) * square; } if (face.Position.HasFlag(FacePosition.Right)) { xOffs += 6 * square; yOffs += 3 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.Z) * (-1) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Y) * (-1) + 1) * square; } if (face.Position.HasFlag(FacePosition.Back)) { xOffs += 9 * square; yOffs += 3 * square; CubePosition cubePos = new CubePosition(face.MasterPosition); x = xOffs + (CubeFlagService.ToInt(cubePos.X) * (-1) + 1) * square; y = yOffs + (CubeFlagService.ToInt(cubePos.Y) * (-1) + 1) * square; } #endregion Point[] parr = new Point[] { new Point(x, y), new Point(x, y + square), new Point(x + square, y + square), new Point(x + square, y) }; Brush b = new SolidBrush(face.Color); double factor = ((Math.Sin((double)Environment.TickCount / (double)200) + 1) / 4) + 0.75; PositionSpec facePos = new PositionSpec() { FacePosition = face.Position, CubePosition = face.MasterPosition }; if (this.MouseHandling) { if (_selections[facePos].HasFlag(Selection.Second)) { b = new HatchBrush(HatchStyle.Percent75, Color.Black, face.Color); } else if (_selections[facePos].HasFlag(Selection.NotPossible)) { b = new SolidBrush(Color.FromArgb(face.Color.A, (int)(face.Color.R * 0.3), (int)(face.Color.G * 0.3), (int)(face.Color.B * 0.3))); } else if (_selections[facePos].HasFlag(Selection.First)) { b = new HatchBrush(HatchStyle.Percent30, Color.Black, face.Color); } else if (_selections[facePos].HasFlag(Selection.Possible)) { b = new SolidBrush(Color.FromArgb(face.Color.A, (int)(Math.Min(face.Color.R * factor, 255)), (int)(Math.Min(face.Color.G * factor, 255)), (int)(Math.Min(face.Color.B * factor, 255)))); } else { b = new SolidBrush(face.Color); } } else { b = new SolidBrush(face.Color); } g.FillPolygon(b, parr); g.DrawPolygon(new Pen(Color.Black, 1), parr); GraphicsPath gp = new GraphicsPath(); gp.AddPolygon(parr); if (gp.IsVisible(mousePos)) { pos = facePos; } } g.DrawRectangle(Pens.Black, 0, this.Height - 25, this.Width - 1, 24); //g.DrawLine(Pens.Black, 0, this.Height - 25, this.Width, this.Height - 25); g.DrawString(string.Format("[{0}] | {1}", _currentSelection.CubePosition, _currentSelection.FacePosition), this.Font, Brushes.Black, 5, this.Height - 20); g.DrawRectangle(Pens.Black, 0, this.Height - 50, this.Width - 1, 25); g.DrawString(this.State, this.Font, Brushes.Black, 5, this.Height - 45); g.DrawRectangle(Pens.Black, 0, 0, this.Width - 1, this.Height - 50); return(pos); }
private void InitPatterns(CubeFlag r, CubeFlag f) { CubeFlag l = CubeFlagService.GetOppositeFlag(r); CubeFlag b = CubeFlagService.GetOppositeFlag(f); bool rIsX = CubeFlagService.IsXFlag(r); // edge orientation changes depending on the target slot Orientation correct = (r == CubeFlag.BackSlice && f == CubeFlag.RightSlice) || (f == CubeFlag.LeftSlice && r == CubeFlag.FrontSlice) ? Orientation.Correct : Orientation.Clockwise; Orientation clockwise = correct == Orientation.Correct ? Orientation.Clockwise : Orientation.Correct; patterns = new Dictionary <Pattern, Algorithm>() { #region Corner correct oriented at targetposition { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | f | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Correct, CornerTargetPos) }), new Algorithm("U {0} U {0}' U' {1}' U' {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | r | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Correct, CornerTargetPos) }), new Algorithm("U' {1}' U' {1} U {0} U {0}'", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0}2 U2 {1} {0}2 {1}' U2 {0}' U {0}'", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, #endregion #region Corner clockwise oriented at target position { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | f | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0}' U {0} U' {0}' U {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | r | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0} U {0}' U' {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0} U2 {0} U {0}' U {0} U2 {0}2", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0} U {0}' U' {0} U' {0}' U2 {1}' U' {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, #endregion #region Corner counter-clockwise oriented at target position { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | f | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{0}' U' {0} U {0}' U' {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | r | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice)), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{0} U' {0}' U {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{0}' U' {0} U2 {0}' U {0} U' {0}' U' {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{1}' U' {1} U {1}' U {1} U2 {0} U {0}'", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, #endregion #region Corner correct oriented in top layer { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0} U {0}' U' {0} U {0}' U' {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0} U' {0}' U {1}' U {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("U {0} U2 {0}' U {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0}' U {0} U2 {0}' U' {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0} U' {0}' U2 {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("U' {0}' U2 {0} U' {0}' U {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0}' U2 {0} U {0}' U' {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0}' U' {1}' U {1} {0} {1}' U {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0} U2 {0}' U' {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, CornerTargetPos) }), new Algorithm("{0} U {1} U' {1}' {0}' {1} U' {1}'", CubeFlagService.ToNotationString(f), CubeFlagService.ToNotationString(r)) }, #endregion #region Corner counter-clockwise oriented in top layer { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U' {0} U' {0}' U2 {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U' {0} U {0}' U {1}' U' {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0} U2 {0}2 U' {0}2 U' {0}'", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U' {0} U {0}' U2 {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U' {0} U' {0}' U {1}' U' {1}", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0}' U' {0}", CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("U' {0} U2 {0}' U2 {0} U' {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("d {0}' U {0} U' {0}' U' {0}", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, CornerTargetPos) }), new Algorithm("{0}' U {0} U2 {1} U {1}'", CubeFlagService.ToNotationString(f), CubeFlagService.ToNotationString(r)) }, #endregion #region Corner clockwise oriented in top layer { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("U {0} U {0}' U2 {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(EdgeTargetPos), Orientation.Clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("U2 {1}' U {1} U {0} U {0}'", CubeFlagService.ToNotationString(r), CubeFlagService.ToNotationString(f)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("U' {0} U' {0}' U {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | r), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{1} U' {1}' U2 {0}' U' {0}", CubeFlagService.ToNotationString(f), CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("d {0}' U2 {0} U2 {0}' U {0}", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | b), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("d {0}' U' {0} U2 {0}' U {0}", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (!rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | l), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("d {0}' U {0} d' {0} U {0}'", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), clockwise, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("{0}' U2 {0}2 U {0}2 U {0}", CubeFlagService.ToNotationString(r)) }, { new Pattern(new List <PatternItem>() { new PatternItem(new CubePosition(CubeFlag.TopLayer | (rIsX ? CubeFlag.MiddleSliceSides : CubeFlag.MiddleSlice) | f), correct, EdgeTargetPos), new PatternItem(new CubePosition(CornerTargetPos & ~CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, CornerTargetPos) }), new Algorithm("U' {0}' U {0}", CubeFlagService.ToNotationString(f)) } #endregion }; }
// **** 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); }