public ActionResult Index(int k = 0) { int?[,] numbers = new int?[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { string key = string.Format("f{0}{1}", i, j); int number; if (int.TryParse(Request[key], out number)) numbers[i, j] = number; } } Game game = new Game(numbers); Solver solver = new Solver(); try { DateTime start = DateTime.Now; solver.Solve(game); DateTime end = DateTime.Now; ViewBag.Interval = string.Format("Solved in {0} ms.", end.Subtract(start).Milliseconds); } catch (InvalidGameException) { ViewBag.Message = "Invalid entry. There is no solution for the game!"; } ViewBag.Numbers = game.Numbers; return View(); }
public void Solve(Game game) { bool progress = true; while (progress && !game.IsSolved) { //Console.Out.Write(game); //Console.Out.WriteLine(""); progress = SolveIteration(game); if (!progress && !game.IsSolved) { progress = SearchSolution(game); } } }
private bool SearchSolution(Game game) { // Plan B if SearchIteration doesn't make progress. // Make a copy of the game, and do a depth first search on possible permutations, until a feasible solution is found. Stack<Game> gameStack = new Stack<Game>(); gameStack.Push(game); bool result = SearchSolutionRecursive(gameStack); Game copy = gameStack.Peek(); var unsolvedTiles = game.GetFlattenedTiles().Where(t => !t.IsSolved); foreach (Tile tile in unsolvedTiles) { tile.Number = copy[tile.XIndex, tile.YIndex].Number; } return result; }
public void TestExpert() { int?[,] setup = new int?[,] { { 5, null, 6, null, null, 4, null, null, null }, { 4, null, null, null, null, null, null, 2, null }, { null, 2, null, null, null, null, 5, null, 7 }, { null, null, null, 7, null, 8, null, null, null }, { null, null, null, null, 3, null, 2, null, 1 }, { null, null, null, null, null, null, 3, null, null }, { 1, null, null, 4, null, 2, null, null, 5 }, { null, null, 4, null, null, 5, 8, null, null }, { null, null, 3, 6, 8, null, null, null, 2 } }; Game game = new Game(setup); Solver solver = new Solver(); solver.Solve(game); Console.Out.Write(game); Assert.IsTrue(game.IsSolved); }
public void TestEasy() { int?[,] setup = new int?[,] { { null, null, 9, 1, null, null, null, null, 3 }, { null, 5, 6, 2, 8, 9, 7, 1, 4 }, { null, 7, 8, 6, 4, 3, 2, null, null }, { null, null, 2, null, null, null, 1, null, 9 }, { null, 3, 7, 5, null, null, 8, null, null }, { null, 1, 4, 9, null, null, null, 6, null }, { 8, null, 5, null, null, null, null, null, 1 }, { 4, 6, 3, null, null, null, null, 2, null }, { 7, 9, null, null, 5, null, null, null, null } }; Game game = new Game(setup); Solver solver = new Solver(); solver.Solve(game); Console.Out.Write(game); Assert.IsTrue(game.IsSolved); }
private bool SolveIteration(Game game) { bool tileSolved = false; IEnumerable<int> allNumbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // The main idea here: first search all tiles and determine if any unsolved tiles are solvable (i.e. we can narrow the candidates to a single number). // Then walk through all of the numbers and determine if there are any rows, columns, or squares for which that number can fit in only one of the nine tiles. // Return true if at least one tile is solved this way (so we can try again), false otherwise. foreach (Tile tile in game.GetFlattenedTiles()) { if (tile.IsSolved) continue; IEnumerable<int> numbers = allNumbers.Except(tile.Row.Numbers) .Except(tile.Column.Numbers) .Except(tile.Square.Numbers); if (numbers.Count() == 0) { throw new InvalidGameException(); } if (numbers.Count() == 1) { tile.Number = numbers.First(); tileSolved = true; } } foreach (int number in allNumbers) { tileSolved |= SolveForNumber(game.Rows, number); tileSolved |= SolveForNumber(game.Columns, number); tileSolved |= SolveForNumber(game.Squares, number); } return tileSolved; }