public static bool CheckGridHasNoNullTiles(Tile[,] gridToCheck) { for (int i = 0; i < gridToCheck.GetLength(0); i++) // cols { for (int j = 0; j < gridToCheck.GetLength(1); j++) // rows { if (gridToCheck[i, j] == null) return false; } } return true; }
public static bool CheckPuzzleGrid(Tile[,] inputGrid) { for (int i = 0; i < inputGrid.GetLength(0); i++) // cols { for (int j = 0; j < inputGrid.GetLength(1); j++) // rows { if (inputGrid[i, j] == null) // if there's a tile missing it's not solved return false; // check tiles on edges don't have connections outward: if (i == 0 && inputGrid[i, j].Joins(3)) // in first col, so left must be false return false; if (i == inputGrid.GetLength(0) - 1 && inputGrid[i, j].Joins(1)) // in final col, so right must be false return false; if (j == 0 && inputGrid[i, j].Joins(0)) // in first row, so up must be false return false; if (j == inputGrid.GetLength(1) - 1 && inputGrid[i, j].Joins(2)) // in final row, so down is false return false; //check connections between tiles: if (i > 0 && inputGrid[i, j].Joins(3) != inputGrid[i - 1, j].Joins(1)) // Check (our tile)'s (connection to the left) MATCHES (tile to the left)'s (connection to right) return false; if (j > 0 && inputGrid[i, j].Joins(0) != inputGrid[i, j - 1].Joins(2)) // Check (our tile)'s (connection up) MATCHES (tile above)'s (connection down) return false; } } return true; }
public static void SolveByRandomThreader(ref Tile[,] outputGrid, ref ulong attempts, Tile[,] gridToSolve) { // pass a reference to the things that we'll output, so multiple threads can share the data and whoever finishes first will set it Tuple<Tile[,], ulong> solution = SolveByRandom(gridToSolve); outputGrid = solution.Item1; attempts = solution.Item2; }
public static Tuple<Tile[, ], ulong> SolveByRandom(Tile[,] gridToSolve) { // this is crappy on purpose so we can get benefits from threading! var rnd = new Random(); // pass in the random object because otherwise we'll probably create a lot quickly and get insufficient randomness ulong attempts = 0; // up to 2^64. We have 4^25 = 2^50 orderings for a 5x5 grid so this is plenty. Tile[,] solvedGrid = (Tile[,])gridToSolve.Clone(); while (true) { attempts++; solvedGrid = RandomlyRotateTilesInPuzzleGrid(gridToSolve, rnd); if (CheckPuzzleGrid(solvedGrid)) return new Tuple<Tile[,], ulong>(solvedGrid,attempts); } }
public static Tile[,] RandomlyRotateTilesInPuzzleGrid(Tile[,] inputGrid, Random rnd) { // take random object as parameter so that we don't create a lot quickly and get low randomness if this is called a lot for (int i = 0; i < inputGrid.GetLength(0); i++) // cols { for (int j = 0; j < inputGrid.GetLength(1); j++) // rows { if (inputGrid[i, j] == null) continue; var rotations = rnd.Next(1, 5); // number of rotations, 1-4 for (int k = 0; k < rotations; k++) { inputGrid[i, j].RotateCW(); } } } return inputGrid; }
public static Tile[,] CreateSolvedPuzzleGrid(Tile[,] inputGrid) { var rnd = new Random(); // for each tile, determine connections fixed by previously set tiles (or by boundaries), randomise remaining. for (int i = 0; i < inputGrid.GetLength(0); i++) // cols { for (int j = 0; j < inputGrid.GetLength(1); j++) // rows { bool up; bool right; bool down; bool left; if (i == 0) // in first col, so left must be false left = false; else // in a later col, so take left from previous left = inputGrid[i - 1, j].Joins(1); if (i == inputGrid.GetLength(0) - 1) // in final col, so right is false right = false; else // randomise right = rnd.Next(0, 2) == 0 ? true : false; if (j == 0) // in first row, so up must be false up = false; else // in a later row so take up from previous up = inputGrid[i, j - 1].Joins(2); if (j == inputGrid.GetLength(1) - 1) // in final row, so down is false down = false; else // randomise down = rnd.Next(0, 2) == 0 ? true : false; inputGrid[i, j] = new Tile(up, right, down, left); } } // rotate each grid 0-3 times randomly return inputGrid; }
void UpdateForm(Tile[,] gridToUse) { // fill the labels with the needed text for (int i = 0; i < gridToUse.GetLength(0); i++) { for (int j = 0; j < gridToUse.GetLength(1); j++) { if (gridToUse[i, j] == null) continue; tableLayoutPanel1.GetControlFromPosition(i,j).Text = gridToUse[i, j].TileChar.ToString(); } } }