001    package de.hska.java.aufgaben.backtracking;
002    
003    import java.awt.Color;
004    import java.awt.Dimension;
005    import java.awt.Font;
006    import java.awt.Graphics;
007    import java.awt.Graphics2D;
008    import java.awt.event.MouseEvent;
009    import java.awt.event.MouseListener;
010    import java.awt.event.WindowEvent;
011    import java.awt.event.WindowListener;
012    
013    import javax.swing.JFrame;
014    
015    
016    
017    /**
018     * Visualisierung eines Sudokus in einem Fenster.
019     * Durch Klicken mit der Maus wird immer der nächste Schritt des Backtracking-Algorithmus
020     * ausgelöst. 
021     * 
022     * @author Christian Pape
023     *
024     */
025    public class JSudokuFrame extends JFrame implements SudokuListener, MouseListener, WindowListener {
026    
027            private boolean naechstenSchrittAusfuehren;
028            
029            private Sudoku sudoku;
030    
031            private char [] [] zahlen = {{'0'}, {'1'}, {'2'}, {'3'}, {'4'}, {'5'}, {'6'}, {'7'}, {'8'}, {'9'} };
032            
033            /**
034             * Erzeugt ein neues Sudoku-Frame für das gegebene <code>sudoku</code>
035             * @param sudoku
036             */
037            public JSudokuFrame(Sudoku sudoku) {
038                    this.sudoku = sudoku;
039                    this.sudoku.addSudokuListener(this);
040                    this.addMouseListener(this);
041                    this.addWindowListener(this);
042                    setPreferredSize(new Dimension(800, 600));
043            }
044            
045            /**
046             * Wird von <code>sudoku</code> aufgerufen, wenn
047             * sich der Wert einer Zelle im Sudoku geändert hat.
048             */
049            public void zahlHatSichGeaendert(int zeile, int spalte, final int zahl) {
050                    this.repaint(10);
051                    while (! naechstenSchrittAusfuehren) {
052                            try {
053                                    Thread.sleep(100);
054                            } catch (InterruptedException e) {
055                                    naechstenSchrittAusfuehren = true;
056                            }
057                    }
058                    naechstenSchrittAusfuehren = false;
059            }
060    
061            /**
062             * Zeichnet das gesamte Sudoku neu.
063             */
064            public void paint(Graphics g) {
065                    Graphics2D graphics = (Graphics2D) g;
066                    
067                    graphics.setBackground(Color.WHITE);
068                    graphics.clearRect(getRootPane().getX(), getRootPane().getY(),
069                                    getRootPane().getWidth(), getRootPane().getHeight());
070                    int x = getRootPane().getX();
071                    int y = getRootPane().getY();
072                    int cellWidth = (getRootPane().getWidth() - x)  / 9;
073                    int cellHeight = (getRootPane().getHeight() - y) / 9;
074                    Font font = graphics.getFont();
075                    font = font.deriveFont( (cellWidth + cellHeight) / 1.8f );
076                    graphics.setFont(font);
077                    for (int zeile = 0; zeile < 9; zeile++) {
078                            for (int spalte = 0; spalte < 9; spalte++) {
079                                    graphics.setColor(Color.GRAY);  
080                                    graphics.drawRect(x + cellWidth * spalte, y + cellHeight * zeile, cellWidth, cellHeight);
081                                    graphics.setColor(Color.BLACK);
082                                    int zahl = this.sudoku.getZahl(zeile, spalte);
083                                    if (1 <= zahl && zahl <= 9) {
084                                            graphics.drawChars( zahlen[zahl], 0,
085                                                            1, x + cellWidth * spalte, y + font.getBaselineFor(zahlen[zahl][0])+ cellHeight * (zeile + 1));
086                                    }                               
087                            }
088                    }
089            }
090            
091            public static final void main(String [] argv) throws InterruptedException {
092                    final Sudoku sudoku = new Sudoku(new int[][] {
093                    { 9,  -1, 3, -1,  1, -1,  7, -1, -1},
094                    {-1,  6, -1, -1, -1,  8,  5, -1, -1},
095                    {-1,  5, -1, -1, -1, -1, -1,  9,  6},
096                    {-1, -1, -1, -1,  3, -1,  6, -1,  4},
097                    {-1,  4, -1,  9, -1,  1,  3,  7,  2},
098                    {-1, -1, -1,  8,  7,  4, -1,  1, -1},
099                    {-1, -1,  5, -1, -1,  3,  2, -1,  1},
100                    { 6,  8,  7, -1, -1, -1, -1, -1, -1},
101                    { 3, -1, -1, -1, -1, -1, -1,  5, -1}
102                });
103                    JSudokuFrame jSudokuFrame = new JSudokuFrame(sudoku);
104                    jSudokuFrame.pack();
105                    jSudokuFrame.setVisible(true);
106                    Thread thread = new Thread( new Runnable() {
107                            public void run() {
108                                    sudoku.sucheLoesung(0);                         
109                            }
110                    });
111                    thread.start();
112                    thread.join();
113            }
114    
115            public void mouseClicked(MouseEvent e) {
116                    naechstenSchrittAusfuehren = true;
117            }
118    
119            public void mouseEntered(MouseEvent e) {
120                            
121            }
122    
123            public void mouseExited(MouseEvent e) {
124                    
125            }
126    
127            public void mousePressed(MouseEvent e) {
128                    
129            }
130    
131            public void mouseReleased(MouseEvent e) {
132    
133            }
134    
135            public void windowActivated(WindowEvent e) {
136            }
137    
138            public void windowClosed(WindowEvent e) {
139    
140            }
141    
142            public void windowClosing(WindowEvent e) {
143                    System.exit(0);
144            }
145    
146            public void windowDeactivated(WindowEvent e) {
147                    
148            }
149    
150            public void windowDeiconified(WindowEvent e) {
151    
152                    
153            }
154    
155            public void windowIconified(WindowEvent e) {
156    
157                    
158            }
159    
160            public void windowOpened(WindowEvent e) {
161    
162                    
163            }
164    
165    
166    }