/* * This method scrambles a virtual cube, as such * it cannot be used with a real cube. */ public static void Randomizer(Cube a, int count) { Random rand = new Random(); int aux; for (int i = 0; i < count; i++) { aux = rand.Next () % 5; switch (aux) { case 0: a.TurnRowCW (); break; case 1: a.TurnRowCCW (); break; case 2: a.Roll (); break; case 3: a.TurnCubeCW (); break; case 4: a.TurnCubeCCW (); break; } } GoToInitial (a); }
public static void Main(string[] args) { var sensor = new EV3ColorSensor(SensorPort.In1); sensor.Mode = ColorMode.RGB; Motor motorA = new Motor(MotorPort.OutA); Motor motorB = new Motor(MotorPort.OutB); Motor motorD = new Motor(MotorPort.OutD); string solution; Cube cube = new Cube (motorA, motorB, motorD); // instantiate a real cube // Cube cube = new Cube (); // virtual cube used for tests // Solver.Randomizer (cube, 5000); // scramble the virtual cube DateTime starttime = DateTime.Now; TimeSpan elapsedtime = new TimeSpan (); MoveCube.BuildCube2P(cube, MoveCube.BuildCube (cube, motorA, motorB, motorD, sensor)); elapsedtime = DateTime.Now - starttime; Console.WriteLine (cube.GetCubeMap()); Console.WriteLine (cube.ToString ()); Console.WriteLine ("Elapsed time scanning cube: {0}", elapsedtime); starttime = DateTime.Now; // uncomment line below if you want to use the internal algorithm to solve the cube. // It's the easiest way, but also the slowest. // solution = Solver.Solve (cube); // comment the following block if you intend to use the internal algorithm to solve // the cube. By default the main program tries to read the solution from a solution // file. Just run the Kociemba algorithm on a pc and use scp, putty or any other ssh // tool to send the file to the intelligent Lego brick. Communication.ClearCube (Communication.CubePath); Communication.ClearCube (Communication.SolutionPath); Communication.SaveCube (Communication.CubePath, cube.ToString ()); solution = Communication.ReceiveSolution (); elapsedtime = DateTime.Now - starttime; Console.WriteLine ("Solution: {0}", solution); Console.WriteLine ("Elapsed time receiving solution: {0}", elapsedtime); starttime = DateTime.Now; Solver.TranslateMove (solution, cube); Console.WriteLine (cube.GetCubeMap ()); elapsedtime = DateTime.Now - starttime; Console.WriteLine ("Time elapsed moving cube: {0}", elapsedtime); Communication.ClearCube (Communication.CubePath); Communication.ClearCube (Communication.SolutionPath); }
public static readonly int SensorSide = 87; //79 #endregion Fields #region Methods /* * This method controls the movements of the robot to position * each face of the cube to be scanned by the color sensor. */ public static char[] BuildCube(Cube cube, Motor motorA, Motor motorB, Motor motorD, EV3ColorSensor sensor) { char[] faces = new char[6]; // Position face in cube for (int j = 0; j < 6; j++) { switch (j) { case 0: BuildFace (cube.face[3], motorA, motorB, sensor); cube.face [3].TurnCWCore (); cube.face [3].TurnCWCore (); MoveCube.Move (motorD, MoveCube.GrabArm); MoveCube.Move (motorD, MoveCube.PullArm); MoveCube.Move (motorD, MoveCube.RestArm); break; case 1: BuildFace (cube.face[2], motorA, motorB, sensor); cube.face [2].TurnCWCore (); MoveCube.Move (motorD, MoveCube.GrabArm); MoveCube.Move (motorD, MoveCube.PullArm); MoveCube.Move (motorD, MoveCube.RestArm); break; case 2: BuildFace (cube.face[1], motorA, motorB, sensor); MoveCube.MoveRel (motorA, MoveCube.CCW90); MoveCube.Move (motorD, MoveCube.GrabArm); MoveCube.Move (motorD, MoveCube.PullArm); MoveCube.Move (motorD, MoveCube.RestArm); break; case 3: BuildFace (cube.face[0], motorA, motorB, sensor); cube.face [0].TurnCCWCore (); MoveCube.MoveRel (motorA, MoveCube.CW90); MoveCube.Move (motorD, MoveCube.GrabArm); MoveCube.Move (motorD, MoveCube.PullArm); MoveCube.Move (motorD, MoveCube.RestArm); break; case 4: BuildFace (cube.face [4], motorA, motorB, sensor); MoveCube.Move (motorD, MoveCube.GrabArm); MoveCube.Move (motorD, MoveCube.PullArm); MoveCube.Move (motorD, MoveCube.RestArm); break; case 5: BuildFace (cube.face [5], motorA, motorB, sensor); break; } } for (int i = 0; i < 6; i++) faces [i] = cube.face [i].square [1, 1]; return faces; }
/* * This method positions any specified face in the bottom * of the cube (a face is specified by its central facelet). */ public static void GoToFace(string face, Cube a) { if (a.face [5].square [1, 1].ToString() == face) { a.Roll (); a.Roll (); } else if (a.face [4].square [1, 1].ToString () == face) { a.Roll (); } else if (a.face [3].square [1, 1].ToString () == face) { a.TurnCubeCW (); a.Roll (); } else if (a.face [2].square [1, 1].ToString () == face) { a.TurnCube180 (); a.Roll (); } else if (a.face [1].square [1, 1].ToString () == face) { a.TurnCubeCCW (); a.Roll (); } }
/* * This method translates the string retrieved from Kociemba's two-phase * algorithm into movements of the virtual and real cube (if instantiated). */ public static void TranslateMove(String move, Cube a) { string aux; bool turn = false; for (int i = 0; i < move.Length; i++){ aux = move.Substring (i, 1); switch (aux) { case "U": case "D": case "L": case "R": case "F": case "B": turn = true; GoToFace (aux, a); break; default: continue; } if (turn){ turn = false; aux = move.Substring (i + 1, 1); switch (aux) { case "\'": a.TurnRowCCW (); break; case "2": a.TurnRow180 (); break; default: a.TurnRowCW (); break; } } } a.RestArm (); }
/* * Converts facelets' colors into a metaformat used by Kociemba's algorithm. * Kociemba's algorithm always uses an immutable metaformat. * This means that the front of the cube will always stay in * in front, top on top, back in back, etc. * By calling this method, whichever color of the central facelet that * happens to be on top will become the top in the metaformat, the color on * on the frontal central facelet will become the new front, and so on. This saves * the trouble of repositioning the cube before solving it instead of when the colors * are fixed to each of the faces in the metaformat. */ public static void BuildCube2P(Cube a, char[] faces) { for (int k = 0; k < 6; k++) for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++){ if (faces [0] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'F'; else if (faces [1] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'D'; else if (faces [2] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'L'; else if (faces [3] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'U'; else if (faces [4] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'R'; else if (faces [5] == a.face [k].square [i,j]) a.face [k].square [i,j] = 'B'; } }
/* * This method just delegates the solving of the cube * to Kociemba's algorithm. */ public static String Solve(Cube a) { return Search.solution (a.ToString (), 20, true); }
/* * Used only by the Randomizer function, to return the cube to the original position * Not necessary if MoveCube is building the cube through color scan */ private static void GoToInitial(Cube a) { GoToFace ("F", a); switch (a.face [1].square[1,1].ToString()) { case "L": a.TurnCubeCW (); break; case "R": a.TurnCubeCCW (); break; case "U": a.TurnCube180(); break; } }