adds more javadoc

Sat, 25 Jul 2020 15:29:51 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 25 Jul 2020 15:29:51 +0200
changeset 10
369903afbb29
parent 9
576e7a2861ae
child 11
f7433671fec5

adds more javadoc

src/main/java/de/uapcore/sudoku/ActionHandler.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/ButtonPanel.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/DocumentHandler.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/Field.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/MainMenu.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/Solver.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/Sudoku.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/sudoku/SudokuTextField.java file | annotate | diff | comparison | revisions
--- a/src/main/java/de/uapcore/sudoku/ActionHandler.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/ActionHandler.java	Sat Jul 25 15:29:51 2020 +0200
@@ -1,16 +1,16 @@
 /*
  * Copyright 2013 Mike Becker. All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 
+ *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -33,31 +33,42 @@
 import java.io.IOException;
 
 /**
- *
- * @author mike
+ * Handles all user issued actions in the application.
  */
 public final class ActionHandler implements ActionListener {
-    
+
     public static final String SAVE = "save";
     public static final String CHECK = "check";
     public static final String SOLVE = "solve";
-    
+
     public static final String NEW = "new";
     public static final String OPEN = "open";
     public static final String SAVE_AS = "save as";
     public static final String QUIT = "quit";
     public static final String ABOUT = "about";
-    
+
     private Field field;
     private Solver solver;
     private DocumentHandler doc;
-    
+
+    /**
+     * Constructs a new action handler instance.
+     *
+     * @param f a reference to the playing field
+     */
     public ActionHandler(Field f) {
         field = f;
         solver = new Solver();
         doc = new DocumentHandler();
     }
-    
+
+    /**
+     * Prompts the user for a file name.
+     * <p>
+     * If the user chooses an existing file, they are asked whether the file should be overwritten.
+     *
+     * @return true if the user approves a chosen file name
+     */
     private boolean chooseSaveFilename() {
         JFileChooser fc = new JFileChooser(".");
         fc.setMultiSelectionEnabled(false);
@@ -81,7 +92,10 @@
             return false;
         }
     }
-    
+
+    /**
+     * Prompts the user for a file to open and, if approved, loads that file.
+     */
     private void open() {
         JFileChooser fc = new JFileChooser(".");
         fc.setMultiSelectionEnabled(false);
@@ -92,12 +106,22 @@
                 doc.load(field);
             } catch (IOException e) {
                 JOptionPane.showMessageDialog(field,
-                    "Datei konnte nicht geladen werden: "+e.getMessage(),
-                    "Sudoku", JOptionPane.ERROR_MESSAGE);
+                        "Datei konnte nicht geladen werden: " + e.getMessage(),
+                        "Sudoku", JOptionPane.ERROR_MESSAGE);
             }
         }
     }
-    
+
+    /**
+     * Attempts to save the Sudoku field to a file.
+     * <p>
+     * If necessary, the user is prompted for a file name.
+     * <p>
+     * The field must be solvable, otherwise it cannot be saved.
+     *
+     * @param rename true if the user shall always be prompted, even if a file name is already known
+     * @return true if the user approves the chosen file name
+     */
     private boolean save(boolean rename) {
         if (!doc.isFilenameSet() || rename) {
             if (!chooseSaveFilename()) {
@@ -110,8 +134,8 @@
                 doc.save(field);
             } catch (IOException e) {
                 JOptionPane.showMessageDialog(field,
-                    "Datei konnte nicht gespeichert werden: "+e.getMessage(),
-                    "Sudoku", JOptionPane.ERROR_MESSAGE);
+                        "Datei konnte nicht gespeichert werden: " + e.getMessage(),
+                        "Sudoku", JOptionPane.ERROR_MESSAGE);
             }
             return true;
         } else {
@@ -121,7 +145,10 @@
             return false;
         }
     }
-    
+
+    /**
+     * Checks the Sudoku field and displays the result as a dialog box.
+     */
     private void check() {
         if (solver.check(field)) {
             JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!",
@@ -131,14 +158,22 @@
                     "Sudoku", JOptionPane.WARNING_MESSAGE);
         }
     }
