private void FormCross() { while (!RubixCubeStatusEvaluator.CrossIsFormed(_cube, Side.Front)) { var backEdges = _cube.GetBackEdges().Where(b => b.HasColour(Colour.White)).ToList(); if (backEdges.Any()) { var backEdge = backEdges.First(); SolveBackEdge(backEdge); } var frontEdge = GetAnIncorrectFrontEdge(); if (frontEdge != null) { RotateFrontEdgeToBack(frontEdge); } var sideEdges = _cube.GetSideEdges().Where(b => b.HasColour(Colour.White)).ToList(); if (sideEdges.Any()) { var sideEdge = sideEdges.First(); RotateSideEdgeToBack(sideEdge); } } }
private void FormYellowCross() { while (!RubixCubeStatusEvaluator.CrossFaceIsFormed(_cube, Side.Back)) { if (!CrossIsPartiallySolved()) { // Any rotation is fine here (providing the face matches the side) PerformFruRufRotations(Side.Right, Side.Bottom); } var crossBlocks = _cube.GetBackFaceCrossBlocks().ToList(); if (CrossIsCurrentlyAnArrow(crossBlocks)) { var sides = GetIncorrectCrossBlockSides(crossBlocks); var faceToRotate = GetFaceToRotate(sides); var sideToRotate = GetSideToRotate(faceToRotate); PerformFruRufRotations(faceToRotate, sideToRotate); } crossBlocks = _cube.GetBackFaceCrossBlocks().ToList(); if (CrossIsCurrentlyALine(crossBlocks)) { var faceToRotate = GetIncorrectCrossBlockSides(crossBlocks).First(); var sideToRotate = GetSideToRotate(faceToRotate); PerformFruRufRotations(faceToRotate, sideToRotate); } } }
private void RotateIncorrectSideEdgeToBack() { var incorrectEdge = _cube.GetSideEdges().First(b => !RubixCubeStatusEvaluator.EdgeIsInCorrectPosition(b)); var sides = incorrectEdge.GetNonNullSides(); if (sides.Contains(Side.Top) && sides.Contains(Side.Left)) { PerformRightSwitch(Side.Left, Side.Top); } if (sides.Contains(Side.Right) && sides.Contains(Side.Top)) { PerformRightSwitch(Side.Top, Side.Right); } if (sides.Contains(Side.Bottom) && sides.Contains(Side.Right)) { PerformRightSwitch(Side.Right, Side.Bottom); } if (sides.Contains(Side.Left) && sides.Contains(Side.Bottom)) { PerformRightSwitch(Side.Bottom, Side.Left); } }
private Block?GetAnIncorrectFrontEdge() { var blocks = _cube.GetFrontEdges().Where(b => b.HasColour(Colour.White)); foreach (var block in blocks) { var nonFrontSide = GetSideToRotate(block, Side.Front); if (block.Front != Colour.White || !RubixCubeStatusEvaluator.SideIsCorrectColour(nonFrontSide, block)) { return(block); } } return(null); }
private Block GetSolvableEdge() { var backEdges = _cube.GetBackEdges().Where(b => !b.HasColour(Colour.Yellow)); foreach (var block in backEdges) { var sides = block.GetNonNullSides(); var nonBackSide = sides.Single(side => side != Side.Back); if (RubixCubeStatusEvaluator.SideIsCorrectColour(nonBackSide, block)) { return(block); } } return(null); }
public void Solve() { while (!RubixCubeStatusEvaluator.SecondLayerIsSolved(_cube)) { var backEdges = _cube.GetBackEdges(); if (backEdges.All(b => b.HasColour(Colour.Yellow))) { RotateIncorrectSideEdgeToBack(); } while (GetSolvableEdge() == null) { _cube.RotateClockwise(Side.Back); } SolveBackEdge(GetSolvableEdge()); } }
private void SolveCorners() { while (!RubixCubeStatusEvaluator.FirstLayerIsSolved(_cube)) { var frontCorners = _cube.GetFrontCornerBlocks().Where(c => !c.IsCorrectlyPositioned()).ToList(); if (frontCorners.Select(c => c.Block.HasColour(Colour.White)).Any()) { var corner = frontCorners.First(); RotateCornerToBack(corner); } var backCorners = _cube.GetBackCornerBlocks().Where(c => c.IsCorrectlyPositioned()).ToList(); if (backCorners.Select(c => c.Block.HasColour(Colour.White)).Any()) { var corner = backCorners.First(); RotateCornerToFront(corner); } else { _cube.RotateClockwise(Side.Back); } } }
private void ReorganiseMiddleEdges() { while (!RubixCubeStatusEvaluator.CrossIsFormed(_cube, Side.Back)) { var middleEdges = GetMiddleEdges(); var numIncorrectEdges = middleEdges.Count(b => b.isCorrect); if (numIncorrectEdges == 2) { var firstIncorrectEdge = middleEdges.First(b => !b.isCorrect); var startNode = middleEdges.Find(firstIncorrectEdge); if (startNode == null) { throw new Exception("There should be an incorrect edge"); } if (startNode.Next != null && !startNode.Next.Value.isCorrect) // TODO: managed to get a NullReferenceException here... { var sideToRotate = firstIncorrectEdge.index switch { (0, 1) => Side.Right, (1, 2) => Side.Top, (2, 1) => Side.Left, (1, 0) => Side.Bottom, _ => throw new Exception("The selected block is not a middle edge") }; PerformRuRuRuuRuRotation(sideToRotate); } else if (startNode.Previous != null && !startNode.Previous.Value.isCorrect) { var sideToRotate = firstIncorrectEdge.index switch { (0, 1) => Side.Bottom, (1, 2) => Side.Right, (2, 1) => Side.Top, (1, 0) => Side.Left, _ => throw new Exception("The selected block is not a middle edge") }; PerformRuRuRuuRuRotation(sideToRotate); } else { switch (firstIncorrectEdge.index) { case (0, 1): case (2, 1): PerformRuRuRuuRuRotation(Side.Bottom); PerformRuRuRuuRuRotation(Side.Left); PerformRuRuRuuRuRotation(Side.Bottom); break; case (1, 2): case (1, 0): PerformRuRuRuuRuRotation(Side.Right); PerformRuRuRuuRuRotation(Side.Bottom); PerformRuRuRuuRuRotation(Side.Right); break; } } } else if (numIncorrectEdges == 3) { var correctEdge = middleEdges.First(b => b.isCorrect); var sideToRotate = correctEdge.index switch { (0, 1) => Side.Left, (1, 2) => Side.Bottom, (2, 1) => Side.Right, (1, 0) => Side.Top, _ => throw new Exception("The selected block is not a middle edge") }; PerformRuRuRuuRuRotation(sideToRotate); } else { _cube.RotateClockwise(Side.Back); } } }
public void FirstLayerSolver_CorrectlySolvesCorners_GivenCornerBetweenWrongSidesOnFront() { var cube = new RubixCube(new[, , ] { { { new Block(Colour.Red, null, Colour.Green, null, Colour.White, null), new Block(null, null, Colour.Green, null, Colour.White, null), new Block(null, Colour.Blue, Colour.White, null, Colour.Red, null) }, { new Block(Colour.Red, null, null, null, Colour.White, null), new Block(null, null, null, null, Colour.White, null), new Block(null, Colour.Orange, null, null, Colour.White, null) }, { new Block(Colour.Orange, null, null, Colour.Green, Colour.White, null), new Block(null, null, null, Colour.Blue, Colour.White, null), new Block(null, Colour.Yellow, null, Colour.Orange, Colour.Green, null) } }, { { new Block(Colour.Yellow, null, Colour.Orange, null, null, null), new Block(null, null, Colour.Green, null, null, null), new Block(null, Colour.Yellow, Colour.Green, null, null, null) }, { new Block(Colour.Red, null, null, null, null, null), new Block(null, null, null, null, null, null), new Block(null, Colour.Orange, null, null, null, null) }, { new Block(Colour.Green, null, null, Colour.Orange, null, null), new Block(null, null, null, Colour.Blue, null, null), new Block(null, Colour.Yellow, null, Colour.Red, null, null) } }, { { new Block(Colour.Green, null, Colour.Yellow, null, null, Colour.Red), new Block(null, null, Colour.Yellow, null, null, Colour.Blue), new Block(null, Colour.Orange, Colour.Blue, null, null, Colour.White) }, { new Block(Colour.Blue, null, null, null, null, Colour.Red), new Block(null, null, null, null, null, Colour.Yellow), new Block(null, Colour.Orange, null, null, null, Colour.Blue) }, { new Block(Colour.Yellow, null, null, Colour.Blue, null, Colour.Orange), new Block(null, null, null, Colour.Red, null, Colour.Green), new Block(null, Colour.Yellow, null, Colour.Blue, null, Colour.Red) } } }); var solver = new FirstLayerSolver(cube); solver.Solve(); Assert.That(RubixCubeStatusEvaluator.FirstLayerIsSolved(cube), Is.True); }
private static bool BackEdgeIsOnCorrectSide(Block block, Colour nonWhiteColour) { var layer = block.GetLayer(nonWhiteColour) ?? throw new ArgumentException("Cannot be null here"); return(RubixCubeStatusEvaluator.SideIsCorrectColour(layer, block)); }