protected override bool isSolution(IState state) { SudokuState s = (SudokuState)state; return(s.Rozwiazanie()); // return state.H == 0.0; }
public SudokuState(SudokuState parent, int newValue, int x, int y) : base(parent) { this.table = new int[GRID_SIZE, GRID_SIZE]; // Skopiowanie stanu sudoku do nowej tabeli Array.Copy(parent.table, this.table, this.table.Length); // Ustawienie nowej wartosci w wybranym polu sudoku this.table[x, y] = newValue; StringBuilder builder = new StringBuilder(parent.id); builder[x * GRID_SIZE + y] = (char)(newValue + 48); this.id = builder.ToString(); this.h = ComputeHeuristicGrade(x, y, false); //Tworzymy tablice heurystyk komórek węzła z Talicy for (int i = 0; i < GRID_SIZE; ++i) { for (int j = 0; j < GRID_SIZE; ++j) { this.heuristic_array[i, j] = ComputeHeuristicGrade(i, j, true); } } //Console.Clear(); //this.Print(); //Thread.Sleep(15); }
static void Main(string [] args) { Stopwatch sw = Stopwatch.StartNew(); //string sudokuPattern = "123456789123456789123456789123456789123456789123456789123456789123456789123456789"; //sudoku w postaci stringa np.: " 010330218... " //string sudokuPattern = "294167358315489627678253491456312879983574216721698534562941783839726145147835962"; //sudoku w postaci stringa np.: " 010330218... " string sudokuPattern = "204107358315489627678053491406302879983004216721698534002941783039726045147835062"; //sudoku w postaci stringa np.: " 010330218... " //string sudokuPattern = "004100308010000620008200400000302809000070000701608000562001703030000040100005000"; SudokuState startState = new SudokuState(sudokuPattern); SudokuSearch searcher = new SudokuSearch(startState); searcher.DoSearch(); IState state = searcher.Solutions [0]; List <SudokuState> solutionPath = new List <SudokuState>(); while (state != null) { solutionPath.Add(( SudokuState )state); state = state.Parent; } solutionPath.Reverse(); foreach (SudokuState s in solutionPath) { s.Print(); } sw.Stop(); Console.WriteLine("Czas: " + sw.ElapsedMilliseconds + "ms"); Console.ReadKey(); }
public static void start(string sudokuPattern) { Stopwatch stopWatch_search = new Stopwatch(); Stopwatch stopWatch_print = new Stopwatch(); SudokuState startState = new SudokuState(sudokuPattern); SudokuSearch searcher = new SudokuSearch(startState); stopWatch_search.Start(); searcher.DoSearch(); stopWatch_search.Stop(); TimeSpan t_search = stopWatch_search.Elapsed; IState state = searcher.Solutions[0]; List <SudokuState> solutionPath = new List <SudokuState>(); while (state != null) { solutionPath.Add((SudokuState)state); state = state.Parent; } solutionPath.Reverse(); int[,] table_tmp1 = new int[9, 9]; int[,] table_tmp2 = new int[9, 9]; table_tmp1 = solutionPath[0].Table; stopWatch_print.Start(); foreach (SudokuState s in solutionPath) { table_tmp2 = table_tmp1; table_tmp1 = s.Table; s.Print(table_tmp2, table_tmp1); } stopWatch_print.Stop(); TimeSpan t_print = stopWatch_print.Elapsed; string SearchTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", t_search.Hours, t_search.Minutes, t_search.Seconds, t_search.Milliseconds / 10); Console.WriteLine("Czas przeszukiwania " + SearchTime); string PrintTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", t_print.Hours, t_print.Minutes, t_print.Seconds, t_print.Milliseconds / 10); Console.WriteLine("Czas wyswietlania " + PrintTime); }
//Konstruktor tworzący stany potomne na podstawie rodzica //Kopiuje pola stanu rodzicielskiego, wstawia nową wartość i oblicza wartość heurystyczną nowego stanu public SudokuState(SudokuState parent, int newValue, int x, int y) : base(parent) { this.table = new int[GRID_SIZE, GRID_SIZE]; Array.Copy(parent.table, this.table, this.table.Length); this.table[x, y] = newValue; StringBuilder builder = new StringBuilder(parent.id); builder[x * GRID_SIZE + y] = (char)(newValue + 48); this.id = builder.ToString(); this.h = ComputeHeuristicGrade(); }
protected override void buildChildren(IState parent) { SudokuState state = (SudokuState)parent; // poszukiwanie wolnego pola for (int i = 1; i < 10; i++) { if (state._tab[i] == 0) { SudokuState child = new SudokuState(state, i, state._x, state._y); parent.Children.Add(child); } } }
public SudokuState(SudokuState aParent, int aRows, int aColumns, int aNumber) // tworzymy stan jako dziecko stanu rodzicielskiego (analogicznie jak np. w drzewie BST) { // stan taki bedzie identyczny jak jego rodzic z tym, ze 1 komorka bedzie inna (liczba ktora dodalismy na plansze w jakiejs kratce) this.board = new int[9, 9]; for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { this.board [i, j] = aParent.board [i, j]; // kopiujemy plansze od rodzica } } this.Parent = aParent; // ustawiamy, ze rodzic tego stanu to podany aParent this.board[aRows, aColumns] = aNumber; // ustawiamy dana komorke planszy na inna wartosc, okresla ja aNumber aParent.Children.Add(this); // ustawiamy w rodzicu, ze ten stan bedzie jednym z jego dzieci this.h = ComputeHeuristicGrade(); // obliczamy heurystyke tego stanu }
protected override void buildChildren(IState parent) { SudokuState state = (SudokuState)parent; state.findBeginField(useAdvancedHeuristic); for (int k = 1; k < SudokuState.GRID_SIZE + 1; k++) { //Console.Write(String.Format("k: {0}, xy({1},{2})\n", k, state.xyBegin[0], state.xyBegin[1])); if (state.isNumberCorrect(k, state.xyBegin[0], state.xyBegin[1])) { SudokuState child = new SudokuState(state, k, state.xyBegin[0], state.xyBegin[1]); parent.Children.Add(child); } } return; }
public SudokuState(SudokuState parent, int newValue, int x, int y) : base(parent) { this.table = new int[GRID_SIZE, GRID_SIZE]; // Skopiowanie stanu sudoku do nowej tabeli Array.Copy(parent.table, this.table, this.table.Length); // Ustawienie nowej wartosci w wybranym polu sudoku this.table[x, y] = newValue; // Utworzenie nowego id odpowiadajacemu aktualnemu stanowi planszy StringBuilder builder = new StringBuilder(parent.id); builder[x * GRID_SIZE + y] = (char)(newValue + 48); this.id = builder.ToString(); this.h = ComputeHeuristicGrade(); }
static void Main(string[] args) { //string sudokuPattern = "000079065000003002005060093340050106000000000608020059950010600700600000820390000"; string sudokuPattern = "002008050000040070480072000008000031600080005570000600000960048090020000030800900"; // String sudokuPattern = "219685743400000001800000005600000007547218936900000004100000008700000009386549172"; SudokuState startState = new SudokuState(sudokuPattern); startState.Print(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); SudokuSearch searcher = new SudokuSearch(startState); searcher.DoSearch(); IState state = searcher.Solutions [0]; List <SudokuState> solutionPath = new List <SudokuState>(); while (state != null) { solutionPath.Add(( SudokuState )state); state = state.Parent; } stopwatch.Stop(); solutionPath.Reverse(); foreach (SudokuState s in solutionPath) { Console.Clear(); s.Print(); Console.ReadKey(); } Console.WriteLine(); Console.WriteLine("Czas obliczen: {0}", stopwatch.Elapsed); Console.ReadKey(); }
static void sudoku(bool UseAdvancedSearch) { string[] heuristicType = { "Simple", "Advanced" }; string[] hash = { "800030000930007000071520900005010620000050000046080300009076850060100032000040006", "000000600600700001401005700005900000072140000000000080326000010000006842040002930", "457682193600000007100000004200000006584716239300000008800000002700000005926835471", "000012034000056017000000000000000000480000051270000048000000000350061000760035000", "000700800000040030000009001600500000010030040005001007500200600030080090007000002", "100040002050000090008000300000509000700080003000706000007000500090000040600020001", "600040003010000070005000800000502000300090002000103000008000900070000050200030004", "000000000000003085001020000000507000004000100090000000500000073002010000000040009", "000040700080000000010000020000800006700000050400000200302070000000000000000006018" }; string SudokuPattern; int m = getInt("Choice Sudoku: "); SudokuPattern = hash[(m > hash.Length ? hash.Length - 1 : m)]; SudokuState startState = new SudokuState(SudokuPattern); SudokuSearch searcher = new SudokuSearch(startState, UseAdvancedSearch); searcher.DoSearch(); IState state = searcher.Solutions[0]; List <SudokuState> solutionPath = new List <SudokuState>(); while (state != null) { solutionPath.Add((SudokuState)state); state = state.Parent; } solutionPath.Reverse(); foreach (SudokuState s in solutionPath) { s.Print(); } string data = string.Format("{0} heuristic: \nSteps: {1}, \ncreated {2} board objects", heuristicType[UseAdvancedSearch ? 0 : 1], solutionPath.Count, SudokuState.counter); Console.Write(data); Console.Write("\nOpen: " + searcher.Open.Count); Console.Write("\nClose: " + searcher.Closed.Count); Console.Write("\n\nPress key to menu -> "); // Cleaning SudokuState.counter = 0; SudokuState.slowdown = false; }
} // dziedziczy cały konstruktor po AStartSearch protected override void buildChildren(IState parent) { SudokuState state = (SudokuState)parent; // Każdy węzeł ma swoją tablice heurystyczna tworzoną w jego kontruktorze. double F_max = 0; for (int i = 0; i < SudokuState.GRID_SIZE; ++i) { for (int j = 0; j < SudokuState.GRID_SIZE; ++j) { if ((state.Heuristic_array[i, j] > F_max) && (state.Heuristic_array[i, j] != state.infinity)) { F_max = state.Heuristic_array[i, j]; } } } for (int m = 1; m <= F_max; m++)// nie wiem czy m od 0 czy od 1 { for (int i = 0; i < SudokuState.GRID_SIZE; ++i) { for (int j = 0; j < SudokuState.GRID_SIZE; ++j) { //ważne aby rodzic dzieci tylko w pustych miejscach - inaczej bedziemy mieli konflikt id if ((state.Heuristic_array[i, j] == m)) { for (int k = 1; k < SudokuState.GRID_SIZE + 1; ++k) { SudokuState child = new SudokuState(state, k, i, j); parent.Children.Add(child); } break; //zastanawia mnie ten break; po co wychodzi } } } } }
protected override void buildChildren(IState parent) { SudokuState state = (SudokuState)parent; //Pobranie stanu rodzicielskiego, z którego tworzymy stany potomne List <SudokuField> minMovesFields = new List <SudokuField>(); //Lista pól wymagających najmniej ruchów SudokuField minMovesField = state.emptyFields[0]; //Pobranie pierwszego pustego pola ze stanu rodzicielskiego //Wyszukiwanie pola wymagającego najmniej ruchów for (int i = 1; i < state.emptyFields.Count; ++i) { if (state.emptyFields[i].availableMoves.Count < minMovesField.availableMoves.Count) { minMovesField = state.emptyFields[i]; } } minMovesFields.Add(minMovesField); //Zapisanie pierwszego pola wymagającego najmniej ruchów //Wyszukiwanie pól wymagających tyle samo ruchów foreach (SudokuField i in state.emptyFields) { if (i != minMovesField) { if (i.availableMoves.Count == minMovesField.availableMoves.Count) { minMovesFields.Add(i); } } } //Lista minMovesFields zawiera pola wymagające najmniej ruchów //Tworzenie nowych stanów potomnych: foreach (SudokuField i in minMovesFields) //dla wszystkich pustych pól o minimanej liczbie ruchów { foreach (int j in i.availableMoves) //dla każdego możliwego ruchu (zawsza taka sama ilość dla konkretnego stanu rodzicielskiego) { SudokuState child = new SudokuState(state, j, i.row, i.col); // parent, value, row, col parent.Children.Add(child); } } }
static void Main(string[] args) { SudokuState theState = new SudokuState("800030000930007000071520900005010620000050000046080300009076850060100032000040006"); SudokuSearch theSearcher = new SudokuSearch(theState); // tworzymy szukacz na podstawie pierwszego stanu theSearcher.DoSearch(); // szukacz wykonuje algorytm A* znajduje droge od pierwszego stanu do rozwiazania List <SudokuState> states = new List <SudokuState>(); // tworzymy liste stanow SudokuState theResult = (SudokuState)theSearcher.Solutions[0]; // do zmiennej theResult przypisujemy stan z rozwiazaniem znalezionym przez szukacz while (theResult != null) // do kolejnych elementow listy states wpisujemy kolejne stany po drodze od stanu poczatkowego do rozwiazania { states.Add(theResult); theResult = (SudokuState)theResult.Parent; } for (int i = states.Count() - 1; i > 0; --i) // od tylu wypisujemy stany; od poczatku do rozwiazania { states.ElementAt(i).Write(); Console.WriteLine("Jeszcze " + i + " stanow do rozwiazania"); Thread.Sleep(300); Console.Clear(); // czyscimy konsole } states.ElementAt(0).Write(); // wypisujemy ostateczne rozwiazanie na sam koniec }
protected override void buildChildren(IState parent) { SudokuState state = ( SudokuState )parent; // poszukiwanie wolnego pola //Console.WriteLine("trzy"); for (int i = 0; i < SudokuState.GRID_SIZE; ++i) { for (int j = 0; j < SudokuState.GRID_SIZE; ++j) { if (state.Table[i, j] == 0) { // wstawianie kolejnych potomkow w wolne pole for (int k = 1; k < SudokuState.GRID_SIZE + 1; ++k) { SudokuState child = new SudokuState(state, k, i, j); parent.Children.Add(child); } break; } } } }
public SudokuSearch(SudokuState aState) : base(aState, true, true) { }
public SudokuSearch(SudokuState state, bool advancedHeuristic = false) : base(state) { useAdvancedHeuristic = advancedHeuristic; state.findBeginField(useAdvancedHeuristic); }
static void Main(string[] args) { Console.BufferHeight = 1000; DialogResult dialogResult_sudoku = MessageBox.Show("Chesz zobaczyć sudoku? ( ͡° ͜ʖ ͡°)", "", MessageBoxButtons.YesNo); if (dialogResult_sudoku == DialogResult.Yes) { string sudokuPattern = "083279465409583710270461893342058176597106284618720359954812037701645908826397540"; // sudoku w postaci stringa np .:" 010330218... " #region test //040000065469583712275461893342958176597136284618724359954812637731645928826397541 //183279465469583712275461893342958176597136284618724359954812637731645928826397541 /*"040 000 065 * 469 583 712 * 275 461 893 * * 342 958 176 * 597 136 284 * 618 724 359 * * 954 812 637 * 731 645 928 * 826 397 541" */ //000000465469583712275461893342958176597136284618724359954812637731645928826397541 //000079065000003002005060093340050106000000000608020059950010600700600000820390000 #endregion //test SudokuState.start(sudokuPattern); Console.ReadLine(); } DialogResult dialogResult_puzzle = MessageBox.Show("A puzzle? ( ͡° ͜ʖ ͡°)", "", MessageBoxButtons.YesNo); if (dialogResult_puzzle == DialogResult.Yes) { int puzzlesize = 3; PuzzleState.PuzzleSize = puzzlesize; Laboratory1_m.PuzzleState.PuzzleSize = puzzlesize; gen(); Stopwatch stopWatch_tails = new Stopwatch(); stopWatch_tails.Start(); PuzzleState.start(puzzlesize); stopWatch_tails.Stop(); Stopwatch stopWatch_man = new Stopwatch(); stopWatch_man.Start(); Laboratory1_m.PuzzleState.start(puzzlesize); stopWatch_man.Stop(); TimeSpan t_search = stopWatch_tails.Elapsed; string SearchTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", t_search.Hours, t_search.Minutes, t_search.Seconds, t_search.Milliseconds / 10); Console.WriteLine("Calkowity czas tails: " + SearchTime); t_search = stopWatch_man.Elapsed; SearchTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", t_search.Hours, t_search.Minutes, t_search.Seconds, t_search.Milliseconds / 10); Console.WriteLine("Calkowity czas man: " + SearchTime); Console.ReadLine(); } }
public SudokuSearch(SudokuState state) : base(state, true, true) { } // dziedziczy cały konstruktor po AStartSearch
public SudokuSearch(SudokuState state) : base(state) { }
static void Main(string[] args) { bool puzzle = true; bool sudoku = false; if (sudoku) { List <string> sudokuPatterns = new List <string>(); sudokuPatterns.Add("800030000930007000071520900005010620000050000046080300009076850060100032000040006"); sudokuPatterns.Add("000000600600700001401005700005900000072140000000000080326000010000006842040002930"); sudokuPatterns.Add("457682193600000007100000004200000006584716239300000008800000002700000005926835471"); //sudokuPatterns.Add("000012034000056017000000000000000000480000051270000048000000000350061000760035000"); //not enough memory //sudokuPatterns.Add("000700800000040030000009001600500000010030040005001007500200600030080090007000002"); //not enough memory //sudokuPatterns.Add("100040002050000090008000300000509000700080003000706000007000500090000040600020001"); //not enough memory foreach (string pattern in sudokuPatterns) { //Sprawdzenie ilości pustych pól int emptyFieldsCount = 0; for (int i = 0; i < pattern.Length; ++i) { if (pattern[i] == '0') { emptyFieldsCount++; } } SudokuState startState = new SudokuState(pattern); //Stan startowy SudokuSearch searcher = new SudokuSearch(startState); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); searcher.DoSearch(); watch.Stop(); IState state = searcher.Solutions[0]; List <SudokuState> solutionPath = new List <SudokuState>(); while (state != null) { solutionPath.Add((SudokuState)state); state = state.Parent; } solutionPath.Reverse(); foreach (SudokuState s in solutionPath) { s.Print(); Console.WriteLine(); } Console.WriteLine("Empty fields count: {0}", emptyFieldsCount); Console.WriteLine("States count in Open: {0}", searcher.Open.Count); Console.WriteLine("States count in Closed: {0}", searcher.Closed.Count); Console.WriteLine("Time: {0}s", watch.ElapsedMilliseconds / 1000.0); Console.ReadKey(); } } if (puzzle) { const int TESTS_NUMBER = 100; Console.WriteLine("Creating {0} puzzles.", TESTS_NUMBER); PuzzleState[] startStatesMisplaced = new PuzzleState[TESTS_NUMBER]; PuzzleState[] startStatesManhattan = new PuzzleState[TESTS_NUMBER]; Random random = new Random(); for (int i = 0; i < TESTS_NUMBER; ++i) //Tworzenie 100 stanów startowych puzzli { startStatesMisplaced[i] = new PuzzleState(random, true); startStatesManhattan[i] = new PuzzleState(startStatesMisplaced[i], false); } double misplacedTilesTimeSum = 0.0; double manhattanTimeSum = 0.0; long misplacedTilesOpenSum = 0; long misplacedTilesClosedSum = 0; long manhattanOpenSum = 0; long manhattanClosedSum = 0; double misplacedTilesPathLength = 0.0; double manhattanPathLength = 0.0; Console.WriteLine("Attempting to solve the puzzles using Misplaced Tiles heuristic:"); for (int i = 0; i < TESTS_NUMBER; ++i) { Console.WriteLine("Puzzle no. " + i); PuzzleSearch searcher = new PuzzleSearch(startStatesMisplaced[i]); searcher.DoSearch(); IState state = searcher.Solutions[0]; List <PuzzleState> solutionPath = new List <PuzzleState>(); while (state != null) { solutionPath.Add((PuzzleState)state); state = state.Parent; } solutionPath.Reverse(); foreach (PuzzleState s in solutionPath) { s.Print(); Console.WriteLine(); } System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); searcher.DoSearch(); watch.Stop(); misplacedTilesTimeSum += watch.ElapsedMilliseconds; misplacedTilesOpenSum += searcher.Open.Count; misplacedTilesClosedSum += searcher.Closed.Count; misplacedTilesPathLength += searcher.Solutions[0].G; Console.WriteLine("\tNumber of states in Open set: " + searcher.Open.Count); Console.WriteLine("\tNumber of states in Closed set: " + searcher.Closed.Count); Console.WriteLine("\tSolution path length: " + searcher.Solutions[0].G); Console.WriteLine("\tElapsed time: {0}s.", watch.ElapsedMilliseconds / 1000.0); } Console.WriteLine(); Console.WriteLine("Attempting to solve the puzzles using Manhattan heuristic: "); for (int i = 0; i < TESTS_NUMBER; ++i) { Console.WriteLine("Puzzle no. {0}.", i + 1); PuzzleSearch searcher = new PuzzleSearch(startStatesManhattan[i]); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); searcher.DoSearch(); watch.Stop(); manhattanTimeSum += watch.ElapsedMilliseconds; manhattanOpenSum += searcher.Open.Count; manhattanClosedSum += searcher.Closed.Count; manhattanPathLength += searcher.Solutions[0].G; Console.WriteLine("\tNumber of states in Open set: " + searcher.Open.Count); Console.WriteLine("\tNumber of states in Closed set: " + searcher.Closed.Count); Console.WriteLine("\tSolution path length: " + searcher.Solutions[0].G); Console.WriteLine("\tElapsed time: {0}s.", watch.ElapsedMilliseconds / 1000.0); } Console.WriteLine(); Console.WriteLine("Misplaced Tiles heuristic: "); Console.WriteLine("\tAverage time: {0}s.", misplacedTilesTimeSum / 1000.0 / TESTS_NUMBER); Console.WriteLine("\tAverage Open states number: " + misplacedTilesOpenSum / TESTS_NUMBER); Console.WriteLine("\tAverage Closed states number: " + misplacedTilesClosedSum / TESTS_NUMBER); Console.WriteLine("\tAverage solution path length: " + misplacedTilesPathLength / TESTS_NUMBER); Console.WriteLine(); Console.WriteLine("Manhattan heuristic: "); Console.WriteLine("\tAverage time: {0}s.", manhattanTimeSum / 1000.0 / TESTS_NUMBER); Console.WriteLine("\tAverage Open states number: " + manhattanOpenSum / TESTS_NUMBER); Console.WriteLine("\tAverage Closed states number: " + manhattanClosedSum / TESTS_NUMBER); Console.WriteLine("\tAverage solution path length: " + manhattanPathLength / TESTS_NUMBER); Console.ReadKey(); } }
protected override void buildChildren(IState aParent) { SudokuState state = (SudokuState)aParent; int x = 0; int y = 0; int [] tab; int [] tab2 = new int[9]; for (int i = 0; i < 9; ++i) { tab2[i] = 0; } int spr, tmp = 0; for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { tab = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; spr = 0; if (state.Board[i, j] == 0) { for (int k = 0; k < 9; ++k) { if (state.Board [i, k] != 0 && k != j) { tab[state.Board[i, k] - 1] = 0; } if (state.Board [k, j] != 0 && k != i) { tab[state.Board[k, j] - 1] = 0; } for (int l = 0; l < 9; ++l) { if (k == i && l == j) { continue; } if (i <= 2 && k > 2) { continue; } if (j <= 2 && l > 2) { continue; } if (i > 2 && i <= 5 && (k <= 2 || k > 5)) { continue; } if (j > 2 && j <= 5 && (l <= 2 || l > 5)) { continue; } if (i > 5 && k <= 5) { continue; } if (j > 5 && l <= 5) { continue; } if (state.Board[k, l] != 0) { tab[state.Board[k, l] - 1] = 0; } } } for (int k = 0; k < 9; ++k) { if (tab[k] == 0) { ++spr; } } if (spr > tmp) { tmp = spr; x = i; y = j; tab2 = tab; } } } } for (int i = 0; i < 9; ++i) { if (tab2[i] != 0) { new SudokuState(state, x, y, tab2[i]); } } }