I know it may be fairly bad. I want to find out exactly how horrendous it is and any suggestions on how to improve are appreciated.
public class SudokuSolver_4{
//Creating the main sudoku board
int sudokuGraph[][] = new int[9][9];
public boolean attemptAssignValue(int leftIndex, int upIndex){
//Attempt to assign a value to the specified cell
for(int x = 0; x < 10 ; x++){
if(notContainedInRow(leftIndex, x) && notContainedInColumn(upIndex, x) && notContainedInSubGrid(leftIndex, upIndex, x)){
sudokuGraph[leftIndex][upIndex] = x;
return true;
}
}
return false;
}
public boolean attemptAssignValue(int leftIndex, int upIndex, int startValue){
//When the program backtracks and has to reassign a value, this overloaded version of the assignent function takes a third parameter - the value that the cell currently has, so that the program does not reassign it
if(startValue != 9){
for(int x = startValue; x < 10; x++){
if(notContainedInRow(leftIndex, x) && notContainedInColumn(upIndex, x) && notContainedInSubGrid(leftIndex, upIndex, x)){
sudokuGraph[leftIndex][upIndex] = x;
return true;
}
}
return false;
}
else{
//This return is because it complained of no definite return statement in the method, as the other one was still in the larger if statement
return false;
}
}
public boolean notContainedInRow(int leftIndex, int numberToCheck){
//Uses a simple nested loop to check if the particular number is anywhere in the row
for (int upIndex = 0; upIndex < 9; upIndex++){
if (sudokuGraph[leftIndex][upIndex] == numberToCheck){
return false;
}
}
return true;
}
public boolean notContainedInColumn(int upIndex, int numberToCheck){
//Uses another nested loop to make sure that number is not anywhere in the column
for (int leftIndex = 0; leftIndex < 9; leftIndex++){
if(sudokuGraph[leftIndex][upIndex] == numberToCheck){
return false;
}
}
return true;
}
public boolean notContainedInSubGrid(int leftIndex, int upIndex, int numberToCheck){
/* A peice of code that could definitely be improved. It is a successive if else ladder that check which grid a particular value is in. The logic is simple:
It assumes that each grid is bound by two indexes - one on the upper side and one on the left side. So if the cell was in the first grid, it's leftIndex would be less than three
and its upIndex would also be less than three. And so on. And as the ladder is if else, we don't need to define a greater than condition.*/
int boundLeftIndex = 0;
int boundUpIndex = 0;
if (leftIndex < 3 && upIndex < 3){
boundLeftIndex = 0;
boundUpIndex = 0;
}
else if (leftIndex < 3 && upIndex < 6){
boundLeftIndex = 0;
boundUpIndex = 3;
}
else if (leftIndex < 3 && upIndex < 9){
boundLeftIndex = 0;
boundUpIndex = 6;
}
else if (leftIndex < 6 && upIndex < 3){
boundLeftIndex = 3;
boundUpIndex = 0;
}
else if (leftIndex < 6 && upIndex < 6){
boundLeftIndex = 3;
boundUpIndex = 3;
}
else if (leftIndex < 6 && upIndex < 9){
boundLeftIndex = 3;
boundUpIndex = 6;
}
else if (leftIndex < 9 && upIndex < 3){
boundLeftIndex = 6;
boundUpIndex = 0;
}
else if (leftIndex < 9 && upIndex < 6){
boundLeftIndex = 6;
boundUpIndex = 3;
}
else if (leftIndex < 9 && upIndex < 9){
boundLeftIndex = 6;
boundUpIndex = 6;
}
//Returns the boolean result of a call to another method which actually check whether or not the value is in the grid
return notContainedInGridCheck(boundLeftIndex, boundUpIndex, numberToCheck);
}
public boolean notContainedInGridCheck(int leftIndex, int upIndex, int numberToCheck){
//Uses a nested loop to traverse the subgrid and determine whether the value is present
int x = leftIndex;
int y = upIndex;
for (x = leftIndex; x < leftIndex + 3; x++){
for (y = upIndex; y < upIndex + 3; y++){
if (sudokuGraph[x][y] == numberToCheck){
return false;
}
}
}
return true;
}
public int[] goBackOneCell(int leftIndex, int upIndex){
/* Simply returns the index values for the previous cell on the graph. If it works properly there should be no need to specify a exception for the beginning
and end of the grid as the program shold never encounter that situation */
if (upIndex == 0){
upIndex = 8;
leftIndex--;
}
else{
upIndex--;
}
int newValues[] = new int[2];
newValues[0] = leftIndex;
newValues[1] = upIndex;
return newValues;
}
public int[] goAheadOneCell(int leftIndex, int upIndex){
//Similar to the goBack function, this function returns the value of the next cell instead
if (upIndex == 8){
upIndex = 0;
leftIndex++;
}
else{
upIndex++;
}
int newValues[] = new int[2];
newValues[0] = leftIndex;
newValues[1] = upIndex;
return newValues;
}
public void showTable(){
//Used to print the graph
for (int leftIndex = 0; leftIndex < 9; leftIndex++){
for (int upIndex = 0; upIndex < 9; upIndex++){
System.out.print(sudokuGraph[leftIndex][upIndex]);
System.out.print(" ");
}
System.out.println();
System.out.println("------------------------------------");
}
System.out.println();
System.out.println("**END**");
System.out.println();
}
public void control(){
//The method which incorporates the above methods into a working solution
int leftIndex = 0;
int upIndex = 0;
boolean assignmentAttempt;
int values[] = new int[2];
//The first assignment must be done outside of the loop as the boolean assigmentAttempt must be true for the loop to run
//Yes, there are a hundred other ways of doing this (probably)
assignmentAttempt = attemptAssignValue(leftIndex, upIndex);
//Infinite loop, that is acually a non-infinite loop with a specific exit criteria (like most forever loops I presume)
for(; ;){
//The if statement that handles what to do after a successful assignment
if(assignmentAttempt == true){
//Checks if the end of the graph has been reached, if so, it breaks
if(leftIndex == 8 && upIndex == 8){
showTable();
break;
}
//If the end has not been reached, it goes ahead one cell and attempts the assignment again. The outcome of the assignment is expressed by the assignmentAttempt variable
values = goAheadOneCell(leftIndex, upIndex);
leftIndex = values[0];
upIndex = values[1];
//The next to print statements were only for debugging, they serve no useful purpose to the end user
System.out.print(leftIndex);
System.out.print(upIndex);
System.out.println();
assignmentAttempt = attemptAssignValue(leftIndex, upIndex);
}
//The loop continues. If the assignment succeeded it goes back to the beginning after printing the table
//Otherwise, it goes back one cell and attempts to assign again. Note that here, the overloaded version of the assignment method is used so that already previously assigned values are not reassigned
//This if loop will continue to execute until another successful assignment occurs, ending the backtrack
if(assignmentAttempt == false){
sudokuGraph[leftIndex][upIndex] = 0;
values = goBackOneCell(leftIndex, upIndex);
leftIndex = values[0];
upIndex = values[1];
//Again, the next two print statements are only for debugging
System.out.print(leftIndex);
System.out.print(upIndex);
System.out.println();
//The same assignment variable is used for control
assignmentAttempt = attemptAssignValue(leftIndex, upIndex, sudokuGraph[leftIndex][upIndex]);
}
//Printing the table at the end of each attempt
showTable();
}
}
}