From 71c43b35c3e5c8474a100bedc566d4b305d9b391 Mon Sep 17 00:00:00 2001 From: Imbus Date: Sun, 10 Dec 2023 14:54:56 +0100 Subject: [PATCH] MVC architecture user interface implemented with swing --- app/src/main/java/gui/SudokuController.java | 86 +++++++++ app/src/main/java/gui/SudokuView.java | 186 ++++++++++++++++++++ app/src/main/java/sudoku/SolverMain.java | 34 +++- 3 files changed, 300 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/gui/SudokuController.java create mode 100644 app/src/main/java/gui/SudokuView.java diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java new file mode 100644 index 0000000..58043d4 --- /dev/null +++ b/app/src/main/java/gui/SudokuController.java @@ -0,0 +1,86 @@ +package gui; + +import sudoku.SudokuSolver; +import java.awt.event.*; + +/** + * SolverController is a controller for the SudokuSolver interface + */ +public class SudokuController { + SudokuSolver model; + SudokuView view; + + /** + * Constructor + * + * @param model SudokuSolver model + * @param view SudokuView view + */ + public SudokuController(SudokuSolver model, SudokuView view) { + this.model = model; + this.view = view; + + // Add action listeners to the buttons + view.addSolveButtonListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Solve the board + model.solve(); + + // Update the view + view.updateView(model.getBoard()); + } + }); + + view.addResetButtonListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Clear the board + model.clear(); + + // Update the view + view.updateView(model.getBoard()); + } + }); + + view.addRandomButtonListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // Randomize the board + model.randomizeBoard(); + + // Update the view + view.updateView(model.getBoard()); + } + }); + + view.addCellClickListener(new CellActionListener()); + } + + /** Start the GUI */ + public void start() { + view.setVisible(true); + } + + /** + * CellActionListener is an ActionListener for the Sudoku grid cells + */ + private class CellActionListener implements ActionListener { + @Override + public void actionPerformed(ActionEvent e) { + // Get the row and column from the clicked cell + int row = view.getSelectedRow(); + int col = view.getSelectedColumn(); + + String inputText = view.getCellValue(row, col); + int value = Integer.parseInt(inputText); + // Check if the input is legal and update the model and view + if (model.isLegal(row, col, value)) { + model.set(row, col, value); + view.updateView(model.getBoard()); + } else { + view.showErrorMessage("Invalid input. Try again."); + } + } + } +} diff --git a/app/src/main/java/gui/SudokuView.java b/app/src/main/java/gui/SudokuView.java new file mode 100644 index 0000000..9570746 --- /dev/null +++ b/app/src/main/java/gui/SudokuView.java @@ -0,0 +1,186 @@ +package gui; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/** + * SolverView is a GUI for the SudokuSolver interface + */ +public class SudokuView extends JFrame { + /** The grid of text fields */ + private JTextField[][] grid; + + /** Button for solve */ + private JButton solveButton; + /** Button for reset */ + private JButton resetButton; + /** Button for random */ + private JButton randomButton; + + /** Constructor */ + public SudokuView() { + setTitle("Sudoku Solver"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setLayout(new BorderLayout()); + + initializeGrid(); + initializeButtons(); + + pack(); + setLocationRelativeTo(null); + } + + /** Initialize the grid, called by the constructor */ + private void initializeGrid() { + grid = new JTextField[9][9]; + JPanel gridPanel = new JPanel(new GridLayout(9, 9)); + + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + grid[row][col] = new JTextField(2); + grid[row][col].setHorizontalAlignment(JTextField.CENTER); + gridPanel.add(grid[row][col]); + } + } + + add(gridPanel, BorderLayout.CENTER); + } + + /** Initialize the buttons, called by the constructor */ + private void initializeButtons() { + solveButton = new JButton("Solve"); + resetButton = new JButton("Reset"); + randomButton = new JButton("Randomize"); + + JPanel buttonPanel = new JPanel(); + buttonPanel.add(solveButton); + buttonPanel.add(resetButton); + buttonPanel.add(randomButton); + + add(buttonPanel, BorderLayout.SOUTH); + } + + /** + * Update the view with a new grid + * + * @param newGrid the new grid to display + */ + public void updateView(int[][] newGrid) { + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + if (newGrid[row][col] != 0) { + grid[row][col].setText(String.valueOf(newGrid[row][col])); + } else { + grid[row][col].setText(""); + } + } + } + } + + /** + * Method to add ActionListener to solve button + * + * @param listener the ActionListener to add + */ + public void addSolveButtonListener(ActionListener listener) { + solveButton.addActionListener(listener); + } + + /** + * Method to add ActionListener to reset button + * + * @param listener the ActionListener to add + */ + public void addResetButtonListener(ActionListener listener) { + resetButton.addActionListener(listener); + } + + /** + * Method to add ActionListener to randomize button + * + * @param listener the ActionListener to add + */ + public void addRandomButtonListener(ActionListener listener) { + randomButton.addActionListener(listener); + } + + /** + * Method to add ActionListener to individual cells in the grid + *

+ * Assumes that the ActionListener will be the same for all cells + * and that the listener will be capable of determining which cell + * was clicked + * + * @param listener the ActionListener to add + */ + public void addCellClickListener(ActionListener listener) { + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + grid[row][col].addActionListener(listener); + } + } + } + + /** + * Getter method to retrieve the values from the text fields + * + * @param row the row of the cell + * @param col the column of the cell + * @return the value of the cell + */ + public String getCellValue(int row, int col) { + return grid[row][col].getText(); + } + + /** + * Method to get the selected row (example implementation) + * + * @return the selected row, or -1 if no cell is selected + */ + public int getSelectedRow() { + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + if (grid[row][col].isFocusOwner()) { + return row; + } + } + } + return -1; // Return -1 if no cell is selected + } + + /** + * Method to get the selected column (example implementation) + * + * @return the selected row, or -1 if no cell is selected + */ + public int getSelectedColumn() { + for (int row = 0; row < 9; row++) { + for (int col = 0; col < 9; col++) { + if (grid[row][col].isFocusOwner()) { + return col; + } + } + } + return -1; // Return -1 if no cell is selected + } + + /** + * Methods to show dialogs + * + * @param message the message to display + * @return the user input + */ + public String showInputDialog(String message) { + return JOptionPane.showInputDialog(this, message); + } + + /** + * Method to show error messages + * + * @param message the message to display + */ + public void showErrorMessage(String message) { + JOptionPane.showMessageDialog(this, message); + } +} diff --git a/app/src/main/java/sudoku/SolverMain.java b/app/src/main/java/sudoku/SolverMain.java index 7077608..ea5ed7c 100644 --- a/app/src/main/java/sudoku/SolverMain.java +++ b/app/src/main/java/sudoku/SolverMain.java @@ -1,12 +1,34 @@ package sudoku; +import gui.SudokuController; +import gui.SudokuView; + +/** SolverMain is the main class for the Sudoku Solver */ public class SolverMain { + + private Solver model; + private SudokuView view; + private SudokuController controller; + + /** Constructor */ + SolverMain() { + model = new Solver(); + view = new SudokuView(); + controller = new SudokuController(model, view); + } + + /** Start the GUI */ + void start() { + controller.start(); + } + + /** + * Main method + * + * @param args command line arguments + */ public static void main(String[] args) { - Solver s = new Solver(); - System.out.println(s.toString()); - s.randomizeBoard(); - System.out.println(s.toString()); - s.solve(); - System.out.println(s.toString()); + SolverMain main = new SolverMain(); + main.start(); } }