private Face3D.FacePosition CubePosToFacePos(Cube3D.RubikPosition position) { switch (position) { case Cube3D.RubikPosition.TopLayer: return(Face3D.FacePosition.Top); case Cube3D.RubikPosition.BottomLayer: return(Face3D.FacePosition.Bottom); case Cube3D.RubikPosition.FrontSlice: return(Face3D.FacePosition.Front); case Cube3D.RubikPosition.BackSlice: return(Face3D.FacePosition.Back); case Cube3D.RubikPosition.LeftSlice: return(Face3D.FacePosition.Left); case Cube3D.RubikPosition.RightSlice: return(Face3D.FacePosition.Right); default: return(Face3D.FacePosition.None); } }
public static FacePosition faceAssocToLayer(Cube3D.RubikPosition Position) { if (Position == Cube3D.RubikPosition.TopLayer) { return(FacePosition.Top); } if (Position == Cube3D.RubikPosition.BottomLayer) { return(FacePosition.Bottom); } if (Position == Cube3D.RubikPosition.LeftSlice) { return(FacePosition.Left); } if (Position == Cube3D.RubikPosition.RightSlice) { return(FacePosition.Right); } if (Position == Cube3D.RubikPosition.FrontSlice) { return(FacePosition.Front); } if (Position == Cube3D.RubikPosition.BackSlice) { return(FacePosition.Back); } return(FacePosition.None); }
public Cube3D.RubikPosition genSideFlags(int i, int j, int k) { Cube3D.RubikPosition rp = Cube3D.RubikPosition.None; switch (i) { case -1: rp |= Cube3D.RubikPosition.LeftSlice; break; case 0: rp |= Cube3D.RubikPosition.MiddleSlice_Sides; break; case 1: rp |= Cube3D.RubikPosition.RightSlice; break; } switch (j) { case -1: rp |= Cube3D.RubikPosition.TopLayer; break; case 0: rp |= Cube3D.RubikPosition.MiddleLayer; break; case 1: rp |= Cube3D.RubikPosition.BottomLayer; break; } switch (k) { case -1: rp |= Cube3D.RubikPosition.FrontSlice; break; case 0: rp |= Cube3D.RubikPosition.MiddleSlice; break; case 1: rp |= Cube3D.RubikPosition.BackSlice; break; } return(rp); }
private Cube3D.RubikPosition GetOppositeFace(Cube3D.RubikPosition layer) { switch (layer) { case Cube3D.RubikPosition.TopLayer: return(Cube3D.RubikPosition.BottomLayer); case Cube3D.RubikPosition.BottomLayer: return(Cube3D.RubikPosition.TopLayer); case Cube3D.RubikPosition.FrontSlice: return(Cube3D.RubikPosition.BackSlice); case Cube3D.RubikPosition.BackSlice: return(Cube3D.RubikPosition.FrontSlice); case Cube3D.RubikPosition.LeftSlice: return(Cube3D.RubikPosition.RightSlice); case Cube3D.RubikPosition.RightSlice: return(Cube3D.RubikPosition.LeftSlice); default: return(Cube3D.RubikPosition.None); } }
public void resetFlagsSync(Cube3D.RubikPosition layer, int target) { RubikCube.LayerRotation[layer] = target; List <Cube3D> affected = RubikCube.cubes.Where(c => c.Position.HasFlag(layer)).ToList(); if (layer == Cube3D.RubikPosition.LeftSlice || layer == Cube3D.RubikPosition.MiddleSlice_Sides || layer == Cube3D.RubikPosition.RightSlice) { affected.ForEach(c => c.Faces.ToList().ForEach(f => f.Rotate(Point3D.RotationType.X, target))); } if (layer == Cube3D.RubikPosition.TopLayer || layer == Cube3D.RubikPosition.MiddleLayer || layer == Cube3D.RubikPosition.BottomLayer) { affected.ForEach(c => c.Faces.ToList().ForEach(f => f.Rotate(Point3D.RotationType.Y, target))); } if (layer == Cube3D.RubikPosition.BackSlice || layer == Cube3D.RubikPosition.MiddleSlice || layer == Cube3D.RubikPosition.FrontSlice) { affected.ForEach(c => c.Faces.ToList().ForEach(f => f.Rotate(Point3D.RotationType.Z, target))); } double ed = ((double)2 / (double)3); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { for (int k = -1; k <= 1; k++) { //Reset Flags but keep Colors Cube3D.RubikPosition flags = RubikCube.genSideFlags(i, j, k);; Cube3D cube = RubikCube.cubes.First(c => (Math.Round(c.Faces.Sum(f => f.Edges.Sum(e => e.X)) / 24, 4) == Math.Round(i * ed, 4)) && (Math.Round(c.Faces.Sum(f => f.Edges.Sum(e => e.Y)) / 24, 4) == Math.Round(j * ed, 4)) && (Math.Round(c.Faces.Sum(f => f.Edges.Sum(e => e.Z)) / 24, 4) == Math.Round(k * ed, 4))); cube.Position = flags; cube.Faces.ToList().ForEach(f => f.MasterPosition = flags); cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round(i * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round((j * ed) - (ed / 2), 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round(k * ed, 4))).Position = Face3D.FacePosition.Top; cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round(i * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round((j * ed) + (ed / 2), 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round(k * ed, 4))).Position = Face3D.FacePosition.Bottom; cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round((i * ed) - (ed / 2), 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round(j * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round(k * ed, 4))).Position = Face3D.FacePosition.Left; cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round((i * ed) + (ed / 2), 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round(j * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round(k * ed, 4))).Position = Face3D.FacePosition.Right; cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round(i * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round(j * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round((k * ed) - (ed / 2), 4))).Position = Face3D.FacePosition.Front; cube.Faces.First(f => (Math.Round(f.Edges.Sum(e => e.X) / 4, 4) == Math.Round(i * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Y) / 4, 4) == Math.Round(j * ed, 4)) && (Math.Round(f.Edges.Sum(e => e.Z) / 4, 4) == Math.Round((k * ed) + (ed / 2), 4))).Position = Face3D.FacePosition.Back; } } } foreach (Cube3D.RubikPosition rp in (Cube3D.RubikPosition[])Enum.GetValues(typeof(Cube3D.RubikPosition))) { RubikCube.LayerRotation[rp] = 0; } Rotating = false; }
public Face3D(IEnumerable <Point3D> edges, Color color, FacePosition position, Cube3D.RubikPosition masterPosition, SelectionMode selection) { Edges = edges; Color = color; Position = position; MasterPosition = masterPosition; Selection = selection; }
public void SolutionMove(Cube3D.RubikPosition layer, bool direction) { Rotate90Sync(layer, direction); if (layer == Cube3D.RubikPosition.TopLayer || layer == Cube3D.RubikPosition.LeftSlice || layer == Cube3D.RubikPosition.FrontSlice) { direction = !direction; } Moves.Add(new LayerMove(layer, direction)); }
public void Rotate90Sync(Cube3D.RubikPosition layer, bool direction) { if (!Rotating) { Rotate90(layer, direction, 1); RubikCube.LayerRotation[rotationLayer] += rotationStep; resetFlags(false); } }
private void button2_Click(object sender, EventArgs e) { groupBox1.Enabled = false; //rotationTicks = 100; Cube3D.RubikPosition layer = (Cube3D.RubikPosition)Enum.Parse(typeof(Cube3D.RubikPosition), comboBox1.Text); bool direction = (button5.Text == "CW"); rubikRenderer.RubikManager.Rotate90(layer, direction, rotationTime); toolStripStatusLabel1.Text = "Rotating " + layer.ToString() + " " + ((button5.Text == "CW") ? "Clockwise" : "Counter-Clockwise"); }
public static IEnumerable <Face3D> genFaces(Cube3D.RubikPosition masterPosition) { return(new Face3D[] { new Face3D(new Point3D[] { new Point3D(-1, 1, -1), new Point3D(1, 1, -1), new Point3D(1, -1, -1), new Point3D(-1, -1, -1) }, Color.Black, Face3D.FacePosition.Front, masterPosition, Face3D.SelectionMode.None), new Face3D(new Point3D[] { new Point3D(-1, 1, 1), new Point3D(1, 1, 1), new Point3D(1, -1, 1), new Point3D(-1, -1, 1) }, Color.Black, Face3D.FacePosition.Back, masterPosition, Face3D.SelectionMode.None), new Face3D(new Point3D[] { new Point3D(-1, -1, -1), new Point3D(1, -1, -1), new Point3D(1, -1, 1), new Point3D(-1, -1, 1) }, Color.Black, Face3D.FacePosition.Top, masterPosition, Face3D.SelectionMode.None), new Face3D(new Point3D[] { new Point3D(-1, 1, -1), new Point3D(1, 1, -1), new Point3D(1, 1, 1), new Point3D(-1, 1, 1) }, Color.Black, Face3D.FacePosition.Bottom, masterPosition, Face3D.SelectionMode.None), new Face3D(new Point3D[] { new Point3D(1, 1, 1), new Point3D(1, 1, -1), new Point3D(1, -1, -1), new Point3D(1, -1, 1) }, Color.Black, Face3D.FacePosition.Right, masterPosition, Face3D.SelectionMode.None), new Face3D(new Point3D[] { new Point3D(-1, 1, 1), new Point3D(-1, 1, -1), new Point3D(-1, -1, -1), new Point3D(-1, -1, 1) }, Color.Black, Face3D.FacePosition.Left, masterPosition, Face3D.SelectionMode.None) }); }
private Tuple <Cube3D.RubikPosition, bool> GetRubikPosition(int layer, int direction, int clockwise) { Cube3D.RubikPosition pos = Cube3D.RubikPosition.None; bool orientation = false; if (direction == 0 && layer == 0) { pos = Cube3D.RubikPosition.LeftSlice; orientation = clockwise > 0; } else if (direction == 0 && layer == 1) { pos = Cube3D.RubikPosition.MiddleSlice_Sides; orientation = clockwise < 0; } else if (direction == 0 && layer == 2) { pos = Cube3D.RubikPosition.RightSlice; orientation = clockwise < 0; } else if (direction == 1 && layer == 0) { pos = Cube3D.RubikPosition.TopLayer; orientation = clockwise > 0; } else if (direction == 1 && layer == 1) { pos = Cube3D.RubikPosition.MiddleLayer; orientation = clockwise < 0; } else if (direction == 1 && layer == 2) { pos = Cube3D.RubikPosition.BottomLayer; orientation = clockwise < 0; } else if (direction == 2 && layer == 0) { pos = Cube3D.RubikPosition.FrontSlice; orientation = clockwise > 0; } else if (direction == 2 && layer == 1) { pos = Cube3D.RubikPosition.MiddleSlice; orientation = clockwise < 0; } else if (direction == 2 && layer == 2) { pos = Cube3D.RubikPosition.BackSlice; orientation = clockwise < 0; } return(new Tuple <Cube3D.RubikPosition, bool>(pos, orientation)); }
public void Rotate90Sync(Cube3D.RubikPosition layer, bool direction) { if (!Rotating) { Rotating = true; if (layer == Cube3D.RubikPosition.TopLayer || layer == Cube3D.RubikPosition.LeftSlice || layer == Cube3D.RubikPosition.FrontSlice) { direction = !direction; } RubikCube.LayerRotation[layer] += (direction) ? -90 : 90; resetFlagsSync(layer, (direction) ? -90 : 90); } }
private void button2_Click(object sender, EventArgs e) { groupBox1.Enabled = false; rotationTicks = 25; Cube3D.RubikPosition layer = (Cube3D.RubikPosition)Enum.Parse(typeof(Cube3D.RubikPosition), comboBox1.Text); bool direction = (button5.Text == "CW"); if (layer == Cube3D.RubikPosition.TopLayer || layer == Cube3D.RubikPosition.LeftSlice || layer == Cube3D.RubikPosition.FrontSlice) { direction = !direction; } rubikManager.Rotate90(layer, direction, rotationTicks); toolStripStatusLabel1.Text = "Rotating " + layer.ToString() + " " + ((button5.Text == "CW") ? "Clockwise" : "Counter-Clockwise"); }
public static LayerMove Parse(string notation) { string layer = notation[0].ToString(); Cube3D.RubikPosition rotationLayer = Cube3D.RubikPosition.None; switch (layer) { case "R": rotationLayer = Cube3D.RubikPosition.RightSlice; break; case "L": rotationLayer = Cube3D.RubikPosition.LeftSlice; break; case "U": rotationLayer = Cube3D.RubikPosition.TopLayer; break; case "D": rotationLayer = Cube3D.RubikPosition.BottomLayer; break; case "F": rotationLayer = Cube3D.RubikPosition.FrontSlice; break; case "B": rotationLayer = Cube3D.RubikPosition.BackSlice; break; case "M": rotationLayer = Cube3D.RubikPosition.MiddleSlice_Sides; break; case "E": rotationLayer = Cube3D.RubikPosition.MiddleLayer; break; case "S": rotationLayer = Cube3D.RubikPosition.MiddleSlice; break; } bool direction = notation.Length == 1; return(new LayerMove(rotationLayer, direction)); }
public void setFaceSelection(Cube3D.RubikPosition affected, Face3D.FacePosition face, Face3D.SelectionMode selection) { RubikCube.cubes.Where(c => c.Position.HasFlag(affected)).ToList().ForEach(c => c.Faces.Where(f => f.Position == face).ToList().ForEach(f => { if (f.Selection.HasFlag(Face3D.SelectionMode.Possible)) { f.Selection = selection | Face3D.SelectionMode.Possible; } else if (f.Selection.HasFlag(Face3D.SelectionMode.NotPossible)) { f.Selection = selection | Face3D.SelectionMode.NotPossible; } else { f.Selection = selection; } })); }
public void Rotate90(Cube3D.RubikPosition layer, bool direction, int steps) { if (!Rotating) { Rotating = true; rotationLayer = layer; rotationStep = (double)90 / (double)steps; if (direction) { rotationStep *= (-1); } rotationTarget = 90; if (direction) { rotationTarget = -90; } } }
private Cube3D.RubikPosition GetOppositeLayer(Cube3D.RubikPosition position) { switch (position) { case Cube3D.RubikPosition.FrontSlice: return(Cube3D.RubikPosition.BackSlice); case Cube3D.RubikPosition.BackSlice: return(Cube3D.RubikPosition.FrontSlice); case Cube3D.RubikPosition.LeftSlice: return(Cube3D.RubikPosition.RightSlice); case Cube3D.RubikPosition.RightSlice: return(Cube3D.RubikPosition.LeftSlice); default: return(Cube3D.RubikPosition.None); } }
private void listBox1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) { //rotationTicks = 25; if (listBox1.SelectedIndex == -1 & listBox1.Items.Count > 0) { listBox1.SelectedIndex = 0; } if (listBox1.Items.Count > 0) { string layerString = listBox1.SelectedItem.ToString().Split(new Char[] { Convert.ToChar(" ") })[0]; Cube3D.RubikPosition layer = (Cube3D.RubikPosition)Enum.Parse(typeof(Cube3D.RubikPosition), layerString); string directionString = listBox1.SelectedItem.ToString().Split(new Char[] { Convert.ToChar(" ") })[1]; bool direction = (directionString == "Clockwise") ? true : false; rubikRenderer.RubikManager.Rotate90(layer, direction, rotationTime); } } }
public void Rotate90(Cube3D.RubikPosition layer, bool direction, int rotationTime) { if (!Rotating) { Rotating = true; rotationLayer = layer; this.rotationTime = rotationTime; if (layer == Cube3D.RubikPosition.TopLayer || layer == Cube3D.RubikPosition.LeftSlice || layer == Cube3D.RubikPosition.FrontSlice) { direction = !direction; } this.rotationDirection = direction; if (direction) { rotationStep *= (-1); } rotationTarget = 90; if (direction) { rotationTarget = -90; } } }
public bool CanSolve() { RubikManager oldManager = Manager.Clone(); //check colors bool correctColors = standardCube.RubikCube.cubes.Count(sc => Manager.RubikCube.cubes .Where(c => ScrambledEquals(c.Colors, sc.Colors)).Count() == 1) == Manager.RubikCube.cubes.Count(); //return false, if there are invalid cube colors if (!correctColors) { return(false); } Solve(false); //check if all the cube faces are solved Cube3D.RubikPosition layers = Cube3D.RubikPosition.TopLayer | Cube3D.RubikPosition.BottomLayer | Cube3D.RubikPosition.RightSlice | Cube3D.RubikPosition.LeftSlice | Cube3D.RubikPosition.FrontSlice | Cube3D.RubikPosition.BackSlice; foreach (Cube3D.RubikPosition l in GetFlags(layers)) { Face3D.FacePosition facePos = CubePosToFacePos(l); if (facePos != Face3D.FacePosition.None) { Cube3D.RubikPosition centerPos = Manager.RubikCube.cubes.First(c => Cube3D.isCenter(c.Position) && c.Position.HasFlag(l)).Position; Color faceColor = Manager.getFaceColor(centerPos, facePos); bool faceNotSolved = Manager.RubikCube.cubes.Count(c => c.Position.HasFlag(l) && c.Faces.First(f => f.Position == facePos).Color == faceColor) != 9; if (faceNotSolved) { return(false); } } } Manager = oldManager; return(true); }
private void CompleteMiddleLayer() { //Step 1: Get the color of the bottom and top layer Color bottomColor = Manager.getFaceColor(Cube3D.RubikPosition.BottomLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Bottom); Color topColor = Manager.getFaceColor(Cube3D.RubikPosition.TopLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Top); //Step 2: Get the egdes of the middle layer IEnumerable <Cube3D> middleEdges = Manager.RubikCube.cubes.Where(c => Cube3D.isEdge(c.Position)).Where(c => c.Colors.Count(co => co == bottomColor || co == topColor) == 0); List <Face3D> coloredFaces = new List <Face3D>(); Manager.RubikCube.cubes.Where(cu => Cube3D.isCenter(cu.Position)).ToList().ForEach(cu => coloredFaces.Add(cu.Faces.First(f => f.Color != Color.Black).Clone())); IEnumerable <Cube3D> solvedMiddleEdges = middleEdges.Where(mE => mE.Faces.Count(f => coloredFaces.Count(cf => cf.Color == f.Color && cf.Position == f.Position) == 1) == 2); while (solvedMiddleEdges.Count() < 4) { IEnumerable <Cube3D> unsolvedMiddleEdges = middleEdges.Except(solvedMiddleEdges); Cube3D c = (unsolvedMiddleEdges.FirstOrDefault(cu => !cu.Position.HasFlag(Cube3D.RubikPosition.MiddleLayer)) != null) ? unsolvedMiddleEdges.FirstOrDefault(cu => !cu.Position.HasFlag(Cube3D.RubikPosition.MiddleLayer)) : unsolvedMiddleEdges.First(); //Rotate to top layer if (!c.Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Face3D frontFace = c.Faces.First(f => f.Color != Color.Black); Cube3D.RubikPosition frontSlice = FacePosToCubePos(frontFace.Position); Face3D face = c.Faces.First(f => f.Color != Color.Black && f.Color != frontFace.Color); Cube3D.RubikPosition slice = FacePosToCubePos(face.Position); Manager.SolutionMove(slice, true); if (RefreshCube(c).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(slice, false); //Algorithm to the right: U R Ui Ri Ui Fi U F Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(slice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(slice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(frontSlice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(frontSlice, true); } else { Manager.SolutionMove(slice, false); //Algorithm to the left: Ui Li U L U F Ui Fi Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(slice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(slice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(frontSlice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(frontSlice, false); } } //Rotate to start position for the algorithm IEnumerable <Cube3D> middles = Manager.RubikCube.cubes.Where(cu => Cube3D.isCenter(cu.Position)).Where(m => m.Colors.First(co => co != Color.Black) == RefreshCube(c).Faces.First(f => f.Color != Color.Black && f.Position != Face3D.FacePosition.Top).Color&& RemoveFlag(m.Position, Cube3D.RubikPosition.MiddleLayer) == RemoveFlag(RefreshCube(c).Position, Cube3D.RubikPosition.TopLayer)); while (middles.Count() < 1) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); middles = Manager.RubikCube.cubes.Where(cu => Cube3D.isCenter(cu.Position)).Where(m => m.Colors.First(co => co != Color.Black) == RefreshCube(c).Faces.First(f => f.Color != Color.Black && f.Position != Face3D.FacePosition.Top).Color&& RemoveFlag(m.Position, Cube3D.RubikPosition.MiddleLayer) == RemoveFlag(RefreshCube(c).Position, Cube3D.RubikPosition.TopLayer)); } //Rotate to target position Face3D frontFac = RefreshCube(c).Faces.First(f => f.Color != Color.Black && f.Position != Face3D.FacePosition.Top); Cube3D.RubikPosition frontSlic = FacePosToCubePos(frontFac.Position); Cube3D.RubikPosition slic = Cube3D.RubikPosition.None; foreach (Cube3D.RubikPosition p in GetFlags(GetTargetPosition(c))) { if (p != Cube3D.RubikPosition.MiddleLayer && p != frontSlic) { slic |= p; } } Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); if (!RefreshCube(c).Position.HasFlag(slic)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); //Algorithm to the right: U R Ui Ri Ui Fi U F Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(slic, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(slic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(frontSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(frontSlic, true); } else { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); //Algorithm to the left: Ui Li U L U F Ui Fi Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(slic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(slic, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(frontSlic, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(frontSlic, false); } solvedMiddleEdges = middleEdges.Where(mE => RefreshCube(mE).Faces.Count(f => coloredFaces.Count(cf => cf.Color == f.Color && cf.Position == f.Position) == 1) == 2); } }
public LayerMove(Cube3D.RubikPosition layer, Boolean direction) { Layer = layer; Direction = direction; }
private void SolveCrossTopLayer() { //Step 1: Get the color of the top layer to start with cross on the last layer Color topColor = Manager.getFaceColor(Cube3D.RubikPosition.TopLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Top); //Step 2: Get edges with the color of the top face IEnumerable <Cube3D> topEdges = Manager.RubikCube.cubes.Where(c => Cube3D.isEdge(c.Position)).Where(c => c.Position.HasFlag(Cube3D.RubikPosition.TopLayer)); //Check if the cube is insoluble if (topEdges.Where(tE => tE.Faces.First(f => f.Position == Face3D.FacePosition.Top).Color == topColor).Count() % 2 != 0) { return; } IEnumerable <Cube3D> correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == Face3D.FacePosition.Top).Color == topColor); Algorithm solveTopCrossAlgorithmI = new Algorithm("F R U Ri Ui Fi"); Algorithm solveTopCrossAlgorithmII = new Algorithm("F Si R U Ri Ui Fi S"); //Step 3: Solve the cross on the top layer if (CountEdgesWithCorrectOrientation(Manager) == 0) { solveTopCrossAlgorithmI.Moves.ForEach(m => Manager.SolutionMove(m.Layer, m.Direction)); topEdges = topEdges.Select(c => RefreshCube(c)); correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == Face3D.FacePosition.Top).Color == topColor); } if (CountEdgesWithCorrectOrientation(Manager) == 2) { Cube3D firstCorrect = correctEdges.First(); Cube3D secondCorrect = correctEdges.First(f => f != firstCorrect); bool opposite = false; foreach (Cube3D.RubikPosition flag in GetFlags(firstCorrect.Position)) { Cube3D.RubikPosition pos = GetOppositeLayer(flag); if (secondCorrect.Position.HasFlag(pos) && pos != Cube3D.RubikPosition.None) { opposite = true; break; } } if (opposite) { while (correctEdges.Select(c => RefreshCube(c)).Count(c => c.Position.HasFlag(Cube3D.RubikPosition.RightSlice)) != 1) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } solveTopCrossAlgorithmI.Moves.ForEach(m => Manager.SolutionMove(m.Layer, m.Direction)); } else { while (correctEdges.Select(c => RefreshCube(c)).Count(c => c.Position.HasFlag(Cube3D.RubikPosition.RightSlice) || c.Position.HasFlag(Cube3D.RubikPosition.FrontSlice)) != 2) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } solveTopCrossAlgorithmII.Moves.ForEach(m => Manager.SolutionMove(m.Layer, m.Direction)); } } //Step 4: Move the edges of the cross to their target positions IEnumerable <Cube3D> CorrectEdges = topEdges.Where(c => c.Position == GetTargetPosition(c)); while (CorrectEdges.Count() < 2) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); CorrectEdges = CorrectEdges.Select(cE => RefreshCube(cE)); } while (topEdges.Where(c => c.Position == GetTargetPosition(c)).Count() < 4) { CorrectEdges = topEdges.Where(c => c.Position == GetTargetPosition(c)); while (CorrectEdges.Count() < 2) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); CorrectEdges = CorrectEdges.Select(cE => RefreshCube(cE)); } Cube3D.RubikPosition rightSlice = FacePosToCubePos(CorrectEdges.First().Faces .First(f => f.Color != topColor && f.Color != Color.Black).Position); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); CorrectEdges = CorrectEdges.Select(cE => RefreshCube(cE)); if (CorrectEdges.Count(c => c.Position.HasFlag(rightSlice)) == 0) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } else { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); CorrectEdges = CorrectEdges.Select(cE => RefreshCube(cE)); rightSlice = FacePosToCubePos(CorrectEdges.First(cE => !cE.Position.HasFlag(rightSlice)).Faces .First(f => f.Color != topColor && f.Color != Color.Black).Position); } //Algorithm: R U Ri U R U U Ri Manager.SolutionMove(rightSlice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(rightSlice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(rightSlice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(rightSlice, false); topEdges = topEdges.Select(tE => RefreshCube(tE)); while (CorrectEdges.Count() < 2) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); CorrectEdges = CorrectEdges.Select(cE => RefreshCube(cE)); } } }
private void Form1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (oldSelection.cubePos == Cube3D.RubikPosition.None || oldSelection.facePos == Face3D.FacePosition.None) { if (currentSelection.cubePos == Cube3D.RubikPosition.None || currentSelection.facePos == Face3D.FacePosition.None) { rubikManager.RubikCube.cubes.ForEach(c => c.Faces.ToList().ForEach(f => f.Selection = Face3D.SelectionMode.None)); oldSelection = new RubikManager.PositionSpec() { cubePos = Cube3D.RubikPosition.None, facePos = Face3D.FacePosition.None }; currentSelection = new RubikManager.PositionSpec() { cubePos = Cube3D.RubikPosition.None, facePos = Face3D.FacePosition.None }; } else { if (!Cube3D.isCorner(currentSelection.cubePos)) { oldSelection = currentSelection; rubikManager.RubikCube.cubes.ForEach(c => c.Faces.ToList().ForEach(f => { if (currentSelection.cubePos != c.Position && !Cube3D.isCenter(c.Position) && currentSelection.facePos == f.Position) { Cube3D.RubikPosition assocLayer = Face3D.layerAssocToFace(currentSelection.facePos); Cube3D.RubikPosition commonLayer = Cube3D.getCommonLayer(currentSelection.cubePos, c.Position, assocLayer); if (commonLayer != Cube3D.RubikPosition.None && c.Position.HasFlag(commonLayer)) { f.Selection |= Face3D.SelectionMode.Possible; } else { f.Selection |= Face3D.SelectionMode.NotPossible; } } else { f.Selection |= Face3D.SelectionMode.NotPossible; } })); toolStripStatusLabel1.Text = "First selection: [" + currentSelection.cubePos.ToString() + "] | " + currentSelection.facePos.ToString();; } else { rubikManager.RubikCube.cubes.ForEach(c => c.Faces.ToList().ForEach(f => f.Selection = Face3D.SelectionMode.None)); toolStripStatusLabel1.Text = "Error: Invalid first selection, must not be a corner"; } } } else { if (currentSelection.cubePos == Cube3D.RubikPosition.None || currentSelection.facePos == Face3D.FacePosition.None) { toolStripStatusLabel1.Text = "Ready"; } else { if (currentSelection.cubePos != oldSelection.cubePos) { if (!Cube3D.isCenter(currentSelection.cubePos)) { if (oldSelection.facePos == currentSelection.facePos) { Cube3D.RubikPosition assocLayer = Face3D.layerAssocToFace(oldSelection.facePos); Cube3D.RubikPosition commonLayer = Cube3D.getCommonLayer(oldSelection.cubePos, currentSelection.cubePos, assocLayer); Boolean direction = true; if (commonLayer == Cube3D.RubikPosition.TopLayer || commonLayer == Cube3D.RubikPosition.MiddleLayer || commonLayer == Cube3D.RubikPosition.BottomLayer) { if (((oldSelection.facePos == Face3D.FacePosition.Front) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.LeftSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Right) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.FrontSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Back) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.RightSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Left) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.BackSlice))) { direction = false; } } if (commonLayer == Cube3D.RubikPosition.LeftSlice || commonLayer == Cube3D.RubikPosition.MiddleSlice_Sides || commonLayer == Cube3D.RubikPosition.RightSlice) { if (((oldSelection.facePos == Face3D.FacePosition.Top) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.FrontSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Front) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.BottomLayer)) || ((oldSelection.facePos == Face3D.FacePosition.Bottom) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.BackSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Back) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.TopLayer))) { direction = false; } } if (commonLayer == Cube3D.RubikPosition.BackSlice || commonLayer == Cube3D.RubikPosition.MiddleSlice || commonLayer == Cube3D.RubikPosition.FrontSlice) { if (((oldSelection.facePos == Face3D.FacePosition.Top) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.RightSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Right) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.BottomLayer)) || ((oldSelection.facePos == Face3D.FacePosition.Bottom) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.LeftSlice)) || ((oldSelection.facePos == Face3D.FacePosition.Left) && currentSelection.cubePos.HasFlag(Cube3D.RubikPosition.TopLayer))) { direction = false; } } if (commonLayer != Cube3D.RubikPosition.None) { if (groupBox1.Enabled) { groupBox1.Enabled = false; rotationTicks = 25; rubikManager.Rotate90(commonLayer, direction, rotationTicks); comboBox1.Text = commonLayer.ToString(); toolStripStatusLabel1.Text = "Rotating " + commonLayer.ToString() + " " + ((direction) ? "Clockwise" : "Counter-Clockwise"); } } else { toolStripStatusLabel1.Text = "Error: Invalid second selection, does not specify distinct layer"; } } else { toolStripStatusLabel1.Text = "Error: Invalid second selection, must match orientation of first selection"; } } else { toolStripStatusLabel1.Text = "Error: Invalid second selection, must not be a center"; } } else { toolStripStatusLabel1.Text = "Error: Invalid second selection, must not be first selection"; } } rubikManager.RubikCube.cubes.ForEach(c => c.Faces.ToList().ForEach(f => f.Selection = Face3D.SelectionMode.None)); oldSelection = new RubikManager.PositionSpec() { cubePos = Cube3D.RubikPosition.None, facePos = Face3D.FacePosition.None }; currentSelection = new RubikManager.PositionSpec() { cubePos = Cube3D.RubikPosition.None, facePos = Face3D.FacePosition.None }; } } }
private void CompleteLastLayer() { //Step 1: Get the color of the top layer to start with cross on the last layer Color topColor = Manager.getFaceColor(Cube3D.RubikPosition.TopLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Top); //Step 2: Get edges with the color of the top face IEnumerable <Cube3D> topCorners = Manager.RubikCube.cubes.Where(c => Cube3D.isCorner(c.Position)).Where(c => c.Position.HasFlag(Cube3D.RubikPosition.TopLayer)); //Step 3: Bring corners to their target position while (topCorners.Where(c => c.Position == GetTargetPosition(c)).Count() < 4) { IEnumerable <Cube3D> correctCorners = topCorners.Where(c => c.Position == GetTargetPosition(c)); Cube3D.RubikPosition rightSlice; if (correctCorners.Count() != 0) { Cube3D firstCube = correctCorners.First(); Face3D rightFace = firstCube.Faces.First(f => f.Color != Color.Black && f.Position != Face3D.FacePosition.Top); rightSlice = FacePosToCubePos(rightFace.Position); Manager.SolutionMove(rightSlice, true); if (RefreshCube(firstCube).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(rightSlice, false); } else { Manager.SolutionMove(rightSlice, false); rightSlice = FacePosToCubePos(firstCube.Faces.First(f => f.Color != rightFace.Color && f.Color != Color.Black && f.Position != Face3D.FacePosition.Top).Position); } } else { rightSlice = Cube3D.RubikPosition.RightSlice; } Cube3D.RubikPosition leftSlice = GetOppositeFace(rightSlice); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(rightSlice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(leftSlice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(rightSlice, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(leftSlice, true); topCorners = topCorners.Select(tC => RefreshCube(tC)); correctCorners = correctCorners.Select(cC => RefreshCube(cC)); } //Step 4: Orientation of the corners on the top layer topCorners = topCorners.Select(tC => RefreshCube(tC)); Face3D rightFac = RefreshCube(topCorners.First()).Faces.First(f => f.Color != Color.Black && f.Position != Face3D.FacePosition.Top); Cube3D.RubikPosition rightSlic = FacePosToCubePos(rightFac.Position); Manager.SolutionMove(rightSlic, true); if (RefreshCube(topCorners.First()).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(rightSlic, false); } else { Manager.SolutionMove(rightSlic, false); rightSlic = FacePosToCubePos(topCorners.First().Faces.First(f => f.Color != rightFac.Color && f.Color != Color.Black && f.Position != Face3D.FacePosition.Top).Position); } foreach (Cube3D c in topCorners) { while (!RefreshCube(c).Position.HasFlag(rightSlic)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } Manager.SolutionMove(rightSlic, true); if (RefreshCube(c).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(rightSlic, false); } else { Manager.SolutionMove(rightSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } //Algorithm: Ri Di R D while (RefreshCube(c).Faces.First(f => f.Position == Face3D.FacePosition.Top).Color != topColor) { Manager.SolutionMove(rightSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.BottomLayer, false); Manager.SolutionMove(rightSlic, true); Manager.SolutionMove(Cube3D.RubikPosition.BottomLayer, true); } } topCorners = topCorners.Select(tC => RefreshCube(tC)); while (topCorners.Count(tC => tC.Position == GetTargetPosition(tC)) != 4) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } }
private Cube3D.RubikPosition RemoveFlag(Cube3D.RubikPosition oldPosition, Cube3D.RubikPosition item) { return(oldPosition &= ~item); }
public void setFaceColor(Cube3D.RubikPosition affected, Face3D.FacePosition face, Color color) { RubikCube.cubes.Where(c => c.Position.HasFlag(affected)).ToList().ForEach(c => c.Faces.Where(f => f.Position == face).ToList().ForEach(f => f.Color = color)); }
private void CompleteFirstLayer() { //Step 1: Get the color of the bottom layer Color bottomColor = Manager.getFaceColor(Cube3D.RubikPosition.BottomLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Bottom); //Step 2: Get the corners with target position on bottom layer IEnumerable <Cube3D> bottomCorners = Manager.RubikCube.cubes.Where(c => Cube3D.isCorner(c.Position) && GetTargetPosition(c).HasFlag(Cube3D.RubikPosition.BottomLayer)); IEnumerable <Cube3D> solvedBottomCorners = bottomCorners.Where(bC => bC.Position == GetTargetPosition(bC) && bC.Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom); //Step 3: Solve incorrect edges while (solvedBottomCorners.Count() < 4) { IEnumerable <Cube3D> unsolvedBottomCorners = bottomCorners.Except(solvedBottomCorners); Cube3D c = (unsolvedBottomCorners.FirstOrDefault(bC => bC.Position.HasFlag(Cube3D.RubikPosition.TopLayer)) != null) ? unsolvedBottomCorners.FirstOrDefault(bC => bC.Position.HasFlag(Cube3D.RubikPosition.TopLayer)) : unsolvedBottomCorners.First(); if (c.Position != GetTargetPosition(c)) { //Rotate to top layer if (c.Position.HasFlag(Cube3D.RubikPosition.BottomLayer)) { Face3D leftFace = RefreshCube(c).Faces.First(f => f.Position != Face3D.FacePosition.Bottom && f.Color != Color.Black); Cube3D.RubikPosition leftSlice = FacePosToCubePos(leftFace.Position); Manager.SolutionMove(leftSlice, false); if (RefreshCube(c).Position.HasFlag(Cube3D.RubikPosition.BottomLayer)) { Manager.SolutionMove(leftSlice, true); leftFace = RefreshCube(c).Faces.First(f => f.Position != Face3D.FacePosition.Bottom && f.Color != leftFace.Color && f.Color != Color.Black); leftSlice = FacePosToCubePos(leftFace.Position); Manager.SolutionMove(leftSlice, false); } Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(leftSlice, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } //Rotate over target position Cube3D.RubikPosition targetPos = Cube3D.RubikPosition.None; foreach (Cube3D.RubikPosition p in GetFlags(GetTargetPosition(c))) { if (p != Cube3D.RubikPosition.BottomLayer) { targetPos |= p; } } while (!RefreshCube(c).Position.HasFlag(targetPos)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } } //Rotate to target position with the algorithm: Li Ui L U Face3D leftFac = RefreshCube(c).Faces.First(f => f.Position != Face3D.FacePosition.Top && f.Position != Face3D.FacePosition.Bottom && f.Color != Color.Black); Cube3D.RubikPosition leftSlic = FacePosToCubePos(leftFac.Position); Manager.SolutionMove(leftSlic, false); if (!RefreshCube(c).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(leftSlic, true); leftFac = RefreshCube(c).Faces.First(f => f.Position != Face3D.FacePosition.Top && f.Position != Face3D.FacePosition.Bottom && f.Color != leftFac.Color && f.Color != Color.Black); leftSlic = FacePosToCubePos(leftFac.Position); } else { Manager.SolutionMove(leftSlic, true); } while (RefreshCube(c).Faces.First(f => f.Color == bottomColor).Position != Face3D.FacePosition.Bottom) { if (RefreshCube(c).Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Top) { Manager.SolutionMove(leftSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(leftSlic, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } else { Face3D frontFac = RefreshCube(c).Faces.First(f => f.Position != Face3D.FacePosition.Top && f.Position != Face3D.FacePosition.Bottom && f.Color != Color.Black && f.Position != CubePosToFacePos(leftSlic)); if (RefreshCube(c).Faces.First(f => f.Color == bottomColor).Position == frontFac.Position && !RefreshCube(c).Position.HasFlag(Cube3D.RubikPosition.BottomLayer)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(leftSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(leftSlic, true); } else { Manager.SolutionMove(leftSlic, false); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, false); Manager.SolutionMove(leftSlic, true); Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } } } solvedBottomCorners = bottomCorners.Where(bC => RefreshCube(bC).Position == GetTargetPosition(bC) && RefreshCube(bC).Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom); } }
public Color getFaceColor(Cube3D.RubikPosition position, Face3D.FacePosition face) { return(RubikCube.cubes.First(c => c.Position.HasFlag(position)).Faces.First(f => f.Position == face).Color); }
//Solve the first cross on the bottom layer private void SolveFirstCross() { //Step 1: Get color of the bottom layer Color bottomColor = Manager.getFaceColor(Cube3D.RubikPosition.BottomLayer | Cube3D.RubikPosition.MiddleSlice_Sides | Cube3D.RubikPosition.MiddleSlice, Face3D.FacePosition.Bottom); //Step 2: Get the edges with target position on the bottom layer IEnumerable <Cube3D> bottomEdges = Manager.RubikCube.cubes.Where(c => Cube3D.isEdge(c.Position) && GetTargetPosition(c).HasFlag(Cube3D.RubikPosition.BottomLayer)); //Step 3: Rotate a correct orientated edge of the bottom layer to target position IEnumerable <Cube3D> solvedBottomEdges = bottomEdges.Where(bE => bE.Position == GetTargetPosition(bE) && bE.Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom); if (bottomEdges.Count(bE => bE.Position.HasFlag(Cube3D.RubikPosition.BottomLayer) && bE.Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom) > 0) { while (solvedBottomEdges.Count() < 1) { Manager.SolutionMove(Cube3D.RubikPosition.BottomLayer, true); solvedBottomEdges = bottomEdges.Where(bE => RefreshCube(bE).Position == GetTargetPosition(RefreshCube(bE)) && RefreshCube(bE).Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom); } } //Step 4: Solve incorrect edges of the bottom layer while (solvedBottomEdges.Count() < 4) { IEnumerable <Cube3D> unsolvedBottomEdges = bottomEdges.Except(solvedBottomEdges); Cube3D e = (unsolvedBottomEdges.FirstOrDefault(c => c.Position.HasFlag(Cube3D.RubikPosition.TopLayer)) != null) ? unsolvedBottomEdges.FirstOrDefault(c => c.Position.HasFlag(Cube3D.RubikPosition.TopLayer)) : unsolvedBottomEdges.First(); Color secondColor = e.Colors.First(co => co != bottomColor && co != Color.Black); if (e.Position != GetTargetPosition(e)) { //Rotate to top layer Cube3D.RubikPosition layer = FacePosToCubePos(e.Faces.First(f => (f.Color == bottomColor || f.Color == secondColor) && f.Position != Face3D.FacePosition.Top && f.Position != Face3D.FacePosition.Bottom).Position); Cube3D.RubikPosition targetLayer = FacePosToCubePos(standardCube.RubikCube.cubes.First(cu => ScrambledEquals(cu.Colors, e.Colors)) .Faces.First(f => f.Color == secondColor).Position); if (e.Position.HasFlag(Cube3D.RubikPosition.MiddleLayer)) { if (layer == targetLayer) { while (!RefreshCube(e).Position.HasFlag(Cube3D.RubikPosition.BottomLayer)) { Manager.SolutionMove(layer, true); } } else { Manager.SolutionMove(layer, true); if (RefreshCube(e).Position.HasFlag(Cube3D.RubikPosition.TopLayer)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(layer, false); } else { for (int i = 0; i < 2; i++) { Manager.SolutionMove(layer, true); } Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); Manager.SolutionMove(layer, true); } } } if (e.Position.HasFlag(Cube3D.RubikPosition.BottomLayer)) { for (int i = 0; i < 2; i++) { Manager.SolutionMove(layer, true); } } //Rotate over target position while (!RefreshCube(e).Position.HasFlag(targetLayer)) { Manager.SolutionMove(Cube3D.RubikPosition.TopLayer, true); } //Rotate to target position for (int i = 0; i < 2; i++) { Manager.SolutionMove(targetLayer, true); } } //Flip the incorrect orientated edges with the algorithm: Fi D Ri Di if (e.Faces.First(f => f.Position == Face3D.FacePosition.Bottom).Color != bottomColor) { Cube3D.RubikPosition frontLayer = FacePosToCubePos(RefreshCube(e).Faces.First(f => f.Color == bottomColor).Position); Manager.SolutionMove(frontLayer, false); Manager.SolutionMove(Cube3D.RubikPosition.BottomLayer, true); Cube3D.RubikPosition rightSlice = FacePosToCubePos(RefreshCube(e).Faces.First(f => f.Color == secondColor).Position); Manager.SolutionMove(rightSlice, false); Manager.SolutionMove(Cube3D.RubikPosition.BottomLayer, false); } solvedBottomEdges = bottomEdges.Where(bE => RefreshCube(bE).Position == GetTargetPosition(RefreshCube(bE)) && RefreshCube(bE).Faces.First(f => f.Color == bottomColor).Position == Face3D.FacePosition.Bottom); } }