-    
+
+    /**
+     * Solves the field or displays an error dialog if the field is not solvable.
+     */
     private void solve() {
         if (!solver.check(field) || !solver.solve(field)) {
             JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!",
                     "Sudoku", JOptionPane.WARNING_MESSAGE);
         }
     }
-    
+
+    /**
+     * Checks whether there are unsaved changes and asks the user to save the field.
+     *
+     * @return true if there are no unsaved changes or the user actively decides to continue - false, otherwise
+     */
     private boolean saveUnsaved() {
         boolean proceed = false;
         if (field.isAnyCellModified()) {
@@ -155,49 +190,49 @@
         } else {
             proceed = true;
         }
-        
+
         return proceed;
     }
 
     @Override
     public void actionPerformed(ActionEvent e) {
         switch (e.getActionCommand()) {
-        case NEW:
-            if (saveUnsaved()) {
-                doc.clearFilename();
-                field.clear();
-            }
-            break;
-        case OPEN:
-            open();
-            break;
-        case SAVE:
-            save(false);
-            break;
-        case SAVE_AS:
-            save(true);
-            break;
-        case CHECK:
-            check();
-            break;
-        case SOLVE:
-            solve();
-            break;
-        case QUIT:
-            if (saveUnsaved()) {
-                System.exit(0);
-            }
-            break;
-        case ABOUT:
-            JOptionPane.showMessageDialog(field,
-                    "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de"+
-                    "\nPublished under the BSD License",
-                    "Sudoku", JOptionPane.INFORMATION_MESSAGE);
-            break;
-        default:
-            throw new UnsupportedOperationException(
-                    "unknown action: "+e.getActionCommand());
+            case NEW:
+                if (saveUnsaved()) {
+                    doc.clearFilename();
+                    field.clear();
+                }
+                break;
+            case OPEN:
+                open();
+                break;
+            case SAVE:
+                save(false);
+                break;
+            case SAVE_AS:
+                save(true);
+                break;
+            case CHECK:
+                check();
+                break;
+            case SOLVE:
+                solve();
+                break;
+            case QUIT:
+                if (saveUnsaved()) {
+                    System.exit(0);
+                }
+                break;
+            case ABOUT:
+                JOptionPane.showMessageDialog(field,
+                        "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de" +
+                                "\nPublished under the BSD License",
+                        "Sudoku", JOptionPane.INFORMATION_MESSAGE);
+                break;
+            default:
+                throw new UnsupportedOperationException(
+                        "unknown action: " + e.getActionCommand());
         }
     }
-    
+
 }
