我使用四维数组在Java中编写数独求解器,其中维度描述了单元格在板上的位置,分配给它们的值是单元格可能的数字。 Sudoku Wikipedia, for reference
为了清晰起见,我编写了打印电路板的Unicode艺术表示的方法,以及打印电路板上每个单元的所有选项的方法。这些方法有效。但是,我从单个行,列和框中的其他单元格中消除单例的方法无法正常工作(从未知单元格中移除同一行/列/框中的所有已知单元格)。请注意,左上角的单元格(choiceArray[0][0][0][0]
)应该是字符串467
,而是23478
。这是我写的代码。数独板输入为81个字符的字符串,其中0' s表示初始板中的空单元格。
(除了回答这个问题之外,我还会欣赏来自比我更有经验的程序员的风格/程序建议,因为我非常喜欢初学者)
public class SudokuSolver {
public static void main(String[] args) {
String initialBoard = "020501090800203006030060070001000600540000019002000700090030080200804007010907060";
//Parsing the input to make sure that it is valid
if (!(initialBoard.matches("[0-9]+") && initialBoard.length() == 81)) {
System.err.println("Input board was not valid.");
System.exit(0);
}
//Generating the sudoku board
printBoard(initialBoard);
//Generating an array for the given information
String[][][][] choiceArray = new String[3][3][3][3];
for(int i = 0; i < 3; i++) { //row of box
for(int j = 0; j < 3; j++) { //column of box
for(int k = 0; k < 3; k++) { //row in box
for(int l = 0; l < 3; l++) { //column in box
int cellNumber = 27 * i + 3 * j + 9 * k + l;
char cellContents = initialBoard.charAt(cellNumber);
if(cellContents == '0') {
choiceArray[i][j][k][l] = "123456789";
}
else {
choiceArray[i][j][k][l] = Character.toString(cellContents);
}
}
}
}
}
//Removing singletons
while(!(puzzleIsSolved(choiceArray))) {
boolean boardChanges = false;
for(int i = 0; i < 3; i++) { //row of box
for(int j = 0; j < 3; j++) { //column of box
for(int k = 0; k < 3; k++) { //row in box
for(int l = 0; l < 3; l++) { //column in box
if(choiceArray[i][j][k][l].length() == 1) {
String solvedCell = choiceArray[i][j][k][l];
//Removing choice from row (i, k constant)
for(int a = 0; a < 3; a++) {
for(int b = 0; b < 3; b++) {
if(a != j && b != l) {
if(choiceArray[i][a][k][b].contains(solvedCell)) {
choiceArray[i][a][k][b] = removeChoice(choiceArray[i][a][k][b], solvedCell);
boardChanges = true;
}
}
}
}
//Removing choice from column (j, l constant)
for(int a = 0; a < 3; a++) {
for(int b = 0; b < 3; b++) {
if(a != i && b != k) {
if(choiceArray[a][j][b][l].contains(solvedCell)) {
choiceArray[a][j][b][l] = removeChoice(choiceArray[a][j][b][l], solvedCell);
boardChanges = true;
}
}
}
}
//Removing choice from box (i, j constant)
for(int a = 0; a < 3; a++) {
for(int b = 0; b < 3; b++) {
if(a != i && b != j) {
if(choiceArray[a][b][k][l].contains(solvedCell)) {
choiceArray[a][b][k][l] = removeChoice(choiceArray[a][b][k][l], solvedCell);
boardChanges = true;
}
}
}
}
}
}
}
}
}
if(!boardChanges) {
break;
}
}
System.out.println(choiceArray[0][0][0][0]);
//expected: 467
//actual: 23478
}
//Printing the current state of the sudoku
public static void printBoard(String input) {
String rowA = "╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗";
String rowB = "╟───┼───┼───╫───┼───┼───╫───┼───┼───╢";
String rowC = "╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣";
String rowD = "╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝";
input = input.replaceAll("0", " ");
System.out.println(rowA);
for(int row = 0; row < 9; row++) {
for(int box = 0; box < 3; box++) {
System.out.print("║");
for(int cell = 0; cell < 3; cell++) {
System.out.print(" " + input.charAt(9 * row + 3 * box + cell) + " ");
if(cell != 2) {
System.out.print("│");
}
}
}
System.out.println("║");
if(row % 3 == 2 && row != 8) {
System.out.println(rowC);
}
else if(row != 8){
System.out.println(rowB);
}
else {
System.out.println(rowD);
}
}
}
//Print all possible choices in all cells in sudoku (good for debugging)
public static void printAllChoices(String[][][][] choiceArray) {
for(int i = 0; i < 3; i++) { //row of box
for(int k = 0; k < 3; k++) { //row in box
for(int j = 0; j < 3; j++) { //column of box
for(int l = 0; l < 3; l++) { //column in box
int cellNumber = 27 * i + 3 * j + 9 * k + l + 1;
System.out.println(cellNumber + ": " + choiceArray[i][j][k][l]);
}
}
}
}
}
//Check if all cells only have one choice left
public static boolean puzzleIsSolved(String[][][][] choiceArray) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 3; k++) {
for(int l = 0; l < 3; l++) {
if(choiceArray[i][j][k][l].length() > 1) {
return false;
}
}
}
}
}
return true;
}
//Removing choice from cell
public static String removeChoice(String initialChoices, String choiceToRemove) {
String finalChoices = "";
for(int i = 0; i < initialChoices.length(); i++) {
if(initialChoices.charAt(i) != choiceToRemove.charAt(0)) {
finalChoices += initialChoices.charAt(i);
}
}
return finalChoices;
}
}