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 {