public Difficulty GetDifficulty(CellsGrid inputGrid) { Grid = inputGrid.TrueClone(); if (!IsValid()) { return(Difficulty.Unsolvable); } Grid = inputGrid.TrueClone(); if (!SolveEasy()) { Grid = inputGrid.TrueClone(); if (!SolveMedium()) { Grid = inputGrid.TrueClone(); if (!SolveHard()) { return(Difficulty.Unsolvable); } else { return(Difficulty.Hard); } } else { return(Difficulty.Medium); } } else { return(Difficulty.Easy); } }
private void GenerateEasy() { CellsGrid tempGrid = new CellsGrid(); int iterations = 0; int tests = 0; for (; ;) { grid = new CellsGrid(); tempGrid = new CellsGrid(); while (tempGrid.Count < 20) { DebugGridPrint(); iterations++; tempGrid = grid.Clone(); tempGrid[random.Next(0, 9), random.Next(0, 9)] = random.Next(1, 9); if (new Validator(tempGrid).IsValid()) { grid = tempGrid.Clone(); } } if (new Solver(grid).SolveHard()) { break; } tests++; Debug.Print(tests.ToString()); } Generated = grid.Clone(); }
private void DebugGridPrintMain(CellsGrid cells, string message = "", bool print = false) { if (!print) { return; } string helper = ""; Debug.Print(message); for (int x = 0; x < 9; x++) { helper = ""; for (int y = 0; y < 9; y++) { if (y % 3 == 0) { helper += "| "; } if (cells[x, y] == 0) { helper += " "; } else { helper += cells[x, y].ToString() + " "; } } if (x % 3 == 0) { Debug.Print("------------------------"); } Debug.Print(helper); } Debug.Print(""); }
public Generator() { Generated = new CellsGrid(); grid = new CellsGrid(); random = new Random(); XElement element; using (Stream reader = new FileStream(".\\Data\\solved.xml", FileMode.Open)) { element = XElement.Load(reader); } var tempList = element.Descendants("sudoku").ToList().Select(d => { d.Value.Trim(); return(d.Value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x.ToString()))); }) .ToArray().Select(x => x.Select(y => y.Split(" ").Select(d => int.Parse(d)))).ToArray(); int tempIndex = random.Next(tempList.Length); //Debug.Print("Starting: " + tempIndex); var temp = tempList[tempIndex]; int x = 0; int y = 0; foreach (var item in temp) { if (x > 8) { x = 0; } foreach (var num in item) { if (y > 8) { y = 0; } grid[x, y] = num; y++; } x++; } Generated = grid.TrueClone(); //Switches random numbers for (int i = 0; i < 9; i++) { int num1 = Next(); int num2 = Next(); while (num1 == num2) { num2 = Next(); } NumberSwitch(num1, num2); } }
public List <int[]> GetInvalid(CellsGrid inputGrid) { List <int[]> output = new List <int[]>(); if (new Validator(inputGrid).IsValid()) { return(output); } Grid = inputGrid; for (int num = 1; num < 10; num++) { for (int i = 0; i < 9; i++) { int subX = (i / 3) * 3; int subY = (i % 3) * 3; if (CountRow(i, num) > 1) { int[] row = GetRow(i); for (int y = 0; y < 9; y++) { if (row[y] == num) { output.Add(new int[] { i, y }); } } } if (CountColumn(i, num) > 1) { int[] col = GetColumn(i); for (int x = 0; x < 9; x++) { if (col[x] == num) { output.Add(new int[] { x, i }); } } } if (CountSubgrid(subX, subY, num) > 1) { for (int x = subX; x < subX + 3; x++) { for (int y = subY; y < subY + 3; y++) { if (inputGrid[x, y] == num) { output.Add(new int[] { x, y }); } } } } } } return(output); }
/// <summary> /// Returns copy of inputCells. /// </summary> /// <returns>New copy of inputCells</returns> public CellsGrid TrueClone() { CellsGrid cells = new CellsGrid(); for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { cells[x, y] = grid[x, y]; } } return(cells); }
public Solver(CellsGrid inputGrid) : base(inputGrid) { Grid = inputGrid.TrueClone(); possible = new List <List <List <int> > >(); for (int i = 0; i < 9; i++) { possible.Add(new List <List <int> >()); for (int j = 0; j < 9; j++) { possible[i].Add(new List <int>()); } } Steps = new List <CellsGrid>(); Steps.Add(Grid.TrueClone()); }
//Hints ---------------------------------- /// <summary> /// Returns List of x and y indexes, where is difference from inputGrid. /// </summary> /// <param name="inputGrid">InputGrid will be compared to SolvedGrid</param> /// <returns>List of indexes, where are differences.</returns> public List <int[]> IsCorrect(CellsGrid inputGrid) { List <int[]> output = new List <int[]>(); SolveHard(); for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (inputGrid[x, y] != 0 && SolvedGrid[x, y] != inputGrid[x, y]) { output.Add(new int[] { x, y }); } } } return(output); }
/// <summary> /// Returns list of indexes of input grid, where is not a zero. /// </summary> /// <param name="grid">Input CellsGrid</param> /// <returns>List of Lists with x and y indexes.</returns> private List <List <int> > NotNull(CellsGrid grid) { List <List <int> > tempList = new List <List <int> >(); for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (grid[x, y] != 0) { tempList.Add(new List <int> { x, y }); } } } return(tempList); }
public Generator() { grid = new CellsGrid(); solver = new Solver(grid); random = new Random(); XElement element; using (Stream reader = new FileStream("..\\..\\..\\Data\\solved.xml", FileMode.Open)) { element = XElement.Load(reader); } var tempList = element.Descendants("sudoku").ToList().Select(d => { d.Value.Trim(); return(d.Value.Split("\n").Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x.ToString()))); }) .ToArray().Select(x => x.Select(y => y.Split(" ").Select(d => int.Parse(d)))).ToArray(); var temp = tempList[random.Next(tempList.Length)]; int x = 0; int y = 0; foreach (var item in temp) { if (x > 8) { x = 0; } foreach (var num in item) { if (y > 8) { y = 0; } grid[x, y] = num; y++; } x++; } DebugGridPrint(); }
/// <summary> /// Tries to generate random sudoku. Older algorithm. /// </summary> /// <param name="difficulty">Dificulty parameter</param> private void GenerateHelp2(int difficulty) { int left = 20; switch (difficulty) { case 0: left = 25; break; case 1: left = 24; break; case 2: left = 24; break; } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int reset = 0; CellsGrid gridTested = grid.TrueClone(); Solver solver = new Solver(gridTested); while (reset < 100) { reset++; while (gridTested.Count > left) { gridTested[Next(), Next()] = 0; } solver.Grid = gridTested.TrueClone(); switch (difficulty) { case 0: solver.SolveAll(true, true, 4, 4); //solver.SolveEasy(); break; case 1: solver.SolveAll(true, true, 0, 4); //solver.SolveMedium(); break; case 2: solver.SolveAll(true, true, 4, 0); //solver.SolveHard(); break; } if (solver.IsSolved()) { break; } gridTested = grid.TrueClone(); Debug.Print(reset.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); } Generated = gridTested.TrueClone(); stopwatch.Stop(); Debug.Print(reset.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); }
/// <summary> /// Generates sudoku into Generated property. /// </summary> /// <param name="difficulty">Relative difficulty of generated sudoku</param> private void GenerateHelpTestingOnly(Difficulty difficulty, int left, int returning) { int resetsMax = 300; CellsGrid gridTested = grid.TrueClone(); CellsGrid gridSolved = grid.TrueClone(); List <List <int> > NotNullList; int resets = 1; int iterations = 0; int last = 0; int backDebug = 0; Solver solver = new Solver(gridTested); for (; ;) { if (Generated.Count <= left) { return; //Stops generating if any other thread generated } if (gridSolved.Count <= left) { if (new Solver(gridSolved).GetDifficulty() == difficulty) { break; } } if (resets >= resetsMax) { break; } iterations++; NotNullList = NotNull(gridTested); List <int> item = NotNullList[random.Next(NotNullList.Count)]; gridTested[item[0], item[1]] = 0; solver.Grid = gridTested.TrueClone(); switch (difficulty) { case Difficulty.Easy: solver.SolveEasy(); break; case Difficulty.Medium: solver.SolveMedium(); break; case Difficulty.Hard: solver.SolveHard(); break; } if (solver.IsSolved()) { gridSolved = gridTested.TrueClone(); last = 0; } else { gridTested = gridSolved.TrueClone(); backDebug++; last++; if (last > gridSolved.Count / returning) { backDebug = 0; iterations = 0; resets++; gridTested = grid.TrueClone(); gridSolved = grid.TrueClone(); } } } Generated = gridSolved.TrueClone(); }
/// <summary> /// Generates sudoku into Generated property. /// </summary> /// <param name="difficulty">Relative difficulty of generated sudoku</param> /// <param name="offset">Subtract from left numbers to create harder sudoku, CPU intensive</param> private void GenerateHelp(int difficulty, int offset = 0) { int left = 20; switch (difficulty) { case 0: left = 25 - offset; break; case 1: left = 24 - offset; break; case 2: left = 24 - offset; break; } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); CellsGrid gridTested = grid.TrueClone(); CellsGrid gridSolved = grid.TrueClone(); List <List <int> > NotNullList; int resets = 1; int iterations = 0; int last = 0; int backDebug = 0; Solver solver = new Solver(gridTested); while (gridSolved.Count > left && resets < 30) { if (Generated.Count <= left) { return; //Stops generating if any other thread generated } iterations++; NotNullList = NotNull(gridTested); List <int> item = NotNullList[random.Next(NotNullList.Count)]; gridTested[item[0], item[1]] = 0; solver.Grid = gridTested.TrueClone(); switch (difficulty) { case 0: //solver.SolveAll(true, true, 4, 4); solver.SolveEasy(); break; case 1: //solver.SolveAll(true, true, 0, 4); solver.SolveMedium(); break; case 2: //solver.SolveAll(true, true, 2, 0); solver.SolveHard(); break; } if (solver.IsSolved()) { gridSolved = gridTested.TrueClone(); last = 0; } else { gridTested = gridSolved.TrueClone(); backDebug++; last++; if (last > gridSolved.Count / 2) { Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); stopwatch.Restart(); backDebug = 0; iterations = 0; resets++; gridTested = grid.TrueClone(); gridSolved = grid.TrueClone(); } } } Generated = gridSolved.TrueClone(); stopwatch.Stop(); Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); }
public Validator(CellsGrid inputGrid) { grid = inputGrid; }
public int[] ShowNext(CellsGrid inputGrid, Difficulty difficulty) { bool possiblePair = true; int hidden = 0; int same = 0; switch (difficulty) { case Difficulty.Easy: possiblePair = false; break; case Difficulty.Medium: same = 2; break; case Difficulty.Hard: hidden = 4; same = 4; break; } Grid = inputGrid.TrueClone(); //Adding numbers to possible. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { Intersect(x, y); } } } //Removing numbers from possible. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] != 0) { RemovePossible(x, y); } } } if (possiblePair) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemovePair(x, y); } } } } if (hidden != 0) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemoveHidden(x, y); if (hidden > 2) { RemoveHidden(x, y, 3); } if (hidden > 3) { RemoveHidden(x, y, 4); } } } } } if (same != 0) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemoveSame(x, y); if (same > 2) { RemoveSame(x, y, 3); } if (same > 3) { RemoveSame(x, y, 4); } } } } } //Adding numbers to grid. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { if (Count(x, y)) { return(new int[] { x, y, Grid[x, y] }); } else if (AlonePossible(x, y)) { return(new int[] { x, y, Grid[x, y] }); } } } } return(new int[] { -1, -1 }); }
/// <summary> /// Solves a sudoku with different parameters. /// </summary> /// <param name="possibleAlone">Use possibleAlone method.</param> /// <param name="possiblePair">Use possiblePair method.</param> /// <param name="hidden">Use removeHidden method.</param> /// <param name="debug">Steps outputing into debugging console.</param> /// <returns></returns> public int SolveAll(bool possibleAlone = true, bool possiblePair = true, int hidden = 0, int same = 0, bool debug = false) { this.debug = debug; bool changed = false; int changedCounter = 0; int iteration = 0; DebugGridPrint(); //for (int x = 0; x < 9; x++) for (int y = 0; y < 9; y++) if (Grid[x, y] != 0) possible[x][y].Add(Grid[x, y]); for (; ;) { //Adding numbers to possible. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { Intersect(x, y); } } } //Removing numbers from possible. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] != 0) { RemovePossible(x, y); } } } if (possiblePair) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemovePair(x, y); } } } } if (hidden != 0) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemoveHidden(x, y); if (hidden > 2) { RemoveHidden(x, y, 3); } if (hidden > 3) { RemoveHidden(x, y, 4); } } } } } if (same != 0) { for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { RemoveSame(x, y); if (same > 2) { RemoveSame(x, y, 3); } if (same > 3) { RemoveSame(x, y, 4); } } } } } //Adding numbers to grid. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (Grid[x, y] == 0) { if (Count(x, y)) { changed = true; DebugGridPrint("COUNT X: " + x + " Y: " + y + " NUM: " + Grid[x, y]); Steps.Add(Grid.Clone()); } else if (possibleAlone && AlonePossible(x, y)) { changed = true; Steps.Add(Grid.Clone()); } } } } //Ends loop if nothing is added 10 iterations in row. if (changed) { changedCounter = 0; } else { changedCounter++; } if (changedCounter >= 10) { break; } changed = false; if (IsSolved()) { if (debug) { Debug.Print("Solved"); string helper = ""; for (int x = 0; x < 9; x++) { helper = ""; for (int y = 0; y < 9; y++) { helper += Grid[x, y].ToString() + " "; } Debug.Print(helper); } Debug.Print(""); } break; } iteration++; } SolvedGrid = Grid.Clone(); return(iteration); }
/// <summary> /// Generates sudoku into Generated property. /// </summary> /// <param name="difficulty">Relative difficulty of generated sudoku</param> /// <param name="offset">Subtract from left numbers to create harder sudoku, CPU intensive</param> private void GenerateHelp3(Difficulty difficulty) { int resetsMax = 300; int left = 30; int returning = 2; switch (difficulty) { case Difficulty.Easy: left = 25; returning = 2; break; case Difficulty.Medium: left = 26; returning = 3; break; case Difficulty.Hard: left = 35; returning = 7; break; } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); CellsGrid gridTested = grid.TrueClone(); CellsGrid gridSolved = grid.TrueClone(); List <List <int> > NotNullList; int resets = 1; int iterations = 0; int last = 0; int backDebug = 0; Solver solver = new Solver(gridTested); for (; ;) { if (Generated.Count <= left) { return; //Stops generating if any other thread generated } if (gridSolved.Count <= left) { if (new Solver(gridSolved).GetDifficulty() == difficulty) { break; } } if (resets >= resetsMax) { break; } iterations++; NotNullList = NotNull(gridTested); List <int> item = NotNullList[random.Next(NotNullList.Count)]; gridTested[item[0], item[1]] = 0; solver.Grid = gridTested.TrueClone(); switch (difficulty) { case Difficulty.Easy: solver.SolveEasy(); break; case Difficulty.Medium: solver.SolveMedium(); break; case Difficulty.Hard: solver.SolveHard(); break; } if (solver.IsSolved()) { gridSolved = gridTested.TrueClone(); last = 0; } else { gridTested = gridSolved.TrueClone(); backDebug++; last++; if (last > gridSolved.Count / returning) { Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); stopwatch.Restart(); backDebug = 0; iterations = 0; resets++; gridTested = grid.TrueClone(); gridSolved = grid.TrueClone(); } } } Generated = gridSolved.TrueClone(); stopwatch.Stop(); Debug.Print(resets.ToString() + "\t" + backDebug.ToString() + "\t" + iterations.ToString() + "\t" + gridSolved.Count.ToString() + "\t" + stopwatch.ElapsedMilliseconds.ToString()); }