import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Scanner; /** All in one solution to the Sudoku lab. */ public class SudokuOne { /** Helper var for max size of grid/array. */ public static final int SIZE = 9; // all methods can use /** Helper var for the block size. */ public static final int BLOCKMAX = 3; /** Method checks validity of imported sudoku submission from text file. @param args not used. @throws IOException if invalid input. */ public static void main(String[] args) throws IOException { int[][] puzzle; Scanner keyboard = new Scanner(new InputStreamReader(System.in)); System.out.println("Please enter the name of a file containing" + "a 9x9 Sudoku solution:"); puzzle = read(keyboard.nextLine()); print(puzzle); System.out.println("Grid validity: " + validate(puzzle)); } /** Read the puzzle from a file. @param filename the name of the external text file. @return the grid where the puzzle is stored @throws IOException if invalid input. */ public static int[][] read(String filename) throws IOException { int[][] grid = new int[SIZE][SIZE]; Scanner infile = new Scanner(new FileReader(filename)); // read in the file contents for (int row = 0; row < SIZE; row++) { for (int col = 0; col < SIZE; col++) { grid[row][col] = infile.nextInt(); } } return grid; } /** Print out the grid for reference. @param grid the puzzle to print */ public static void print(int[][] grid) { for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { System.out.print(grid[i][j]); if (j % BLOCKMAX == 2 && j != SIZE - 1) { System.out.print('|'); } } System.out.println(); if (i % BLOCKMAX == 2 && i != SIZE - 1) { System.out.println("---+---+---"); } } System.out.println(); } /** Helper method for validating a sudoku grid. @param grid the puzzle to check @return true if a valid solution, false if not */ public static boolean validate(int[][] grid) { boolean result = true; String invalids = ""; if (!goodRows(grid)) { result = false; } if (!goodColumns(grid)) { result = false; } if (!goodBoxes(grid)) { result = false; } return result; } /** Helper method for validating a 1D array of ints. @param seg the array to validate @return true if the array contains all the integers between 1 and length, inclusive, false otherwise. */ private static boolean testSegment(int[] seg) { // create an array of flag variables to see if each number 1-9 // occurs in the seg array boolean[] found = new boolean[SIZE]; // automatically initialized to all false // Print each section if you're curious // for (int j = 0; j < SIZE; j++) { // System.out.print(seg[j]); // } // System.out.println(); for (int i = 0; i < seg.length; i++) { if (seg[i] > SIZE || seg[i] < 1) { // to prevent out of bounds errors return false; } else { found[seg[i] - 1] = true; } } for (int i = 0; i < found.length; i++) { // see if all found if (! found[i]) { // missing number i+1 return false; } } // If it makes it this far, it's valid return true; } /** Test all rows, display invalid ones on screen. @param grid the puzzle to check @return true if all rows good, false otherwise */ public static boolean goodRows(int[][] grid) { String invalids = ""; boolean result = true; for (int i = 0; i < SIZE; i++) { if (!testSegment(grid[i])) { invalids += (i + 1) + " "; result = false; } } if (invalids.length() != 0) { System.out.println("invalid rows: " + invalids); } return result; } /** Test all columns - copy each to temp 1D array to call test method, display invalid ones on screen. @param grid the puzzle to check @return true if all good, false otherwise */ public static boolean goodColumns(int[][] grid) { boolean result = true; String invalids = ""; int[] temp = new int[SIZE]; for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { temp[j] = grid[j][i]; } if (!testSegment(temp)) { invalids += (i + 1) + " "; result = false; } } if (invalids.length() != 0) { System.out.println("invalid columns: " + invalids); } return result; } /** Test all subgrids - copy each to 1D array for test method. See end of program for explanation of subgrid numbers and starting values. Display invalid boxes on screen. @param grid the puzzle to check @return true if all good, false otherwise */ public static boolean goodBoxes(int[][] grid) { boolean result = true; String invalids = ""; int[] temp = new int[SIZE]; int rowstart, colstart; for (int i = 0; i < SIZE; i++) { rowstart = BLOCKMAX * (i / BLOCKMAX); colstart = BLOCKMAX * (i % BLOCKMAX); int index = 0; for (int r = rowstart; r < rowstart + BLOCKMAX; r++) { for (int c = colstart; c < colstart + BLOCKMAX; c++) { temp[index++] = grid[r][c]; } } if (!testSegment(temp)) { invalids += (i + 1) + " "; result = false; } } if (invalids.length() != 0) { System.out.println("invalid cubes: " + invalids); } return result; } } // class /**************************************** Cube Numbers in double array: x x x x x x x x x x 0 x x 1 x x 2 x x x x x x x x x x x x x x x x x x x x 3 x x 4 x x 5 x x x x x x x x x x x x x x x x x x x x 6 x x 7 x x 8 x x x x x x x x x x Starting rows: 0 for cubes 0, 1, 2 3 for cubes 3, 4, 5 6 for cubes 6, 7, 8 Starting col: 0 for cubes 0, 3, 6 3 for cubes 1, 4, 7 6 for cubes 2, 5, 8 *****************************************/