bool IsAtGoal(byte[] key, int piece, solveType type, int pos) { if (type != solveType.AllNonSpecificSolutions) { return(pos == key[this.piecePositions[this.isA[piece - 1, 0] - 1] + this.isA[piece - 1, 1] - 1]); } else { foreach (byte p2 in this.aIs[this.isA[piece - 1, 0] - 1]) { if (pos == key[this.piecePositions[this.isA[p2 - 1, 0] - 1] + this.isA[p2 - 1, 1] - 1]) { return(true); } } return(false); } }
static void Main(string[] args) { //Solve type solveType type = solveType.Diameter; int goalPosition = 13; int goalPiece = 1; //Only needed if solveType=1 or 2. int NumSolutions = 0; //Only for solveType.AllSolutions Boolean WriteToFile = false; //TODO: Actually use this Boolean verbose = false; DateTime startTime = DateTime.Now; DateTime moveTime; Globals.boards = new Dictionary <byte[], int[]>(new IntArrayComparer()); //At some point I should change the second type to a smaller type. Globals.lastboards = new Dictionary <byte[], int[]>(new IntArrayComparer()); //Maybe tomorrow. Globals.newboards = new Dictionary <byte[], int[]>(new IntArrayComparer()); Globals.PuzzlesConsidered = 0; Globals.TotalPuzzles = 0; //System.IO.TextWriter tw = new System.IO.StreamWriter("output.log"); //Start writing the log file. byte[,] testboard = new byte[, ] { { 1, 2, 2, 3 }, { 1, 2, 2, 3 }, { 0, 4, 4, 0 }, { 5, 6, 7, 8 }, { 5, 9, 10, 8 }, }; //Climb 24:{ { 1, 1, 1, 0, 1, 1, 1 }, { 2, 2, 0, 0, 0, 3, 3 }, { 4, 4, 5, 5, 5, 6, 6 }, { 4, 4, 7, 8, 8, 6, 6 }, { 9, 9, 7, 7, 8, 10, 10 }, { 11, 9, 12, 13, 14, 10, 15 }, { 11, 16, 12, 17, 14, 18, 15 }, { 16, 16, 19, 19, 19, 18, 18 }, { 20, 20, 21, 22, 23, 24, 24 }, { 20, 20, 22, 22, 22, 24, 24 } }; //Must be the same size as Globals.y*Globals.x //By the way, if you're wondering why all the coordinates in the program are like (y,x), it's to make the above look nice. Globals.x = 4; Globals.y = 5; Globals.numPieces = 10; //The maximum number of testboard MakePieceArray(testboard); //Initialize all the arrays. byte[] packtest2 = Pack(testboard); //The only use of the pack function. foreach (byte k in Unpack(packtest2)) { Console.Write(k + " "); } Globals.newboards.Add(packtest2, new int[0]); //Initalize the puzzle. int step = 1; //This is the read generation while (Globals.newboards.Count != 0) { moveTime = DateTime.Now; GenerateNextBoards(); //This step takes the longest. //check for solutions if ((type != solveType.Diameter) && (type != solveType.FullList)) { if (verbose) { Console.WriteLine("Checking for solution..."); } foreach (KeyValuePair <byte[], int[]> pair in Globals.newboards) { if (pair.Key[Globals.piecePositions[Globals.isA[goalPiece - 1, 0] - 1] + Globals.isA[goalPiece - 1, 1] - 1] == goalPosition) { if (type == solveType.Solve) { if (verbose) { Console.WriteLine("FOUND SOLUTION AT {0} MOVES!", step); WriteBoard(pair); } goto donehere; //I am ashamed. } else { if (verbose) { WriteBoard(pair); } NumSolutions++; } } } } Globals.TotalPuzzles += Globals.newboards.Count; //tw.WriteLine(step + " steps: " + Globals.newboards.Count + " boards, " + DateTime.Now+"({0} total puzzles, {1} total puzzles considered)",Globals.TotalPuzzles,Globals.PuzzlesConsidered); //tw.Flush(); Console.WriteLine(step + " steps: " + Globals.newboards.Count + " boards, " + DateTime.Now + "({0} total puzzles, {1} total puzzles considered, {2} boards per second)", Globals.TotalPuzzles, Globals.PuzzlesConsidered, Globals.newboards.Count / DateTime.Now.Subtract(moveTime).TotalSeconds); step++; //Fairly important. } donehere: if (type == solveType.Diameter) { //Write out the moves to get to the positions which are hardest to get to. Console.WriteLine("Finished diameter search! Total time: {0}", DateTime.Now.Subtract(startTime)); foreach (KeyValuePair <byte[], int[]> temp in Globals.boards) { WriteBoard(temp); } } else { Console.WriteLine("Done! Total time: {0}", DateTime.Now.Subtract(startTime)); if (type == solveType.AllSolutions) { Console.WriteLine("{0} solutions found", NumSolutions); } } Console.WriteLine("Press enter to exit..."); Console.ReadLine(); }
/// <summary> /// Solve a sliding-block puzzle given the puzzle, solve type, goal position, goal piece, and different pieces (oh and also if it should spew things to the screen) /// </summary> /// <param name="startboards">The initial state(s) of the puzzle to be solved.</param> /// <param name="type">The type of solution to give.</param> /// <param name="goalPosition">Where the goal piece should be moved.</param> /// <param name="goalPiece">The goal piece.</param> /// <param name="verbose">Should I tell you everything about the number 42 and this puzzle?</param> /// <param name="differentPieces">The pieces which are painted differently from the others.</param> public void SolveBoard(List <byte[, ]> startboards, solveType type, int goalPosition, int goalPiece, Verbosity verbosity, byte[] differentPieces, Func <byte[, ], bool> checkfunc) { //Solve type //solveType type = solveType.Solve; //int goalPosition = 2; //int goalPiece = 22; //Only needed if solveType=1 or 2. int NumSolutions = 0; //Only for solveType.AllSolutions Boolean WriteToFile = false; //TODO: Actually use this //Boolean verbose = true; results = new List <byte[, ]>(); resultnum = 0; this.startTime = DateTime.Now; DateTime moveTime; //System.IO.TextWriter tw = new System.IO.StreamWriter("output.log"); //Start writing the log file. //testboard Must be the same size as Globals.y*Globals.x //By the way, if you're wondering why all the coordinates in the program are like (y,x), it's to make the above look nice. //Globals.x = 7; //Globals.y = 10; Globals.x = (byte)startboards[0].GetLength(1); Globals.y = (byte)startboards[0].GetLength(0); this.numPieces = Max(startboards[0]); //The maximum number of testboard MakePieceArray(startboards[0], differentPieces); //Initialize all the arrays. comparer = new IntArrayComparer(piecePositions); this.boards = new Dictionary <byte[], int[]>(comparer); //At some point I should change the second type to a smaller type. this.lastboards = new Dictionary <byte[], int[]>(comparer); //Maybe tomorrow. this.newboards = new Dictionary <byte[], int[]>(comparer); this.PuzzlesConsidered = 0; this.TotalPuzzles = 0; byte[] packtest2; for (int i = 0; i < startboards.Count; i++) { packtest2 = Pack(startboards[i]); //The only use of the pack function. if (verbosity == Verbosity.Verbose) { foreach (byte k in Unpack(packtest2)) { Console.Write(k + " "); } } this.newboards.Add(packtest2, new int[0]); //Initalize the puzzle (s). } int step = 0; //This is the read generation moveTime = DateTime.Now; while (this.newboards.Count != 0) { //check for solutions if ((type != solveType.Diameter) && (type != solveType.FullList)) { if (verbosity == Verbosity.Verbose) { Console.WriteLine("Checking for solution..."); } foreach (KeyValuePair <byte[], int[]> pair in this.newboards) { if (IsAtGoal(pair.Key, goalPiece, type, goalPosition)) { byte[,] unpackedBoard = Unpack(pair.Key); bool isOK = false; if (checkfunc == null) { isOK = true; } else if (checkfunc(unpackedBoard)) { isOK = true; } if (isOK) { if (type == solveType.Solve) { if (verbosity != Verbosity.Silent) { Console.WriteLine("FOUND SOLUTION AT {0} MOVES!", step); WriteBoard(pair); } results.Add(Unpack(pair.Key)); goto donehere; //I am ashamed. } else { if (verbosity == Verbosity.Verbose) { WriteBoard(pair); } results.Add(Unpack(pair.Key)); resultnum = step; NumSolutions++; } } } } } this.TotalPuzzles += this.newboards.Count; //tw.WriteLine(step + " steps: " + this.newboards.Count + " boards, " + DateTime.Now+"({0} total puzzles, {1} total puzzles considered)",this.TotalPuzzles,this.PuzzlesConsidered); //tw.Flush(); if (verbosity == Verbosity.Verbose) { Console.WriteLine(step + " steps: " + this.newboards.Count + " boards, " + DateTime.Now + "({0} total puzzles, {1} total puzzles considered, {2} boards per second)", this.TotalPuzzles, this.PuzzlesConsidered, this.newboards.Count / DateTime.Now.Subtract(moveTime).TotalSeconds); } step++; //Fairly important. moveTime = DateTime.Now; GenerateNextBoards(); //This step takes the longest. } donehere: //Write out results to the results class switch (type) { case solveType.Solve: resultnum = step; break; case solveType.Diameter: resultnum = step - 1; break; } if (type == solveType.Diameter) { foreach (KeyValuePair <byte[], int[]> key in this.boards) { results.Add(Unpack(key.Key)); //Yeah, this line isn't confusing at all. } } if (type == solveType.Diameter && verbosity != Verbosity.Silent) { //Write out the moves to get to the positions which are hardest to get to. Console.WriteLine("Finished diameter search! Total time: {0}", DateTime.Now.Subtract(this.startTime)); foreach (KeyValuePair <byte[], int[]> temp in this.boards) { WriteBoard(temp); } } else { if (verbosity != Verbosity.Silent) { Console.WriteLine("Done! Total time: {0}", DateTime.Now.Subtract(this.startTime)); } if (type == solveType.AllNonSpecificSolutions) { if (verbosity != Verbosity.Silent) { Console.WriteLine("{0} solutions found", NumSolutions); } resultnum = step - 1; } } //Console.WriteLine("Press enter to exit..."); //Console.ReadLine(); }