Working parser, file chooser and sample files
This commit is contained in:
		
							parent
							
								
									175545d3d5
								
							
						
					
					
						commit
						521b3fb05b
					
				
					 6 changed files with 163 additions and 4 deletions
				
			
		|  | @ -54,7 +54,23 @@ public class SudokuController { | |||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         view.addCellClickListener(new CellActionListener()); | ||||
|         view.addFileButtonListener(new ActionListener() { | ||||
|             @Override | ||||
|             public void actionPerformed(ActionEvent e) { | ||||
|                 // Open a file, view handles the parsing internally via SudokuParser | ||||
|                 int[][] newBoard = view.openFile(); | ||||
| 
 | ||||
|                 // If the file was parsed successfully | ||||
|                 if (newBoard != null) { | ||||
|                     // Set the model | ||||
|                     model.setBoard(newBoard); | ||||
|                     // Update the view | ||||
|                     view.updateView(model.getBoard()); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         view.addCellActionListener(new CellActionListener()); | ||||
|     } | ||||
| 
 | ||||
|     /** Start the GUI */ | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ import javax.swing.*; | |||
| import java.awt.*; | ||||
| import java.awt.event.*; | ||||
| 
 | ||||
| import sudoku.SudokuParser; | ||||
| 
 | ||||
| /** | ||||
|  * SolverView is a GUI for the SudokuSolver interface | ||||
|  */ | ||||
|  | @ -17,6 +19,8 @@ public class SudokuView extends JFrame { | |||
|     private JButton resetButton; | ||||
|     /** Button for random */ | ||||
|     private JButton randomButton; | ||||
|     /** Button for picking a Sudoku-file */ | ||||
|     private JButton fileButton; | ||||
| 
 | ||||
|     /** Constructor */ | ||||
|     public SudokuView() { | ||||
|  | @ -52,11 +56,13 @@ public class SudokuView extends JFrame { | |||
|         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); | ||||
|     } | ||||
|  | @ -105,6 +111,15 @@ public class SudokuView extends JFrame { | |||
|         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 | ||||
|      * <p> | ||||
|  | @ -114,7 +129,7 @@ public class SudokuView extends JFrame { | |||
|      *  | ||||
|      * @param listener the ActionListener to add | ||||
|      */ | ||||
|     public void addCellClickListener(ActionListener listener) { | ||||
|     public void addCellActionListener(ActionListener listener) { | ||||
|         for (int row = 0; row < 9; row++) { | ||||
|             for (int col = 0; col < 9; col++) { | ||||
|                 grid[row][col].addActionListener(listener); | ||||
|  | @ -183,4 +198,35 @@ public class SudokuView extends JFrame { | |||
|     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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -47,8 +47,6 @@ public class Solver implements SudokuSolver { | |||
|      */ | ||||
|     private boolean solve(int row, int col) { | ||||
|         if (++tries >= 10000) { | ||||
|             if (tries == 10000) | ||||
|                 System.out.println(String.format("Likely unsolvable. Tries: %d", tries)); | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										73
									
								
								app/src/main/java/sudoku/SudokuParser.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								app/src/main/java/sudoku/SudokuParser.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| package sudoku; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.io.FileNotFoundException; | ||||
| 
 | ||||
| /** Helpers class for parsing Sudoku files */ | ||||
| public class SudokuParser { | ||||
|     private static final int BOARD_SIZE = 9; | ||||
| 
 | ||||
|     // * Empty private constructor */ | ||||
|     private SudokuParser() { | ||||
|         // Empty | ||||
|     }; | ||||
| 
 | ||||
|     /** | ||||
|      * Parses a Sudoku file and returns a 2D array of integers | ||||
|      *  | ||||
|      * @param filePath Path to the Sudoku file | ||||
|      * @return 2D array of integers representing the Sudoku board | ||||
|      * @throws IOException              If an IO error occurs | ||||
|      * @throws FileNotFoundException    When the file cannot be found | ||||
|      * @throws NumberFormatException    When the file contains invalid characters | ||||
|      * @throws IllegalArgumentException When the file contains an invalid number of | ||||
|      *                                  rows or columns | ||||
|      */ | ||||
|     public static int[][] parseSudoku(String filePath) | ||||
|             throws IOException, FileNotFoundException, NumberFormatException, IllegalArgumentException { | ||||
|         int[][] sudokuBoard = new int[BOARD_SIZE][BOARD_SIZE]; | ||||
| 
 | ||||
|         // In practice we could just split the entire file into a single string and then | ||||
|         // parse it into an array of integers, which is then partitioned into a 2D | ||||
|         // array. | ||||
|         // However, this is how the assignment is specified, so we will do it this way. | ||||
| 
 | ||||
|         // Try to read the file with a BufferedReader | ||||
|         try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { | ||||
|             String line; | ||||
|             int row = 0; | ||||
| 
 | ||||
|             // While there are lines to read and we haven't reached the end of the board | ||||
|             while ((line = reader.readLine()) != null && row < BOARD_SIZE) { | ||||
|                 // Split it into an array of strings | ||||
|                 String[] values = line.trim().split("\\s+"); | ||||
| 
 | ||||
|                 // Check that the number of columns is correct | ||||
|                 if (values.length != BOARD_SIZE) { | ||||
|                     throw new IllegalArgumentException("Invalid number of columns in the Sudoku file."); | ||||
|                 } | ||||
| 
 | ||||
|                 // Parse the strings into integers and add them to the board | ||||
|                 for (int col = 0; col < BOARD_SIZE; col++) { | ||||
|                     sudokuBoard[row][col] = Integer.parseInt(values[col]); // Throws NumberFormatException | ||||
|                 } | ||||
| 
 | ||||
|                 row++; | ||||
|             } | ||||
| 
 | ||||
|             if (row != BOARD_SIZE) { | ||||
|                 throw new IllegalArgumentException("Invalid number of rows in the Sudoku file."); | ||||
|             } | ||||
|         } catch (FileNotFoundException e) { | ||||
|             throw new FileNotFoundException("The Sudoku file could not be found."); | ||||
|         } catch (IOException e) { | ||||
|             throw new IOException("An error occurred while reading the Sudoku file."); | ||||
|         } catch (NumberFormatException e) { | ||||
|             throw new NumberFormatException("The Sudoku file contains invalid characters."); | ||||
|         } | ||||
| 
 | ||||
|         return sudokuBoard; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										17
									
								
								app/src/test/java/sudoku/SudokuParserTest.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/src/test/java/sudoku/SudokuParserTest.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| package sudoku; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import static org.junit.jupiter.api.Assertions.*; | ||||
| 
 | ||||
| public class SudokuParserTest { | ||||
|     @Test | ||||
|     void constructorTest() { | ||||
|         int[][] board; | ||||
|         try { | ||||
|             board = SudokuParser.parseSudoku("sample_sudokus/demo_from_lab.txt"); | ||||
|         } catch (Exception e) { | ||||
|             board = null; | ||||
|         } | ||||
|         assertNotNull(board); | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Imbus
						Imbus