//************************************************************************************************* // Sudoku_Solver.java authors: (AL)^2 (i.e., Aaron Logan and Austin Lyons) // Started 31 March 2006, finished 1 April 2006 // This program uses some sweet code to solve a Sudoku puzzle. While your friends are gnashing // their teeth over their inability to solve a puzzle, you can sit back while your computer // does the work for you. // Check out for a catalog of Sudoku puzzles //************************************************************************************************* import java.util.Scanner; public class Sudoku_Solver { private static int[][] grid = new int[9][9]; //----------------------------------------------------------------------------------------------- // Main method: drives the solving process, manages output to user. //----------------------------------------------------------------------------------------------- public static void main(String[] args) { Scanner read = new Scanner(System.in); System.out.println ("To enter a row of the given Sudoku puzzle, enter zeros for empty spaces and separate numbers with spaces."); System.out.println ("Example: [ ][ ][9][8][ ][6][5][ ][ ] should be entered as 0 0 9 8 0 6 5 0 0 \n"); /* Get user input to initialize puzzle grid */ int i, j; for (i=0; i<9; i++){ System.out.print ("Please enter row " +(i+1) + ": "); for (j=0; j<9; j++){ grid[i][j] = read.nextInt(); grid[i][j] *= -1; } } System.out.println("\nOriginal puzzle: "); System.out.println(GridToString()); if (Solve(0,0)) System.out.println ("The puzzle was solved successfully:"); else System.out.println ("The program failed to solve the puzzle:"); System.out.println(GridToString()); } //----------------------------------------------------------------------------------------------- // Solve method: this method works the magic using wonderful recursion. //----------------------------------------------------------------------------------------------- public static boolean Solve(int row, int col) { int possibility = 1; boolean done = false; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BASE CASE: THE PROGRAM IS NOW AT THE LAST CELL (BOTTOM RIGHT) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // The program must look at the sign (neg or pos) to determine if this cell contains a value // that is a predefined part of the puzzle. If the cell is predefined, then the program is // successful (because you can't get here unless all preceding values fit) and this invocation // of the method returns true. If this part is not predefined, then the program searches for a // value that fits. Ideally, the program finds one that fits and returns true in this method // invocation. If it doesn't find a value that fits, then this method invocation returns false, // and the puzzle is unsolveable. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (row == 8 && col == 8) { if (grid[row][col] < 0) done = true; else while (possibility <= 9 && !done) { grid[row][col] = possibility; if (Test(row, col)) done = true; possibility++; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RECURSIVE PART: WHAT TO DO IF THIS CELL IS NOT THE LAST ONE // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // First, determine which cell will be checked next, and assign parameters for the next // recursive method invocation accordingly: if the current cell is not at the end of the row, // then the next cell is the adjacent one to the right. If the current cell is at the end of // the row, then the next cell is at the beginning of the next row. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Second, the program must look at the sign of the value to determine if this cell contains // a value that is a predefined part of the puzzle. If the cell is predefined, then the program // skips over this cell and calls the Solve method for the next cell. If it is not predefined, // then the program assigns it a value that fits and then calls the Solve method for the next // cell. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else { int nextRow, nextCol; if (col < 8){ nextRow = row; nextCol = col + 1;} else{ nextRow = row + 1; nextCol = 0;} if (grid[row][col] < 0) done = Solve(nextRow, nextCol); else { while (!done && possibility <= 9) { grid[row][col] = possibility; if (Test(row, col)) done = Solve(nextRow, nextCol); possibility++; } if (!done) grid[row][col] = 0; } } return done; } //----------------------------------------------------------------------------------------------- // Test method: checks the row, column, and inner 3x3 grid section surrounding the given cell // for values that match the one held in this cell. If any of the checked values match the // one in this cell, then the test returns false, indicating failure. //----------------------------------------------------------------------------------------------- public static boolean Test(int row, int col) { int i, j, testRow, testCol; boolean result = true; for (i=0; i<9; i++) { if (i != col && Math.abs(grid[row][i]) == Math.abs(grid[row][col])) //test row for equal values result = false; if (i != row && Math.abs(grid[i][col]) == Math.abs(grid[row][col])) //test column for equal values result = false; } if (result) //No need to keep testing if the test has already failed. Keep testing if it hasn't. for (i=0; i<3; i++) //test 3x3 section for equal values for (j=0; j<3; j++) { testRow = 3*(row / 3) + i; testCol = 3*(col / 3) + j; if (testRow != row && testCol != col && Math.abs(grid[row][col]) == Math.abs(grid[testRow][testCol])) result = false; } return result; } //----------------------------------------------------------------------------------------------- // GridToString method: returns a string representation of the array grid for printing. //----------------------------------------------------------------------------------------------- public static String GridToString() { String GridString = "\n"; int i, j; for (i=0; i<9; i++) { for (j=0; j<9; j++) { GridString += ((grid[i][j] == 0) ? " " : Math.abs(grid[i][j])); GridString += ((j==2 || j==5) ? "|" : " "); } GridString += "\n"; if (i==2 || i==5) GridString += "-----+-----+-----\n"; } return GridString; } }