// *** CONSTRUCTOR *** /// <summary> /// Initializes a new instance of the Face3D class /// </summary> /// <param name="vertices">Vertices of the 3D face</param> /// <param name="color">Color</param> /// <param name="position">Position</param> /// <param name="masterPosition">Position of the parent 3D cube</param> public Face3D(IEnumerable<Point3D> vertices, Color color, FacePosition position, CubeFlag masterPosition) { this.Vertices = vertices; this.Color = color; this.Position = position; this.MasterPosition = masterPosition; }
/// <summary> /// Initializes a new instance of the Cube3D class /// </summary> /// <param name="faces">Faces</param> /// <param name="position">Position</param> public Cube3D(IEnumerable<Face3D> faces, CubeFlag position, Point3D location, double scale) { this.Faces = faces; this.Position = position; this.Location = location; this.Scale = scale; }
// **** METHODS **** /// <summary> /// Returns true if the given CubeFlag contains a valid move /// </summary> /// <param name="flags">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsPossibleMove(CubeFlag flags) { flags = ExceptFlag(flags, CubeFlag.None); return GetFlags(flags).All(f => IsXFlag((CubeFlag)f)) || GetFlags(flags).All(f => IsYFlag((CubeFlag)f)) || GetFlags(flags).All(f => IsZFlag((CubeFlag)f)); }
/// <summary> /// Finds all possible algorithms for this pattern /// </summary> /// <param name="p">Current rubik pattern</param> /// <param name="rotationLayer">Transformation rotation</param> /// <returns>Returns all possible solutions for this pattern</returns> public Dictionary<Pattern, Algorithm> FindMatches(Pattern p, CubeFlag rotationLayer, PatternFilter filter) { Dictionary<Pattern, Algorithm> transformedPatterns = Patterns.ToDictionary(kvp => kvp.Key.DeepClone(), a => a.Value); // clone Dictionary<Pattern,Algorithm> filteredPatterns = transformedPatterns.Where(kvp => filter.Filter(p, kvp.Key)).ToDictionary(pa => pa.Key, a => a.Value); // filter filteredPatterns = filteredPatterns.OrderByDescending(k => k.Key.Probability).ToDictionary(pa => pa.Key.DeepClone(), a => a.Value); // order by probability Dictionary<Pattern, Algorithm> matches = new Dictionary<Pattern, Algorithm>(); // 4 possible standard transformations for (int i = 0; i < 4; i++) { // Get matches foreach (KeyValuePair<Pattern, Algorithm> kvp in filteredPatterns.Where(pa => p.IncludesAllPatternElements(pa.Key))) { matches.Add(kvp.Key, kvp.Value); // Add to matches } if (rotationLayer == CubeFlag.None) return matches; if (filter.OnlyAtBeginning) { transformedPatterns = filteredPatterns.Except(matches).ToDictionary(pa => pa.Key.Transform(rotationLayer), a => a.Value.Transform(rotationLayer)); filteredPatterns = transformedPatterns; } else { transformedPatterns = transformedPatterns.ToDictionary(pa => pa.Key.Transform(rotationLayer), a => a.Value.Transform(rotationLayer)); filteredPatterns = transformedPatterns.Where(kvp => filter.Filter(p, kvp.Key)).ToDictionary(pa => pa.Key, a => a.Value); } } return matches; }
/// <summary> /// Constructor with faces and position /// </summary> /// <param name="faces">Defines the faces where the cube belongs to</param> /// <param name="position">Defines the position of the cube</param> public Cube(IEnumerable<Face> faces, CubeFlag position) { this.Faces = faces; this.Position = new CubePosition(position); this.Colors = new List<Color>(); this.Colors.Clear(); this.Faces.ToList().ForEach(f => Colors.Add(f.Color)); }
/// <summary> /// Returns a collection with six entries containing the six Faces3D with a black color /// </summary> /// <param name="masterPosition">Defines the master position of the Faces3D</param> /// <returns></returns> public static IEnumerable<Face3D> GenFaces3D(CubeFlag masterPosition) => new[] { new Face3D(new[] { new Point3D(-1, 1, -1), new Point3D(1, 1, -1), new Point3D(1, -1, -1), new Point3D(-1, -1, -1) }, Color.Black, FacePosition.Front, masterPosition), new Face3D(new[] { new Point3D(-1, 1, 1), new Point3D(1, 1, 1), new Point3D(1, -1, 1), new Point3D(-1, -1, 1) }, Color.Black, FacePosition.Back, masterPosition), new Face3D(new[] { new Point3D(-1, -1, -1), new Point3D(1, -1, -1), new Point3D(1, -1, 1), new Point3D(-1, -1, 1) }, Color.Black, FacePosition.Top, masterPosition), new Face3D(new[] { new Point3D(-1, 1, -1), new Point3D(1, 1, -1), new Point3D(1, 1, 1), new Point3D(-1, 1, 1) }, Color.Black, FacePosition.Bottom, masterPosition), new Face3D(new[] { new Point3D(1, 1, 1), new Point3D(1, 1, -1), new Point3D(1, -1, -1), new Point3D(1, -1, 1) }, Color.Black, FacePosition.Right, masterPosition), new Face3D(new[] { new Point3D(-1, 1, 1), new Point3D(-1, 1, -1), new Point3D(-1, -1, -1), new Point3D(-1, -1, 1) }, Color.Black, FacePosition.Left, masterPosition) };
// **** METHODS **** /// <summary> /// Returns true if the given CubeFlag describes a corner cube /// </summary> /// <param name="position">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsCorner(CubeFlag position) => ((position == (CubeFlag.TopLayer | CubeFlag.FrontSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.TopLayer | CubeFlag.FrontSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.TopLayer | CubeFlag.BackSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.TopLayer | CubeFlag.BackSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.FrontSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.FrontSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.BackSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.BackSlice | CubeFlag.RightSlice)));
/// <summary> /// Returns the first flag in the first parameter which the second parameter does not contain /// </summary> /// <param name="flags">Defines the posiible flags to be returned</param> /// <param name="invalid">Defines the invalid flags</param> /// <returns></returns> public static CubeFlag FirstNotInvalidFlag(CubeFlag flags, CubeFlag invalid) { foreach (CubeFlag f in GetFlags(flags)) { if (!invalid.HasFlag(f)) return f; } return CubeFlag.None; }
/// <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; }
public bool TestCubePosition(Cube c, CubeFlag endPos) { foreach(LayerMove move in Algorithm.Moves) { Rubik.RotateLayer(move); } bool result = RefreshCube(c).Position.HasFlag(endPos); return result; }
/// <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; }
public bool TestCubePosition(Cube c, CubeFlag endPos) { foreach (var move in this.Algorithm.Moves.Cast<LayerMove>()) { this.Rubik.RotateLayer(move); } var result = this.RefreshCube(c).Position.HasFlag(endPos); return result; }
/// <summary> /// Returns a CubeFlag which contains all flags which exist in both the first and the second parameter /// </summary> /// <param name="first">Defines the first CubeFlag</param> /// <param name="second">Defines the second CubeFlag</param> /// <returns></returns> public static CubeFlag CommonFlags(CubeFlag first, CubeFlag second) { CubeFlag commonFlags = CubeFlag.None; foreach (CubeFlag flag in GetFlags(first)) { if (second.HasFlag(flag)) commonFlags |= flag; } return commonFlags; }
/// <summary> /// Returns a ClubFlag which contains all single flags in the first parameter which don't exist in the second parameter /// </summary> /// <param name="flags">Defines all possible flags</param> /// <param name="invalid">Defines the flags to be filtered out of the first parameter</param> /// <returns></returns> public static CubeFlag ExceptFlag(CubeFlag flags, CubeFlag invalid) { CubeFlag pos = CubeFlag.None; foreach (CubeFlag p in GetFlags(flags)) { if (!invalid.HasFlag(p)) pos |= p; } return pos; }
// *** CONSTRUCTORS *** /// <summary> /// Constructor /// </summary> /// <param name="layer">Defines the layer to be moved</param> /// <param name="direction">Defines the direction (true == clockwise and false == counter-clockwise)</param> /// <param name="twice">Defines whether this layer will be turned twice or not</param> /// <exception cref="System.Exception">Thrown when layer contains more than one flag</exception> public LayerMove(CubeFlag layer, bool direction = true, bool twice = false) { if (CubeFlagService.CountFlags(layer) == 1) { this.Layer = layer; this.Direction = direction; this.Twice = twice; } else throw new Exception("Impossible movement"); }
/// <summary> /// Returns true if the given CubeFlag describes a edge cube /// </summary> /// <param name="position">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsEdge(CubeFlag position) => ((position == (CubeFlag.TopLayer | CubeFlag.FrontSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.TopLayer | CubeFlag.BackSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.TopLayer | CubeFlag.RightSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.TopLayer | CubeFlag.LeftSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.FrontSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.FrontSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.BackSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.BackSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.FrontSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.BottomLayer | CubeFlag.BackSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.BottomLayer | CubeFlag.RightSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.LeftSlice | CubeFlag.MiddleSlice)));
/// <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"); } }
/// <summary> /// Returns true if the given CubeFlag describes a edge cube /// </summary> /// <param name="position">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsEdge(CubeFlag position) { return((position == (CubeFlag.TopLayer | CubeFlag.FrontSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.TopLayer | CubeFlag.BackSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.TopLayer | CubeFlag.RightSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.TopLayer | CubeFlag.LeftSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.FrontSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.FrontSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.BackSlice | CubeFlag.RightSlice)) || (position == (CubeFlag.MiddleLayer | CubeFlag.BackSlice | CubeFlag.LeftSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.FrontSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.BottomLayer | CubeFlag.BackSlice | CubeFlag.MiddleSliceSides)) || (position == (CubeFlag.BottomLayer | CubeFlag.RightSlice | CubeFlag.MiddleSlice)) || (position == (CubeFlag.BottomLayer | CubeFlag.LeftSlice | CubeFlag.MiddleSlice))); }
/// <summary> /// Returns the CubeFlag of the Cube at the given 3D position /// </summary> /// <param name="i">Defines the XFlag (left to right)</param> /// <param name="j">Defines the YFlag (top to bottom)</param> /// <param name="k">Defines the ZFlag (front to back)</param> /// <returns></returns> public CubeFlag GenSideFlags(int i, int j, int k) { CubeFlag p = new CubeFlag(); switch (i) { case -1: p |= CubeFlag.LeftSlice; break; case 0: p |= CubeFlag.MiddleSliceSides; break; case 1: p |= CubeFlag.RightSlice; break; } switch (j) { case -1: p |= CubeFlag.TopLayer; break; case 0: p |= CubeFlag.MiddleLayer; break; case 1: p |= CubeFlag.BottomLayer; break; } switch (k) { case -1: p |= CubeFlag.FrontSlice; break; case 0: p |= CubeFlag.MiddleSlice; break; case 1: p |= CubeFlag.BackSlice; break; } return(p); }
/// <summary> /// Converts a CubeFlag into values from -1 to 1 /// </summary> /// <param name="flag">todo: describe flag parameter on ToInt</param> /// <exception cref="Exception">Thrown when the CubeFlag is either invalid or has more than one flag</exception> public static int ToInt(CubeFlag flag) { if (IsXFlag(flag)) { switch (flag) { case CubeFlag.RightSlice: return 1; case CubeFlag.MiddleSliceSides: return 0; default: return -1; } } if (IsYFlag(flag)) { switch (flag) { case CubeFlag.TopLayer: return -1; case CubeFlag.MiddleLayer: return 0; default: return 1; } } if (IsZFlag(flag)) { switch (flag) { case CubeFlag.BackSlice: return 1; case CubeFlag.MiddleSlice: return 0; default: return -1; } } if (flag == CubeFlag.None) return 0; throw new Exception("Flag can not be converted to an integer"); }
/// <summary> /// Parses a notation into a collection of cube flags /// </summary> public static CubeFlag Parse(string notation) { CubeFlag flags = CubeFlag.None; for (int i = 0; i < notation.Length; i++) { switch (notation[i]) { case 'R': flags |= CubeFlag.RightSlice; break; case 'L': flags |= CubeFlag.LeftSlice; break; case 'U': flags |= CubeFlag.TopLayer; break; case 'D': flags |= CubeFlag.BottomLayer; break; case 'F': flags |= CubeFlag.FrontSlice; break; case 'B': flags |= CubeFlag.BackSlice; break; case 'M': flags |= CubeFlag.MiddleSliceSides; break; case 'E': flags |= CubeFlag.MiddleLayer; break; case 'S': flags |= CubeFlag.MiddleSlice; break; } } return(flags); }
/// <summary> /// Adds an item at the end of the collection /// </summary> /// <param name="item">Defines the item which is meant to be added</param> /// <exception cref="System.Exception">Thrown if this movement would be impossible</exception> public void Add(LayerMove item) { CubeFlag flag = item.Layer; foreach (LayerMove m in _moves) { flag |= m.Layer; } if (CubeFlagService.IsPossibleMove(flag)) { _moves.Add(item); } else { throw new Exception("Impossible movement"); } }
/// <summary> /// Converts the given CubeFlag into a notation string /// </summary> public static string ToNotationString(CubeFlag flag) { string notation = string.Empty; if (flag.HasFlag(CubeFlag.TopLayer)) { notation += "U"; } if (flag.HasFlag(CubeFlag.BottomLayer)) { notation += "D"; } if (flag.HasFlag(CubeFlag.FrontSlice)) { notation += "F"; } if (flag.HasFlag(CubeFlag.RightSlice)) { notation += "R"; } if (flag.HasFlag(CubeFlag.BackSlice)) { notation += "B"; } if (flag.HasFlag(CubeFlag.LeftSlice)) { notation += "L"; } if (flag.HasFlag(CubeFlag.MiddleSlice)) { notation += "S"; } if (flag.HasFlag(CubeFlag.MiddleSliceSides)) { notation += "M"; } if (flag.HasFlag(CubeFlag.MiddleLayer)) { notation += "E"; } return(notation); }
/// <summary> /// Returns the center color of a slice /// </summary> /// <param name="slice">Defines the slice whose center color will be returned</param> public Color GetSliceColor(CubeFlag slice) { switch (slice) { case CubeFlag.TopLayer: return(this.TopColor); case CubeFlag.BottomLayer: return(this.BottomColor); case CubeFlag.FrontSlice: return(this.FrontColor); case CubeFlag.BackSlice: return(this.BackColor); case CubeFlag.LeftSlice: return(this.LeftColor); case CubeFlag.RightSlice: return(this.RightColor); default: return(Color.Black); } }
// *** CONSTRUCTOR *** /// <summary> /// Initializes a new instance of the Cube3D class /// </summary> /// <param name="location">Center point</param> /// <param name="scale">Scale</param> /// <param name="position">Position</param> /// <param name="faces">Faces</param> public Cube3D(Point3D location, double scale, CubeFlag position, IEnumerable <Face> faces) { this.Faces = UniCube.GenFaces3D(position); this.Position = position; this.Location = location; this.Scale = scale; this.Faces.ToList().ForEach(f => { f.Color = faces.First(face => face.Position == f.Position).Color; f.Vertices.ToList().ForEach(e => { e.X *= scale; e.Y *= scale; e.Z *= scale; //scale e.X += location.X; e.Y += location.Y; e.Z += location.Z; //translate }); }); }
// *** CONSTRUCTOR *** /// <summary> /// Initializes a new instance of the Cube3D class /// </summary> /// <param name="location">Center point</param> /// <param name="scale">Scale</param> /// <param name="position">Position</param> /// <param name="faces">Faces</param> public Cube3D(Point3D location, double scale, CubeFlag position, IEnumerable<Face> faces) { this.Faces = UniCube.GenFaces3D(position); this.Position = position; this.Location = location; this.Scale = scale; this.Faces.ToList().ForEach(f => { f.Color = faces.First(face => face.Position == f.Position).Color; f.Vertices.ToList().ForEach(e => { e.X *= scale; e.Y *= scale; e.Z *= scale; //scale e.X += location.X; e.Y += location.Y; e.Z += location.Z; //translate }); }); }
/// <summary> /// Parses a notation string into a layer move /// </summary> /// <param name="notation">String to be parsed</param> /// <param name="move">The resulting layer move</param> /// <returns>True, if the string was successfully parsed into a layermove</returns> public static bool TryParse(string notation, out LayerMove move) { move = null; string layer = notation[0].ToString(); CubeFlag rotationLayer = CubeFlagService.Parse(layer); char[] ccwChars = new char[] { '\'', 'i' }; bool direction = !ccwChars.Any(c => notation.Contains(c)); bool twice = notation.Contains("2"); if (CubeFlagService.CountFlags(rotationLayer) == 1) { move = new LayerMove(rotationLayer, direction, twice); return(true); } else { return(false); } }
/// <summary> /// Returns true if the flag is a ZFlag only /// </summary> /// <param name="flag">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsZFlag(CubeFlag flag) => CubeFlag.ZFlags.HasFlag(flag);
/// <summary> /// Returns true if the flag is a ZFlag only /// </summary> /// <param name="flag">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static bool IsZFlag(CubeFlag flag) { return(CubeFlag.ZFlags.HasFlag(flag)); }
/// <summary> /// Returns a CubeFlag which is the opposite of the parameter /// </summary> /// <param name="flag">Defines the parameter to be analyzed</param> /// <returns></returns> public static CubeFlag GetOppositeFlag(CubeFlag flag) { switch (flag) { case CubeFlag.TopLayer: return CubeFlag.BottomLayer; case CubeFlag.BottomLayer: return CubeFlag.TopLayer; case CubeFlag.FrontSlice: return CubeFlag.BackSlice; case CubeFlag.BackSlice: return CubeFlag.FrontSlice; case CubeFlag.LeftSlice: return CubeFlag.RightSlice; case CubeFlag.RightSlice: return CubeFlag.LeftSlice; case CubeFlag.MiddleLayer: case CubeFlag.MiddleSlice: case CubeFlag.MiddleSliceSides: return flag; default: return CubeFlag.None; } }
/// <summary> /// Returns the next flag after a layer rotation /// </summary> /// <param name="rotationLayer">Rotation layer</param> /// <param name="direction">Rotation direction</param> /// <returns>Next cube flag</returns> public static CubeFlag NextCubeFlag(CubeFlag flag, CubeFlag rotationLayer, bool direction = true) { var nextFlag = CubeFlag.None; if (CountFlags(flag) != 1) { return ExceptFlag(nextFlag, CubeFlag.None); } if (IsXFlag(rotationLayer)) { if (rotationLayer == CubeFlag.LeftSlice) direction = !direction; if (!direction && !IsXFlag(flag)) flag = GetOppositeFlag(flag); switch (flag) { case CubeFlag.FrontSlice: nextFlag = CubeFlag.TopLayer; break; case CubeFlag.MiddleSlice: nextFlag = CubeFlag.MiddleLayer; break; case CubeFlag.BackSlice: nextFlag = CubeFlag.BottomLayer; break; case CubeFlag.TopLayer: nextFlag = CubeFlag.BackSlice; break; case CubeFlag.MiddleLayer: nextFlag = CubeFlag.MiddleSlice; break; case CubeFlag.BottomLayer: nextFlag = CubeFlag.FrontSlice; break; default: nextFlag = flag; break; } } else if (IsYFlag(rotationLayer)) { if (rotationLayer == CubeFlag.BottomLayer) direction = !direction; if (!direction && !IsYFlag(flag)) flag = GetOppositeFlag(flag); switch (flag) { case CubeFlag.FrontSlice: nextFlag = CubeFlag.LeftSlice; break; case CubeFlag.MiddleSlice: nextFlag = CubeFlag.MiddleSliceSides; break; case CubeFlag.BackSlice: nextFlag = CubeFlag.RightSlice; break; case CubeFlag.LeftSlice: nextFlag = CubeFlag.BackSlice; break; case CubeFlag.MiddleSliceSides: nextFlag = CubeFlag.MiddleSlice; break; case CubeFlag.RightSlice: nextFlag = CubeFlag.FrontSlice; break; default: nextFlag = flag; break; } } else if (IsZFlag(rotationLayer)) { if (rotationLayer == CubeFlag.BackSlice) direction = !direction; if (!direction && !IsZFlag(flag)) flag = GetOppositeFlag(flag); switch (flag) { case CubeFlag.TopLayer: nextFlag = CubeFlag.RightSlice; break; case CubeFlag.MiddleLayer: nextFlag = CubeFlag.MiddleSliceSides; break; case CubeFlag.BottomLayer: nextFlag = CubeFlag.LeftSlice; break; case CubeFlag.LeftSlice: nextFlag = CubeFlag.TopLayer; break; case CubeFlag.MiddleSliceSides: nextFlag = CubeFlag.MiddleLayer; break; case CubeFlag.RightSlice: nextFlag = CubeFlag.BottomLayer; break; default: nextFlag = flag; break; } } return ExceptFlag(nextFlag, CubeFlag.None); }
/// <summary> /// Returns the first ZFlag in the given CubeFlag /// </summary> /// <param name="flags">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static CubeFlag FirstZFlag(CubeFlag flags) { return(FirstNotInvalidFlag(flags, CubeFlag.XFlags | CubeFlag.YFlags)); }
/// <summary> /// Returns the first flag which exists in the first and second parameter but not in the third parameter /// </summary> /// <param name="a">Defines the first CubeFlag</param> /// <param name="b">Defines the second CubeFlag</param> /// <param name="exclude">Defines the CubeFlag which is not allowed</param> /// <returns></returns> public static CubeFlag GetFirstNotInvalidCommonFlag(CubeFlag a, CubeFlag b, CubeFlag exclude) => FirstNotInvalidFlag(CommonFlags(a, b), exclude);
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 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 }; }
// ** ENLARGE RENDER QUEUE ** /// <summary> /// Registers a new animated rotation /// </summary> /// <param name="layer">Rotation layer</param> /// <param name="direction">Direction of rotation</param> public void RotateLayerAnimated(CubeFlag layer, bool direction) { RotateLayerAnimated(new LayerMove(layer, direction), this.RotationSpeed); }
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.Count(c => c.Position.Flags == GetTargetFlags(c)) < 4) { var 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, false)).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); var scenario = new TestScenario(this.Rubik, new LayerMove(CubeFlagService.FromFacePosition(rightFac.Position), true, false)); var scenarioPassed = scenario.TestCubePosition(topCorners.First(), CubeFlag.TopLayer); var positionForRightSlic = !scenarioPassed ? rightFac.Position : topCorners.First().Faces.First(f => f.Color != rightFac.Color && f.Color != Color.Black && f.Position != FacePosition.Top).Position; CubeFlag rightSlic = CubeFlagService.FromFacePosition(positionForRightSlic); foreach (Cube c in topCorners) { while (!c.Position.HasFlag(rightSlic)) { SolverMove(CubeFlag.TopLayer, true); } if (!new TestScenario(Rubik, new LayerMove(rightSlic, true, false)).TestCubePosition(c, CubeFlag.TopLayer)) { SolverMove(CubeFlag.TopLayer, true); } // Algorithm: R' D' 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); } }
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 && 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); } }
/// <summary> /// Returns true if this CubeFlag has the given CubeFlag /// </summary> /// <param name="flag">Defines the CubeFlag which will be checked</param> /// <returns></returns> public bool HasFlag(CubeFlag flag) { return(this.Flags.HasFlag(flag)); }
public F2LPattern(CubeFlag edgeTargetPos, CubeFlag cornerTargetPos, CubeFlag rightSlice, CubeFlag frontSlice) { this.CornerTargetPos = cornerTargetPos; this.EdgeTargetPos = edgeTargetPos; this.InitPatterns(rightSlice, frontSlice); }
// *** CONSTRUCTOR *** /// <summary> /// Initializes a new instance of the Face3D class /// </summary> /// <param name="vertices">Vertices of the 3D face</param> /// <param name="color">Color</param> /// <param name="position">Position</param> /// <param name="masterPosition">Position of the parent 3D cube</param> public Face3D(IEnumerable <Point3D> vertices, Color color, FacePosition position, CubeFlag masterPosition) { this.Vertices = vertices; this.Color = color; this.Position = position; this.MasterPosition = masterPosition; }
/// <summary> /// Constructor with X-, Y- and ZFlag /// </summary> /// <param name="x">Defines the XFlag</param> /// <param name="y">Defines the YFlag</param> /// <param name="z">Defines the ZFlag</param> public CubePosition(CubeFlag x, CubeFlag y, CubeFlag z) { this.X = x; this.Y = y; this.Z = z; }
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 ); } }
/// <summary> /// Returns a CubeFlag which contains all flags which exist in both the first and the second parameter /// </summary> /// <param name="first">Defines the first CubeFlag</param> /// <param name="second">Defines the second CubeFlag</param> /// <returns></returns> public static CubeFlag CommonFlags(CubeFlag first, CubeFlag second) => GetFlags(first).Cast<CubeFlag>().Where(flag => second.HasFlag(flag)).Aggregate(CubeFlag.None, (current, flag) => current | flag);
/// <summary> /// Initializes a new instance of the PatternItem class /// </summary> /// <param name="currPos">Current position</param> /// <param name="currOrientation"> /// Current orientation /// Corner: Correct = 0, Clockwise = 1, Counter-Clockwise = 2 /// Edge: Correct = 0, Flipped = 1 /// Center always 0 /// </param> /// <param name="targetPos">Target position</param> public PatternItem(CubePosition currPos, Orientation currOrientation, CubeFlag targetPos) { this.CurrentPosition = currPos; this.CurrentOrientation = currOrientation; this.TargetPosition = targetPos; }
/// <summary> /// Converts a CubeFlag into a FacePosition /// </summary> /// <param name="cubePos">Defines the CubeFlag to be converted</param> /// <returns></returns> public static FacePosition ToFacePosition(CubeFlag cubePos) { switch (cubePos) { case CubeFlag.TopLayer: return FacePosition.Top; case CubeFlag.BottomLayer: return FacePosition.Bottom; case CubeFlag.LeftSlice: return FacePosition.Left; case CubeFlag.RightSlice: return FacePosition.Right; case CubeFlag.BackSlice: return FacePosition.Back; case CubeFlag.FrontSlice: return FacePosition.Front; default: return FacePosition.None; } }
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 ); } }
/// <summary> /// Returns a CubeFlag which contains all flags of the first parameter except the ones of the second one /// </summary> /// <param name="flags">Defines all flags</param> /// <param name="flagToRemove">Defines the flags to be removed</param> /// <returns></returns> public static CubeFlag RemoveFlag(CubeFlag flags, CubeFlag flagToRemove) => flags &= ~flagToRemove;
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> /// Converts the given CubeFlag into a notation string /// </summary> public static string ToNotationString(CubeFlag flag) { var notation = string.Empty; if (flag.HasFlag(CubeFlag.TopLayer)) notation += "U"; if (flag.HasFlag(CubeFlag.BottomLayer)) notation += "D"; if (flag.HasFlag(CubeFlag.FrontSlice)) notation += "F"; if (flag.HasFlag(CubeFlag.RightSlice)) notation += "R"; if (flag.HasFlag(CubeFlag.BackSlice)) notation += "B"; if (flag.HasFlag(CubeFlag.LeftSlice)) notation += "L"; if (flag.HasFlag(CubeFlag.MiddleSlice)) notation += "S"; if (flag.HasFlag(CubeFlag.MiddleSliceSides)) notation += "M"; if (flag.HasFlag(CubeFlag.MiddleLayer)) notation += "E"; return notation; }
/// <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); }
/// <summary> /// Returns the next flags of the old flags after a layer rotation /// </summary> /// <param name="rotationLayer">Rotation layer</param> /// <param name="direction">Rotation direction</param> /// <returns>Next cube flags</returns> public static CubeFlag NextFlags(CubeFlag flags, CubeFlag rotationLayer, bool direction = true) { var lstFlags = GetFlags(flags); return lstFlags.Cast<CubeFlag>().Aggregate(CubeFlag.None, (current, flag) => current | NextCubeFlag(flag, rotationLayer, direction)); }
private void btnRotate_Click(object sender, EventArgs e) { CubeFlag layer = (CubeFlag)Enum.Parse(typeof(CubeFlag), comboBoxLayers.SelectedItem.ToString()); cubeModel.RotateLayerAnimated(layer, checkBoxDirection.Checked); }
/// <summary> /// Returns the first ZFlag in the given CubeFlag /// </summary> /// <param name="flags">Defines the CubeFlag to be analyzed</param> /// <returns></returns> public static CubeFlag FirstZFlag(CubeFlag flags) => FirstNotInvalidFlag(flags, CubeFlag.XFlags | CubeFlag.YFlags);
private void btnAddToQueue_Click(object sender, EventArgs e) { CubeFlag layer = (CubeFlag)Enum.Parse(typeof(CubeFlag), comboBoxLayers.SelectedItem.ToString()); this.rotations.Add(new LayerMove(layer, checkBoxDirection.Checked)); }
/// <summary> /// Adds n move to the solution and executes it on the Rubik /// </summary> /// <param name="layer">Defines the layer to be rotated</param> /// <param name="direction">Defines the direction of the rotation</param> protected void SolverMove(CubeFlag layer, bool direction) { Rubik.RotateLayer(layer, direction); Algorithm.Moves.Add(new LayerMove(layer, direction)); _movesOfStep.Add(new LayerMove(layer, direction)); }
public F2LPattern(CubeFlag edgeTargetPos, CubeFlag cornerTargetPos, CubeFlag rightSlice, CubeFlag frontSlice) { this.CornerTargetPos = cornerTargetPos; this.EdgeTargetPos = edgeTargetPos; InitPatterns(rightSlice, frontSlice); }
private void InitPatterns(CubeFlag r, CubeFlag f) { var l = CubeFlagService.GetOppositeFlag(r); var b = CubeFlagService.GetOppositeFlag(f); var rIsX = CubeFlagService.IsXFlag(r); // edge orientation changes depending on the target slot var correct = (r == CubeFlag.BackSlice && f == CubeFlag.RightSlice) || (f == CubeFlag.LeftSlice && r == CubeFlag.FrontSlice) ? Orientation.Correct : Orientation.Clockwise; var clockwise = correct == Orientation.Correct ? Orientation.Clockwise : Orientation.Correct; this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Correct, this.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(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.CounterClockwise, this.CornerTargetPos) }), new Algorithm("{0} U {0}' U' {0} U {0}'",CubeFlagService.ToNotationString(r)) }, { new Pattern(new List<PatternItem> { new PatternItem(new CubePosition(this.EdgeTargetPos), Orientation.Correct, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.CounterClockwise, this.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(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Clockwise, this.CornerTargetPos) }), new Algorithm("{0} U' {0}' U {0} U' {0}'",CubeFlagService.ToNotationString(r)) }, { new Pattern(new List<PatternItem> { new PatternItem(new CubePosition(this.EdgeTargetPos), Orientation.Correct, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Clockwise, this.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(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos), Orientation.Clockwise, this.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(this.EdgeTargetPos), Orientation.Correct, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Correct, this.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(this.EdgeTargetPos), Orientation.Correct, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.CornerTargetPos) }), new Algorithm("U' {0} U' {0}' U2 {0} U' {0}'",CubeFlagService.ToNotationString(r)) }, { new Pattern(new List<PatternItem> { new PatternItem(new CubePosition(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.CounterClockwise, this.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(this.EdgeTargetPos), Orientation.Correct, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.CornerTargetPos) }), new Algorithm("U {0} U {0}' U2 {0} U {0}'",CubeFlagService.ToNotationString(r)) }, { new Pattern(new List<PatternItem> { new PatternItem(new CubePosition(this.EdgeTargetPos), Orientation.Clockwise, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.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, this.EdgeTargetPos), new PatternItem(new CubePosition(this.CornerTargetPos &~ CubeFlag.BottomLayer | CubeFlag.TopLayer), Orientation.Clockwise, this.CornerTargetPos) }), new Algorithm("U' {0}' U {0}",CubeFlagService.ToNotationString(f)) } #endregion }; }
/// <summary> /// Constructor with one CubeFlag /// </summary> /// <param name="flags">Defines the CubeFlag where the X-, Y- and ZFlag are filtered out</param> public CubePosition(CubeFlag flags) : this(CubeFlagService.FirstXFlag(flags), CubeFlagService.FirstYFlag(flags), CubeFlagService.FirstZFlag(flags)) { }