--- a/src/main/java/de/uapcore/sudoku/ButtonPanel.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/ButtonPanel.java	Sat Jul 25 15:29:51 2020 +0200
@@ -30,8 +30,7 @@
 import java.awt.*;
 
 /**
- *
- * @author mike
+ * The panel displaying some actions for the Sudoku solver.
  */
 public final class ButtonPanel extends JPanel {
     
--- a/src/main/java/de/uapcore/sudoku/DocumentHandler.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/DocumentHandler.java	Sat Jul 25 15:29:51 2020 +0200
@@ -32,12 +32,18 @@
 
 /**
  *
- * @author mike
  */
 public class DocumentHandler {
     
     private String filename;
-    
+
+    /**
+     * Loads data into the specified field.
+     *
+     * @param field the field to populated with the loaded data
+     * @throws IOException if loading fails or no file name has been set before
+     * @see #setFilename(String)
+     */
     public void load(Field field) throws IOException {
         if (!isFilenameSet()) {
             throw new IOException("no filename supplied");
@@ -72,7 +78,14 @@
         }
         field.setAllCellsModified(false);
     }
-    
+
+    /**
+     * Saves the specified field to a file.
+     *
+     * @param field the field to save
+     * @throws IOException if saving fails or the file name has not been set before
+     * @see #setFilename(String)
+     */
     public void save(Field field) throws IOException {
         if (!isFilenameSet()) {
             throw new IOException("no filename supplied");
@@ -89,15 +102,28 @@
             }
         }
     }
-    
+
+    /**
+     * Sets the file name for loading and saving data.
+     *
+     * @param filename the file name
+     */
     public void setFilename(String filename) {
         this.filename = filename;
     }
-    
+
+    /**
+     * Clears the file name.
+     */
     public void clearFilename() {
         filename = null;
     }
-    
+
+    /**
+     * Checks whether a file name has been set.
+     *
+     * @return true if a file name is known, false otherwise
+     */
     public boolean isFilenameSet() {
         return filename != null;
     }
--- a/src/main/java/de/uapcore/sudoku/Field.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/Field.java	Sat Jul 25 15:29:51 2020 +0200
@@ -1,16 +1,16 @@
 /*
  * Copyright 2013 Mike Becker. All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- * 
+ *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -31,22 +31,26 @@
 import java.awt.image.BufferedImage;
 
 /**
- *
- * @author mike
+ * A panel rendering the Sudoku field.
+ * <p>
+ * Cells are identified by zero-based indices from top-left to bottom-right.
  */
 public final class Field extends JPanel {
     private SudokuTextField[][] cells;
-    
+
+    /**
+     * Constructs a new 9x9 Sudoku grid.
+     */
     public Field() {
         setBackground(Color.WHITE);
-        
+
         setLayout(new GridBagLayout());
         GridBagConstraints c = new GridBagConstraints();
         c.insets = new Insets(5, 5, 5, 5);
-        
+
         cells = new SudokuTextField[9][9];
-        for (int x = 0 ; x < 9 ; x++) {
-            for (int y = 0 ; y < 9 ; y++) {
+        for (int x = 0; x < 9; x++) {
+            for (int y = 0; y < 9; y++) {
                 cells[x][y] = new SudokuTextField();
                 c.gridx = x;
                 c.gridy = y;
@@ -55,69 +59,118 @@
         }
     }
 
+    /**
+     * Paints the grid and all contained cells.
+     *
+     * @param graphics the graphics context
+     */
     @Override
     public void paint(Graphics graphics) {
         final int w = getWidth();
         final int h = getHeight();
         final int cw = w / 9;
         final int ch = h / 9;
-        
+
         BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
         Graphics2D g = img.createGraphics();
         g.setBackground(Color.WHITE);
         g.clearRect(0, 0, w, h);
-        
+
         g.setColor(Color.BLACK);
-        g.drawRect(1, 1, w-2, h-2);
-        g.drawRect(2, 2, w-4, h-4);
-        for (int x = cw ; x < w ; x += cw) {
-            for (int y = ch ; y < h ; y += ch) {
-                g.drawLine(x, 2, x, h-2);
-                g.drawLine(2, y, w-2, y);
+        g.drawRect(1, 1, w - 2, h - 2);
+        g.drawRect(2, 2, w - 4, h - 4);
+        for (int x = cw; x < w; x += cw) {
+            for (int y = ch; y < h; y += ch) {
+                g.drawLine(x, 2, x, h - 2);
+                g.drawLine(2, y, w - 2, y);
                 if ((x / cw) % 3 == 0) {
-                    g.drawLine(x+1, 2, x+1, h-2);
+                    g.drawLine(x + 1, 2, x + 1, h - 2);
                 }
                 if ((y / ch) % 3 == 0) {
-                    g.drawLine(2, y+1, w-2, y+1);
+                    g.drawLine(2, y + 1, w - 2, y + 1);
                 }
             }
         }
-        
+
         graphics.drawImage(img, 0, 0, this);
         super.paintChildren(graphics);
     }
-    
+
+    /**
+     * Checks whether a cell is empty
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     * @return true if the cell is empty, false otherwise
+     */
     public boolean isCellEmpty(int x, int y) {
         return getCellValue(x, y) == 0;
     }
-    
+
+    /**
+     * Returns value of a specific cell.
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     * @return the cell's value
+     */
     public int getCellValue(int x, int y) {
         return cells[x][y].getValue();
     }
-    
+
+    /**
+     * Sets the value of a specific cell.
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     * @param v the cells value
+     */
     public void setCellValue(int x, int y, int v) {
         cells[x][y].setValue(v);
     }
-    
+
+    /**
+     * Clears the value of a specific cell.
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     */
     public void clearCellValue(int x, int y) {
         setCellValue(x, y, 0);
     }
-    
+
+    /**
+     * Sets the modified state of a specific cell.
+     *
+     * @param x        horizontal position
+     * @param y        vertical position
+     * @param modified the modified state
+     */
     public void setCellModified(int x, int y, boolean modified) {
         cells[x][y].setModified(modified);
     }
-    
+
+    /**
+     * Sets the modified state of all cells.
+     *
+     * @param modified the modified state
+     */
     public void setAllCellsModified(boolean modified) {
-        for (int x = 0 ; x < 9 ; x++) {
-            for (int y = 0 ; y < 9 ; y++) {
+        for (int x = 0; x < 9; x++) {
+            for (int y = 0; y < 9; y++) {
                 cells[x][y].setModified(modified);
             }
         }
     }
-    
+
+    /**
+     * Checks whether any cell is modified.
+     *
+     * @return true if any cell is modified, false otherwise
+     */
     public boolean isAnyCellModified() {
-        for (int x = 0 ; x < 9 ; x++) {
-            for (int y = 0 ; y < 9 ; y++) {
+        for (int x = 0; x < 9; x++) {
+            for (int y = 0; y < 9; y++) {
                 if (cells[x][y].isModified()) {
                     return true;
                 }
@@ -125,53 +178,77 @@
         }
         return false;
     }
-    
+
+    /**
+     * Clears all cells.
+     */
     public void clear() {
-        for (int x = 0 ; x < 9 ; x++) {
-            for (int y = 0 ; y < 9 ; y++) {
+        for (int x = 0; x < 9; x++) {
+            for (int y = 0; y < 9; y++) {
                 cells[x][y].setValue(0);
             }
         }
     }
-    
+
+    /**
+     * Returns a square identified by square coordinates.
+     * <p>
+     * Cells within the square are identified by the same coordinate system.
+     *
+     * @param x horizontal position from 0 to 2
+     * @param y vertical position from 0 to 2
+     * @return a two-dimensional array containing the square cell values
+     */
     public int[][] getSquare(int x, int y) {
         if (x < 0 || x > 2 || y < 0 || y > 2) {
             throw new IllegalArgumentException("Invalid square coordinates");
         }
         int[][] square = new int[3][3];
-        
-        for (int u = 0 ; u < 3 ; u++) {
-            for (int v = 0 ; v < 3 ; v++) {
-                square[u][v] = getCellValue(3*x+u, 3*y+v);
+
+        for (int u = 0; u < 3; u++) {
+            for (int v = 0; v < 3; v++) {
+                square[u][v] = getCellValue(3 * x + u, 3 * y + v);
             }
         }
-        
+
         return square;
     }
-    
+
+    /**
+     * Returns an entire row.
+     *
+     * @param y the row position
+     * @return an array containing the row values
+     */
     public int[] getRow(int y) {
         if (y < 0 || y > 8) {
             throw new IllegalArgumentException("Invalid row number");
         }
         int row[] = new int[9];
-        
-        for (int x = 0 ; x < 9 ; x++) {
+
+        for (int x = 0; x < 9; x++) {
             row[x] = getCellValue(x, y);
         }
-        
+
         return row;
     }
-    
+
+    /**
+     * Returns an entire column
+     *
+     * @param x the column position
+     * @return an array containing the column values
+     */
     public int[] getColumn(int x) {
         if (x < 0 || x > 8) {
             throw new IllegalArgumentException("Invalid column number");
         }
         int column[] = new int[9];
-        
-        for (int y = 0 ; y < 9 ; y++) {
+
+        for (int y = 0; y < 9; y++) {
             column[y] = getCellValue(x, y);
         }
-        
+
         return column;
     }
 }
--- a/src/main/java/de/uapcore/sudoku/MainMenu.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/MainMenu.java	Sat Jul 25 15:29:51 2020 +0200
@@ -29,8 +29,7 @@
 import javax.swing.*;
 
 /**
- *
- * @author mike
+ * Main menu bar.
  */
 public class MainMenu {
     
--- a/src/main/java/de/uapcore/sudoku/Solver.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/Solver.java	Sat Jul 25 15:29:51 2020 +0200
@@ -30,14 +30,10 @@
 import java.util.List;
 
 /**
- *
- * @author mike
+ * Implements the backtracking algorithm for solving the Sudoku.
  */
 public final class Solver {
-    
-    public Solver() {
-    }
-    
+
     private Integer fillInCandidate(Field f, List<Integer>[][] candidates, int x, int y) {
         Integer c = candidates[x][y].remove(0);
         f.setCellValue(x, y, c);
@@ -138,7 +134,17 @@
         
         return true;
     }
-    
+
+    /**
+     * Attempts to solve the given Sudoku field.
+     *
+     * The solution, if any, is directly entered into the field.
+     * All solved fields will be in modified state.
+     * The already given fields are left untouched.
+     *
+     * @param f the field to solve
+     * @return true if a solution could be found, false if the field is unsolvable
+     */
     public boolean solve(Field f) {
         
         // Calculate initial candidates
@@ -175,7 +181,13 @@
         // Backtrack
         return solve(f, candidates);
     }
-    
+
+    /**
+     * Performs a fast check whether any field violates the Sudoku rules.
+     *
+     * @param f the field to check
+     * @return true, if the check succeeds, false otherwise
+     */
     public boolean check(Field f) {
         int line[];
         for (int i = 0 ; i < 9 ; i++) {
--- a/src/main/java/de/uapcore/sudoku/Sudoku.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/Sudoku.java	Sat Jul 25 15:29:51 2020 +0200
@@ -30,11 +30,13 @@
 import java.awt.*;
 
 /**
- *
- * @author mike
+ * Main class of the application.
  */
 public final class Sudoku extends JFrame {
-    
+
+    /**
+     * Constructs the Sudoku main window.
+     */
     public Sudoku() {
         super("Sudoku");
         
@@ -61,6 +63,8 @@
     }
 
     /**
+     * Main method starting the Sudoku solver.
+     *
      * @param args the command line arguments
      */
     public static void main(String[] args) {
--- a/src/main/java/de/uapcore/sudoku/SudokuTextField.java	Sat Jul 25 14:01:28 2020 +0200
+++ b/src/main/java/de/uapcore/sudoku/SudokuTextField.java	Sat Jul 25 15:29:51 2020 +0200
@@ -34,8 +34,7 @@
 import java.awt.event.KeyEvent;
 
 /**
- *
- * @author mike
+ * A custom text field specifically for Sudoku number fields.
  */
 public final class SudokuTextField extends JTextField {
     
@@ -105,15 +104,25 @@
             }
         });
     }
-    
+
+    /**
+     * Returns the current value in the field or zero if the field is empty.
+     *
+     * @return the number from 1 to 9 or zero if empty
+     */
     public int getValue() {
-        if (getText().length() > 0) {
+        if (getText().isEmpty()) {
+            return 0;
+        } else {
             return Integer.valueOf(getText());
-        } else {
-            return 0;
         }
     }
-    
+
+    /**
+     * Sets the field's value.
+     *
+     * @param v the number from 1 to 9 or zero to clear the field
+     */
     public void setValue(int v) {
         if (v == 0) {
             setText("");
@@ -124,12 +133,24 @@
                     "Sudoku numbers must be in range 0-9 (0 means 'not set')");
         }
     }
-    
+
+    /**
+     * Sets the modified state of this field.
+     *
+     * Modified fields are displayed in blue color.
+     *
+     * @param modified a flag indicating whether this field is modified
+     */
     public void setModified(boolean modified) {
         this.modified = modified;
         setForeground(modified?Color.BLUE:Color.BLACK);
     }
-    
+
+    /**
+     * Checks whether this field is in modified state.
+     *
+     * @return true if this field is modified
+     */
     public boolean isModified() {
         return modified;
     }

mercurial