Dokumentacja symulatora Sudoku
Transkrypt
Dokumentacja symulatora Sudoku
Mariusz Żbikowski Warszawa,07.05.2007 Programowanie Zdarzeniowe(PROZ) Projekt własny - gra SUDOKU Dokumentacja końcowa 1.Cel projektu i wstępne założenia Celem projektu jest stworzenie aplikacji umożliwiającej grę w Sodoku. Celem gry jest takie ułożenie cyfr od 1 do 9 na planszy (o rozmiarach 9x9, złożonej z 9ciu kwadratów 3x3), aby: -żadna cyfra nie powtarzała się w linii lub wierszu, -cyfry nie powtarzały się w żadnym z kwadratów 3x3. 2.Wygląd aplikacji i opis dziania Główne okno aplikacji Grę rozpoczyna się naciskając kursorem myszy przycisk Start. Na pasku po prawej znajduje od góry zegar (TIME) , licznik punktów SCORE (zmniejszający się wraz z upływem czasu, liczbą błędnie wpisanych cyfr w puste pola ). Na dole paska znajdują się poziomy gry. Poziom wybiera się najeżdżając kursorem myszy. Wybrany poziom podświetli się na szaro. Oczywiście im wyższy poziom tym można zdobyć więcej punktów. Przykładowa plansza Po naciśnięciu przycisku Start użytkownik rozpoczyna grę. Ma do wyboru: Pause – możliwość zatrzymania gry bez konieczności zamykania aplikacji. Create- wygenerowanie nowe planszy. Hint – włączenie trybu podpowiedzi ułatwiającej rozwiązanie SUDOKU. Solve – odkrycie wszystkich pól czyli rozwiązanie SUDOKU. Edit – możliwość stworzenia własnej planszy (opcja dodatkowa) Dodano tę opcje, gdyż jest to znakomita możliwość treningu. Okazuje się bowiem, iż nie jest tak prosto stworzyć własną planszę SUDOKU !!! High Scores – wyświetlenie okna z najlepszymi wynikami użytkownika. Exit –wyjście z aplikacji. Chcąc wprowadzić cyfrę w odpowiednie pole należy najechać kursorem myszki na nie i wprowadzić z klawiatury odpowiednią wartość. W pole można wprowadzić wyłącznie cyfry 1-9 Plansza jest wygenerowane na podstawie algorytmu generacji planszy SUDOKU zaczerpniętego z literatury. Podobnie opcja Solve opiera się na sprawdzonym algorytmie rozwiązywania Sudoku. Dołożyłem starań, aby aplikacja była przyjazna użytkownikowi Aplikacja wspiera użytkownika w rozwiązywaniu Sudoku. Jeżeli wprowadzono błędną cyfrę (niezgodność z regułami Sudoku) jest ona podkreślana na czerwono i nie można wprowadzić żadnej innej cyfry. Rozwiązanie to pozwala zaoszczędzić czas użytkownika na dalsze rozwiązywanie Sudoku z góry skazane na niepowodzenie. Wprowadzenie błędnej cyfry Przewidziałem możliwość podpowiedzi po naciśnięciu przycisku Hint Wiąże sie to oczywiście ze pewną stratą punktów Próba stworzenia własnej planszy Sudoku jest doskonałym treningiem umysłowym. Aplikacja także tutaj wspiera użytkownika i podkreśla na czerwono niewłaściwie wprowadzono cyfrę (niezgodność z regułami Sudoku) lub określony wybór powoduje niemożność rozwiązania planszy (zblokowanie). Użytkownik uświadamia sobie wtedy, że o wiele łatwiej jest rozwiązać plansze Sudoku niż ją stworzyć. To spostrzeżenie potwierdza teoria, gdyż algorytm rozwiązywania Sudoku jest o wiele prostszy niż algorytm generacji planszy Sudoku. Dlatego też zaprojektowany przeze mnie generator generuje jedną planszę Sudoku, której opis generacji znalazłem w literaturze. Użytkownik naciskając na przycisk Create otrzymuje zawsze ta właśnie plansze tylko za każdym naciśnięciem przycisku Create inne pola są dane a inne czyszczone. Zaimplementowany algorytm rozwiązywania Sudoku opiera sie w skrócie na wylosowaniu pustego pola i stwierdzeniu ile można wpisać tu cyfr(entropia), żeby nie naruszać reguł Sudoku. Następnie należy sprawdzić czy któreś z pól w pionie, poziomie lub placu wybranego pola nie ma mniejszej entropi (w szczególności 1) . Jeżeli entropia wynosi 1 to pole te się uzupełnia. W polu o najmniejszej entropi trzeba przyjąć jedną z dozwolonych cyfr i tak dalej należy uzupełniać puste pola przyjmując dozwolone cyfry, aż wszystkie pola będą uzupełnione i reguły Sudoku będą zachowane. Jeżeli dojdzie do zblokowania należy sie cofnąć i zmienić wcześniej założoną cyfrę na inną dozwoloną. Próba stworzenia własnej planszy Okno z najlepszymi wynikami 3.Ważniejsze klasy i ich metody Projekt został wykonany w oparciu o metody i klasy biblioteki Swing. Klasa aplikacji zawierająca funkcje main public class Sudoku Tworzony w funkcji main jest obiekt klasy GameWindow (główne okno aplikacji) Klasa, w której do głównego okna dodawane są wszystkie komponenty class GameWindow extends JFrame { private HighScores hs; private JButton start, create, hint, solve, edit, highScores, exit; private JToggleButton easy, normal, hard, veryHard; private ButtonGroup diffLevel = new ButtonGroup(); private TimeLabel timeLabel = new TimeLabel(); private PointsLabel pointsLabel = new PointsLabel(); private Game game = new Game(timeLabel, pointsLabel, NORMAL); private GamePanel gamePanel; private Solver sol; private Generator gen; private Container c = new Container(); private HighScoresWindow scoresWindow; private Graphics g = getGraphics(); private Image image; Okno prezentujace najlepsze wyniku class WinnerWindow extends JDialog { private GameWindow gameWindow; private Image image; private JTextField nameField = new JTextField(); private HighScores highScores; Okno dialogowe, w którym pogromca Sudoku podaje swoja nazwę class HighScoresWindow extends JDialog { Sterowanie zegarem gry i punktami class Game { private Thread t; //watek uruchamiany na czas gry private TimeLabel timeLabel; private PointsLabel pointsLabel; private int leftFields; //liczba pol pozostalych do wypelnienia private int points; //liczba punktow private int lostPoints; //punkty tracone w kazdej sekundzie private int wrongChoice; //ile punktow traci sie za zly wybor private long begin; Game(TimeLabel tl, PointsLabel pl, int diff) { timeLabel = tl; pointsLabel = pl; } Zasady przyjęte w grze jeżeli chodzi o punkty w zależności od poziomu trudności, podjęcia błędnej decyzji, włączenia podpowiedzi i tracone wraz ze każdą sekundą rozwiązywania Sudoku public void setDifficulty(int diff) { switch(diff) { case GameWindow.EASY: points = 25000; lostPoints = 7; wrongChoice = 2500; break; case GameWindow.NORMAL: points = 50000; lostPoints = 14; wrongChoice = 4500; break; case GameWindow.HARD: points = 100000; lostPoints = 56; wrongChoice = 8500; break; case GameWindow.VERY_HARD: points = 200000; lostPoints = 112; wrongChoice = 17000; break; } pointsLabel.setPoints(points); Okno wraz z komponentami w czasie gry class GamePanel extends JPanel { private GameWindow gw; private WinnerWindow winnerWin; private private private private private private Field[][] fields//tablica przyciskow - pol planszy Solver sol = new SudokuSolver(this); boolean hint = false; //czy wyswietlac wskazowki boolean wrongChoice = false;//czy jest blad na planszy boolean edit = false; //czy w trybie edycji int badX = -1, badY = -1; //gdzie jest blad private int[][] values = new int[9][9];//wartosci w poszczegolnych polach private int rowUsed[][] = new int[9][10];//czy w rzedzie znajduje sie wartosc private int colUsed[][]= new int[9][10]; //czy w kolumnie znajduje sie wartosc private int sqUsed[][]= new int[9][10]; //czy w kwadracie 3x3 jest wartosc Przyciski class Field extends Jbutton Etykieta związana z punktami class PointsLabel extends JLabel { Etykieta związana z pomiarem upływającego czasu class TimeLabel extends Jlabel Generacja planszy interface Generator { void generateSudoku(GamePanel gp); void setDifficulty(int d); } Solver interface Solver { boolean solveSudoku(); } class SudokuSolver implements Solver { Rekord wstawiany do tablicy z najlepszymi wynikami class Record implements Serializable, Comparator { Zegar gry class Time implements Serializable, Comparable {