package gui; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; import java.awt.event.*; import sudoku.SudokuParser; /** * 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; /** Button for picking a Sudoku-file */ private JButton fileButton; /** Constructor */ public SudokuView() { setTitle("Sudoku Solver"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); setIconImage(new ImageIcon("src/main/resources/sudoku.png").getImage()); initializeGrid(); initializeButtons(); setMinimumSize(new Dimension(500, 500)); pack(); // Resize the window to fit the components, if necessary setLocationRelativeTo(null); // Center the window } /** Initialize the grid, called by the constructor */ private void initializeGrid() { grid = new JTextField[9][9]; JPanel gridPanel = new JPanel(new GridLayout(9, 9)); gridPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); int fontSize = 16; String fontName = gridPanel.getFont().getName(); Border border = BorderFactory.createLineBorder(Color.BLACK); Font font = new Font(fontName, Font.BOLD, fontSize); for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { JTextField cell = new JTextField(2); cell.setHorizontalAlignment(JTextField.CENTER); cell.setFont(font); cell.setBorder(border); cell.setForeground(Color.BLACK); // Set background color to gray for every third JTextField if ((row / 3 + col / 3) % 2 == 1) { cell.setBackground(Color.LIGHT_GRAY); } grid[row][col] = cell; gridPanel.add(cell); } } 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"); fileButton = new JButton("Open file"); JPanel buttonPanel = new JPanel(); buttonPanel.add(solveButton); buttonPanel.add(resetButton); buttonPanel.add(randomButton); buttonPanel.add(fileButton); 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 file button * * @param listener the ActionListener to add */ public void addFileButtonListener(ActionListener listener) { fileButton.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 addCellActionListener(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); } /** * Method to open a file picker dialog * * @return 2D array of integers representing the Sudoku board */ public int[][] openFile() { // Create a file chooser and set all related options JFileChooser fileChooser = new JFileChooser(); fileChooser.setCurrentDirectory(new java.io.File(".")); fileChooser.setDialogTitle("Select a Sudoku file"); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setAcceptAllFileFilterUsed(false); // Show the file chooser and return if the user cancels int returnValue = fileChooser.showOpenDialog(this); if (returnValue != JFileChooser.APPROVE_OPTION) { return null; } // Get the path String filepath = fileChooser.getSelectedFile().getAbsolutePath(); // Try to parse it try { return SudokuParser.parseSudoku(filepath); } catch (Exception e) { showErrorMessage(e.getMessage()); return null; } } }