public static void BottomLayerCornersAreCorrect(CubeConfiguration<FaceColour> configuration) { CornerAssert.BottomBackLeftIsCorrect(configuration); CornerAssert.BottomBackRightIsCorrect(configuration); CornerAssert.BottomFrontLeftIsCorrect(configuration); CornerAssert.BottomFrontRightIsCorrect(configuration); }
private async Task CheckFace(CubeConfiguration<FaceColour> configuration, FaceType faceToCheck, List<IRotation> solution, bool reverseDirection = false, bool doubleMoves = false) { var checkFace = configuration.Faces[faceToCheck]; var frontFace = configuration.Faces[FaceType.Front]; var isBack = faceToCheck == FaceType.Back; await CheckEdgeOnFace(configuration, solution, checkFace, Edge.Left, !isBack ? Edge.Left : Edge.Right, frontFace, FaceType.Left, reverseDirection, doubleMoves).ConfigureAwait(false); await CheckEdgeOnFace(configuration, solution, checkFace, Edge.Right, isBack ? Edge.Left : Edge.Right, frontFace, FaceType.Right, !reverseDirection, doubleMoves).ConfigureAwait(false); // TODO: THIS CAN BE IMPROVED, INSTEAD MOVE THE FRONT LAYER FIRST, YOU CAN CHOOSE EITHER THE LEFT OR RIGHT DEPENDING ON WHICH HOLDS THE EMPTY COLOUR if (checkFace.GetEdge(m_layer, Edge.Top).Centre() == m_faceColour) { await CommonActions.ApplyAndAddRotation(Rotations.ByFace(faceToCheck, RotationDirection.AntiClockwise), solution, configuration).ConfigureAwait(false); await CheckEdgeOnFace(configuration, solution, checkFace, !isBack ? Edge.Left : Edge.Right, Edge.Left, frontFace, !isBack ? FaceType.Left : FaceType.Right, reverseDirection, doubleMoves).ConfigureAwait(false); } if (checkFace.GetEdge(m_layer, Edge.Bottom).Centre() == m_faceColour) { await CommonActions.ApplyAndAddRotation(Rotations.ByFace(faceToCheck, RotationDirection.AntiClockwise), solution, configuration).ConfigureAwait(false); await CheckEdgeOnFace(configuration, solution, checkFace, isBack ? Edge.Left : Edge.Right, Edge.Right, frontFace, !isBack ? FaceType.Right : FaceType.Left, reverseDirection, doubleMoves).ConfigureAwait(false); } await CheckEdgeOnFace(configuration, solution, checkFace, Edge.Left, !isBack ? Edge.Left : Edge.Right, frontFace, FaceType.Left, reverseDirection, doubleMoves).ConfigureAwait(false); await CheckEdgeOnFace(configuration, solution, checkFace, Edge.Right, isBack ? Edge.Left : Edge.Right, frontFace, FaceType.Right, !reverseDirection, doubleMoves).ConfigureAwait(false); }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { var solution = new List<IRotation>(); var allColours = new[] { FaceColour.Red, FaceColour.Blue, FaceColour.Yellow, FaceColour.Orange, FaceColour.Green, FaceColour.White, }; var colourIndex = Array.IndexOf(allColours, configuration.Faces[FaceType.Front].Centre); var startIndex = colourIndex; await SolveFrontFace(configuration, solution).ConfigureAwait(false); int count = 0; do { colourIndex++; if (colourIndex >= allColours.Length) { colourIndex = 0; } var nextColour = allColours[colourIndex]; solution.Add(await CommonActions.PositionOnFront(configuration, nextColour).ConfigureAwait(false)); await SolveFrontFace(configuration, solution).ConfigureAwait(false); if (++count > 10) { throw new SolveFailureException("Could not solve the inner square in 10 or less tries"); } } while (colourIndex != startIndex); return solution; }
public static void BottomFrontRightIsCorrect(CubeConfiguration<FaceColour> configuration) { CommonActions.ResetToDefaultPosition(configuration).Wait(); Assert.AreEqual(FaceColour.White, configuration.Faces[FaceType.Down].TopRight()); Assert.AreEqual(FaceColour.Red, configuration.Faces[FaceType.Front].BottomRight()); Assert.AreEqual(FaceColour.Green, configuration.Faces[FaceType.Right].BottomLeft()); }
public static void BottomBackLeftIsCorrect(CubeConfiguration<FaceColour> configuration) { CommonActions.ResetToDefaultPosition(configuration).Wait(); Assert.AreEqual(FaceColour.White, configuration.Faces[FaceType.Down].BottomLeft()); Assert.AreEqual(FaceColour.Orange, configuration.Faces[FaceType.Back].BottomRight()); Assert.AreEqual(FaceColour.Blue, configuration.Faces[FaceType.Left].BottomLeft()); }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { var solution = new List<IRotation>(); List<IRotation> previousSolution; await Repeat.SolvingUntilNoMovesCanBeMade(solution, async () => { await CheckUpperAndDownEdgesOnFace(configuration, solution, FaceType.Front).ConfigureAwait(false); await CheckUpperAndDownEdgesOnFace(configuration, solution, FaceType.Left).ConfigureAwait(false); await CheckUpperAndDownEdgesOnFace(configuration, solution, FaceType.Back).ConfigureAwait(false); await CheckUpperAndDownEdgesOnFace(configuration, solution, FaceType.Right).ConfigureAwait(false); await CheckMiddleLayersOnFace(configuration, solution, FaceType.Right).ConfigureAwait(false); await CheckMiddleLayersOnFace(configuration, solution, FaceType.Back).ConfigureAwait(false); await CheckMiddleLayersOnFace(configuration, solution, FaceType.Front).ConfigureAwait(false); await CheckFlipped(configuration, solution).ConfigureAwait(false); }).ConfigureAwait(false); return solution; }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { var solution = new List<IRotation>(); solution.Add(await CommonActions.PositionOnBottom(configuration, FaceColour.Yellow).ConfigureAwait(false)); for (int i = 0; i <= 3; i++) { var stepsToSolveTredge = await m_solver.Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveTredge); await MoveTredgeToUpperLayer(configuration, solution).ConfigureAwait(false); } await CommonActions.ApplyAndAddRotation(CubeRotations.Z2, solution, configuration).ConfigureAwait(false); for (int i = 0; i <= 3; i++) { var stepsToSolveTredge = await m_solver.Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveTredge); await MoveTredgeToUpperLayer(configuration, solution).ConfigureAwait(false); } await FixInnerSquare(solution, configuration).ConfigureAwait(false); return solution; }
internal async Task CheckBottomFaceForWhite(CubeConfiguration<FaceColour> configuration, List<IRotation> solution) { if (configuration.Faces[FaceType.Down].TopRight() == FaceColour.White && configuration.Faces[FaceType.Front].BottomRight() != configuration.Faces[FaceType.Front].Centre) { await SortBottom(configuration, solution).ConfigureAwait(false); } if (configuration.Faces[FaceType.Down].TopLeft() == FaceColour.White && configuration.Faces[FaceType.Front].BottomLeft() != configuration.Faces[FaceType.Front].Centre) { await CommonActions.ApplyAndAddRotation(CubeRotations.YAntiClockwise, solution, configuration).ConfigureAwait(false); await SortBottom(configuration, solution).ConfigureAwait(false); } if (configuration.Faces[FaceType.Down].BottomLeft() == FaceColour.White && configuration.Faces[FaceType.Back].BottomRight() != configuration.Faces[FaceType.Back].Centre) { await CommonActions.ApplyAndAddRotation(CubeRotations.Y2, solution, configuration).ConfigureAwait(false); await SortBottom(configuration, solution).ConfigureAwait(false); } if (configuration.Faces[FaceType.Down].BottomRight() == FaceColour.White && configuration.Faces[FaceType.Back].BottomLeft() != configuration.Faces[FaceType.Back].Centre) { await CommonActions.ApplyAndAddRotation(CubeRotations.YClockwise, solution, configuration).ConfigureAwait(false); await SortBottom(configuration, solution).ConfigureAwait(false); } }
private async Task CheckEdgeOnFace(CubeConfiguration<FaceColour> configuration, List<IRotation> solution, Face<FaceColour> checkFace, Edge frontEdge, Edge checkEdge, Face<FaceColour> frontFace, FaceType movementFace, bool reverseDirection = false, bool doubleMoves = false) { var numMoves = doubleMoves ? 2 : 1; var center = checkFace.GetEdge(m_layer, checkEdge).Centre(); if (center == m_faceColour) { for (int i = 0; i <= 3; i++) { if (frontFace.GetEdge(m_layer, frontEdge).Centre() == m_faceColour) break; await CommonActions.ApplyAndAddRotation(Rotations.FrontClockwise, solution, configuration).ConfigureAwait(false); } var direction = !reverseDirection ? RotationDirection.Clockwise : RotationDirection.AntiClockwise; var rotation = numMoves == 1 ? Rotations.ByFace(movementFace, direction, m_layer) : Rotations.ByFaceTwice(movementFace, m_layer); await CommonActions.ApplyAndAddRotation(rotation, solution, configuration).ConfigureAwait(false); for (int i = 0; i <= 3; i++) { if (frontFace.GetEdge(m_layer, frontEdge).Centre() != m_faceColour) break; await CommonActions.ApplyAndAddRotation(Rotations.FrontClockwise, solution, configuration).ConfigureAwait(false); } direction = !reverseDirection ? RotationDirection.AntiClockwise : RotationDirection.Clockwise; rotation = numMoves == 1 ? Rotations.ByFace(movementFace, direction, m_layer) : Rotations.ByFaceTwice(movementFace, m_layer); await CommonActions.ApplyAndAddRotation(rotation, solution, configuration).ConfigureAwait(false); } }
internal FaceColourPair ChooseFaceColourForBottom(CubeConfiguration<FaceColour> configuration) { var maxAmountOfColoursSoFar = 0; FaceType? chosenFace = null; FaceColour? chosenColour = null; foreach (var kvp in configuration.Faces) { var groups = kvp.Value.Items.AsEnumerable().GroupBy(f => f).Select(group => new { Colour = group.Key, Count = group.Count() }).ToList(); var maxColoursOnFace = groups.Max(g => g.Count); if (maxColoursOnFace > maxAmountOfColoursSoFar) { maxAmountOfColoursSoFar = maxColoursOnFace; chosenColour = groups.First(g => g.Count == maxColoursOnFace).Colour; chosenFace = kvp.Key; } } // TODO: DETECT HOW MANY IN CORRECT POS TO EACH OTHER return new FaceColourPair{Face = chosenFace.Value, Colour = chosenColour.Value}; }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { var solution = new List<IRotation>(); var stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.White).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.Red).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.Blue).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.Orange).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.Green).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); stepsToSolveCross = await new SingleFaceCrossSolver(FaceColour.Yellow).Solve(configuration).ConfigureAwait(false); solution.AddRange(stepsToSolveCross); return solution; }
public void Rotate_UpperClockwise() { var brd = new T { Id = "brd" }; var bld = new T { Id = "bld" }; var bru = new T { Id = "bru" }; var blu = new T { Id = "blu" }; var frd = new T { Id = "frd" }; var fld = new T { Id = "fld" }; var fru = new T { Id = "fru" }; var flu = new T { Id = "flu" }; var frontFace = new[,] { { flu, fru }, { fld, frd } }; var backFace = new[,] { { bru, blu }, { brd, bld } }; var faceTop = new[,] { { flu, fru }, { blu, bru } }; var faceBottom = new[,] { { bld, brd }, { fld, frd } }; var faceLeft = new[,] { { blu, flu }, { bld, fld } }; var faceRight = new[,] { { fru, bru }, { frd, brd } }; var config = new CubeConfiguration<T>(faceTop, faceBottom, faceLeft, faceRight, frontFace, backFace); config.Rotate(Rotations.UpperClockwise); CollectionAssert.AreEqual(new[,] { { fru, bru }, { fld, frd } }, config.Faces[FaceType.Front].Items); CollectionAssert.AreEqual(new[,] { { flu, fru }, { bld, fld } }, config.Faces[FaceType.Left].Items); CollectionAssert.AreEqual(new[,] { { blu, flu }, { brd, bld } }, config.Faces[FaceType.Back].Items); CollectionAssert.AreEqual(new[,] { { bru, blu }, { frd, brd } }, config.Faces[FaceType.Right].Items); }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { var solution = new List<IRotation>(); var solved = configuration.Faces.Values.All(face => face.Items.AsEnumerable().All(colour => colour == face.Items[0, 0])); if (!solved) { solved = await OneCornerCorrect(configuration, solution).ConfigureAwait(false); if (!solved) { solved = await CrossedCorners(configuration, solution).ConfigureAwait(false); if (!solved) { await CornersSwitchedInParallel(configuration, solution).ConfigureAwait(false); } } } return solution; }
public async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { if (m_layer < 0) { m_layer = configuration.MinInnerLayerIndex(); } var solution = new List<IRotation>(); var rotationToBottom = await CommonActions.PositionOnFront(configuration, m_faceColour).ConfigureAwait(false); if (rotationToBottom != null) solution.Add(rotationToBottom); for (int i = 0; i <= 3; i++) { await CheckFace(configuration, FaceType.Upper, solution).ConfigureAwait(false); await CommonActions.ApplyAndAddRotation(CubeRotations.ZClockwise, solution, configuration).ConfigureAwait(false); } await CheckFace(configuration, FaceType.Back, solution, false, true).ConfigureAwait(false); return solution; }
public void GetCentreLayer_WhenConfigurationIsForAnEvenNumber_ThrowsInvalidOperationException(int size) { var configuration = new CubeConfiguration<int>(size); TestDelegate testFunc = () => configuration.GetCentreLayer(); Assert.Throws<InvalidOperationException>(testFunc); }
public void GetCentreLayer_WhenConfigurationIsForAnOddNumber_ReturnsTheIndexOfTheCentreLayer(int size, int expected) { var configuration = new CubeConfiguration<int>(size); var centreLayerIndex = configuration.GetCentreLayer(); Assert.AreEqual(expected, centreLayerIndex); }
private static void AssertInnerSquareIsCorrectOnAllFaces(CubeConfiguration<FaceColour> configuration) { Assert.IsTrue(InnerSquareIsComplete(FaceType.Front, configuration)); Assert.IsTrue(InnerSquareIsComplete(FaceType.Back, configuration)); Assert.IsTrue(InnerSquareIsComplete(FaceType.Left, configuration)); Assert.IsTrue(InnerSquareIsComplete(FaceType.Right, configuration)); Assert.IsTrue(InnerSquareIsComplete(FaceType.Upper, configuration)); Assert.IsTrue(InnerSquareIsComplete(FaceType.Down, configuration)); }
public RubiksCube(int cubeSize) { Size = cubeSize; CubeConfiguration = new CubeConfiguration<Cubie>(cubeSize); float halfSize = (Size + (Size - 1) * CubeSpacing) / 2f; halfSize -= 0.5f; m_cubieCentre = new Vector3(-halfSize); }
private static IEnumerable<FaceColour> GetInnerSquareForFace(CubeConfiguration<FaceColour> configuration, FaceType faceType) { var upperEdge = configuration.Faces[faceType].GetEdge(1, Edge.Top).Skip(1).Take(3).ToArray(); var middleEdge = configuration.Faces[faceType].GetEdge(2, Edge.Top).Skip(1).Take(3).ToArray(); var lowerEdge = configuration.Faces[faceType].GetEdge(3, Edge.Top).Skip(1).Take(3).ToArray(); var allItems = upperEdge.Concat(middleEdge).Concat(lowerEdge); return allItems; }
public virtual Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration) { if (!SkipChecks) { CheckConfigurationIsValidForThisSolver(configuration); } return Task.FromResult(new List<IRotation>().AsEnumerable()); }
private static void AssertConfigurationsAreEqual(CubeConfiguration<FaceColour> configuration1, CubeConfiguration<FaceColour> configuration2) { CollectionAssert.AreEqual(configuration1.Faces[FaceType.Front].Items, configuration2.Faces[FaceType.Front].Items); CollectionAssert.AreEqual(configuration1.Faces[FaceType.Back].Items, configuration2.Faces[FaceType.Back].Items); CollectionAssert.AreEqual(configuration1.Faces[FaceType.Left].Items, configuration2.Faces[FaceType.Left].Items); CollectionAssert.AreEqual(configuration1.Faces[FaceType.Right].Items, configuration2.Faces[FaceType.Right].Items); CollectionAssert.AreEqual(configuration1.Faces[FaceType.Upper].Items, configuration2.Faces[FaceType.Upper].Items); CollectionAssert.AreEqual(configuration1.Faces[FaceType.Down].Items, configuration2.Faces[FaceType.Down].Items); }
public static void TopLayerCrossIsCorrect(CubeConfiguration<FaceColour> configuration) { CommonActions.ResetToDefaultPosition(configuration).Wait(); FaceHasCrossOfColour(configuration, FaceType.Upper, FaceColour.Yellow); Assert.AreEqual(FaceColour.Red, configuration.Faces[FaceType.Front].TopCentre()); Assert.AreEqual(FaceColour.Blue, configuration.Faces[FaceType.Left].TopCentre()); Assert.AreEqual(FaceColour.Orange, configuration.Faces[FaceType.Back].TopCentre()); Assert.AreEqual(FaceColour.Green, configuration.Faces[FaceType.Right].TopCentre()); }
public static void FaceHasCrossOfColour(CubeConfiguration<FaceColour> configuration, FaceType faceType, FaceColour faceColour) { int layer = Math.Max(configuration.Size - 4, 0); var face = configuration.Faces[faceType]; Assert.AreEqual(faceColour, face.Centre); Assert.AreEqual(faceColour, face.GetEdge(layer, Edge.Right).Centre()); Assert.AreEqual(faceColour, face.GetEdge(layer, Edge.Top).Centre()); Assert.AreEqual(faceColour, face.GetEdge(layer, Edge.Bottom).Centre()); Assert.AreEqual(faceColour, face.GetEdge(layer, Edge.Bottom).Centre()); }
private static void AssertCornersAreCorrect(CubeConfiguration<FaceColour> configuration, FaceType faceType) { var colour = configuration.Faces[faceType].Centre; var topEdge = configuration.Faces[faceType].GetEdge(1, Edge.Top); var bottomEdge = configuration.Faces[faceType].GetEdge(1, Edge.Bottom); Assert.AreEqual(colour, topEdge[1]); Assert.AreEqual(colour, topEdge[3]); Assert.AreEqual(colour, bottomEdge[1]); Assert.AreEqual(colour, bottomEdge[3]); }
public Task SetCubeConfiguration(CubeConfiguration<FaceColour> configuration) { m_cubeResetTask = new TaskCompletionSource<object>(); RubiksCube = new RubiksCube(configuration); m_cubeAnimator = new RubiksCubeAnimator(RubiksCube, AnimationLength); m_regenerateRubiksCube = true; return m_cubeResetTask.Task; }
internal async Task CheckTopLayerForWhite(CubeConfiguration<FaceColour> configuration, List<IRotation> solution) { await FrontTopLayer(configuration, solution).ConfigureAwait(false); await BackTopLayer(configuration, solution).ConfigureAwait(false); await RightTopLayer(configuration, solution).ConfigureAwait(false); await LeftTopLayer(configuration, solution).ConfigureAwait(false); }
private async Task CheckTopLayer(CubeConfiguration<FaceColour> configuration, ICollection<IRotation> solution) { await CheckTopFrontLayer(configuration, solution).ConfigureAwait(false); await CheckTopLeftLayer(configuration, solution).ConfigureAwait(false); await CheckTopBackLayer(configuration, solution).ConfigureAwait(false); await CheckTopRightLayer(configuration, solution).ConfigureAwait(false); }
private static async Task SortBottom(CubeConfiguration<FaceColour> configuration, ICollection<IRotation> solution) { await CommonActions.ApplyAndAddRotation(Rotations.RightClockwise, solution, configuration).ConfigureAwait(false); await CommonActions.ApplyAndAddRotation(Rotations.UpperClockwise, solution, configuration).ConfigureAwait(false); await CommonActions.ApplyAndAddRotation(Rotations.RightAntiClockwise, solution, configuration).ConfigureAwait(false); await CheckTopLayerForWhite(configuration, solution, FaceType.Left, false, true).ConfigureAwait(false); }
internal async Task CheckMiddleLayerForWhite(CubeConfiguration<FaceColour> configuration, List<IRotation> solution) { await CheckMiddleLayerForWhite(configuration, configuration.Faces[FaceType.Left], FaceType.Left, solution).ConfigureAwait(false); await CheckMiddleLayerForWhite(configuration, configuration.Faces[FaceType.Right], FaceType.Right, solution).ConfigureAwait(false); await CheckMiddleLayerForWhite(configuration, configuration.Faces[FaceType.Front], FaceType.Front, solution).ConfigureAwait(false); await CheckMiddleLayerForWhite(configuration, configuration.Faces[FaceType.Back], FaceType.Back, solution).ConfigureAwait(false); }
internal async Task CheckBottomFaceForWhite(CubeConfiguration<FaceColour> configuration, List<IRotation> solution) { await CheckBottomFaceForWhite(configuration, FaceType.Left, solution).ConfigureAwait(false); await CheckBottomFaceForWhite(configuration, FaceType.Right, solution).ConfigureAwait(false); await CheckBottomFaceForWhite(configuration, FaceType.Front, solution).ConfigureAwait(false); await CheckBottomFaceForWhite(configuration, FaceType.Back, solution).ConfigureAwait(false); }
private void Awake() { Instance = this; colors = ColorExtensions.LoadMassive(); }