Java 数独解算器问题(回溯算法)无休止地运行
我对Java有点陌生。下面是我尝试制作数独解算器的尝试。到目前为止,这还没有GUI,要输入问题,您必须修改代码本身。通常,程序在大约30毫秒(从一些填充值开始)内完成数独,如果必须从头开始(从空白数独开始),则在大约100毫秒内完成。我面临的问题是,有时程序在没有提供解决方案的情况下继续运行,我必须手动停止它。这是因为数独只有一个或几个解决方案吗?或者是因为它被卡在某种环路上。我还注意到,如果在程序中填充了最底部最右端(8,8),则该程序甚至不会尝试求解数独。也许是因为我的代码的编写方式,它认为数独已经解决了。我可以让它检查最后一个未填充的位置而不是固定位置吗Java 数独解算器问题(回溯算法)无休止地运行,java,sudoku,Java,Sudoku,我对Java有点陌生。下面是我尝试制作数独解算器的尝试。到目前为止,这还没有GUI,要输入问题,您必须修改代码本身。通常,程序在大约30毫秒(从一些填充值开始)内完成数独,如果必须从头开始(从空白数独开始),则在大约100毫秒内完成。我面临的问题是,有时程序在没有提供解决方案的情况下继续运行,我必须手动停止它。这是因为数独只有一个或几个解决方案吗?或者是因为它被卡在某种环路上。我还注意到,如果在程序中填充了最底部最右端(8,8),则该程序甚至不会尝试求解数独。也许是因为我的代码的编写方式,它认为
package sudoku;
public class Sudoku {
static int userGrid[][]=new int[][]
{{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0}};//[Horizontal][Vertical]
static int grid[][]=new int[9][9];//Program experiments
public static void main(String[] args) {
for(int i=0;i<9;i+=1) {
for (int j=0;j<9;j+=1) {
grid[i][j]=userGrid[i][j];
}
}
print(grid);
double timeStart=System.currentTimeMillis();
print(loop(0, 0, grid));
double timeEnd=System.currentTimeMillis();
System.out.println("That took "+(timeEnd - timeStart)+" milliseconds to complete");
}
public static int[][] loop(int y, int x, int[][] grid) {
while(!validity(8, 8, grid) || grid[8][8]==0)//while it's not solved
{
if(userGrid[y][x]!=0){
int yy,xx;
if (x==8) {yy=y+1;xx=0;} else {yy=y; xx=x+1;}
loop(yy, xx, grid);
} else {
if(grid[y][x]<9) {//going forward
grid[y][x]+=1;
if(validity(y, x, grid)) {
int yy,xx;
if (x==8) {yy=y+1;xx=0;} else {yy=y; xx=x+1;}
loop(yy, xx, grid);
}
} else {
grid[y][x]=0;
break;}
}
}
return grid;
}
public static boolean validity(int x, int y, int[][] grid) {
String temp="";
for(int i=0;i<9;i+=1) {
temp+=Integer.toString (grid[i][y]);//horizontal
temp+=Integer.toString (grid[x][i]);//vertical
temp+=Integer.toString (grid[(x/3)*3+i/3][(y/3)*3+i%3]);//square
}
int count=0, idx=0;
while((idx=temp.indexOf(Integer.toString (grid[x][y]),idx))!=-1)
{idx+=1;count+=1;}
return count==3;
}
public static void print(int[][] grid) {
System.out.println();
for(int i=0;i<9;i+=1) {
for (int j=0;j<9;j+=1) {
System.out.print(grid[i][j]);
}
System.out.println();
}
}
}
package数独;
公共级数独{
静态int userGrid[][]=新int[][]
{{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0};/[水平][垂直]
静态整数网格[][]=新整数[9][9];//程序实验
公共静态void main(字符串[]args){
对于(int i=0;有很多模棱两可的问题。stackoverflow上有很多数独回溯解决方案问题。它们有帮助吗?大多数都是以不同的方式完成的,没有人经历过这个问题。我也不清楚可能需要什么样的细节。你肯定不希望我们调试你的代码吗?也许你可以开始解耦你的代码r编码并添加方法,如checkRow
checkColumn
,然后重新设计循环。
package sudoku;
public class Sudoku {
static int userGrid[][]=new int[][]
{{2,0,0,4,0,0,0,0,0},
{0,0,4,0,9,0,0,0,0},
{0,0,0,0,6,0,8,7,0},
{7,0,2,0,0,0,0,8,0},
{0,0,0,7,0,0,0,0,9},
{0,4,9,0,0,2,0,0,5},
{0,8,0,0,0,7,1,9,3},
{0,5,0,0,0,4,0,0,0},
{0,0,0,8,0,0,0,0,0}};//[Horizontal][Vertical]
static int grid[][]=new int[9][9];//Program experiments
//static String pGrid[][]=new String[9][9];//Possibilities
public static void main(String[] args) {
for(int i=0;i<9;i+=1) {
for (int j=0;j<9;j+=1) {
grid[i][j]=userGrid[i][j];
}
}
print(grid);
double timeStart=System.currentTimeMillis();
int lastPos = findLastCell();
if (lastPos == 0){
return;
}
int lastY = lastPos % 16;
int lastX = lastPos / 16;
print(loop(0, 0, lastY, lastX, grid));
double timeEnd=System.currentTimeMillis();
System.out.println("That took "+(timeEnd - timeStart)+" milliseconds to complete");
}
public static int findLastCell(){
for (int i=8; i>=0; i--){
for (int j=8; j>=0; j--){
if (userGrid[i][j]==0){
return ((j * 16) + i);
}
}
}
return 0;
}
public static int[][] loop(int y, int x, int lastY, int lastX, int[][] grid) {
while(!validity(lastY, lastX, grid) || grid[lastY][lastX]==0)//while it's not solved
{
while (userGrid[y][x]!=0){
if (x==8)
{
// System.out.println("Here 2");
y=y+1;
x=0;
}
else
{
x=x+1;
}
}
if(grid[y][x]<9) {//going forward
grid[y][x]+=1;
if(validity(y, x, grid)) {
int yy,xx;
if (x==8)
{
//System.out.println("Here");
yy=y+1;
xx=0;
}
else
{
yy=y;
xx=x+1;
}
loop(yy, xx, lastY, lastX, grid);
}
} else {
grid[y][x]=0;
break;}
}
return grid;
}
public static boolean validity(int x, int y, int[][] grid) {
String temp="";
for(int i=0;i<9;i+=1) {
temp+=Integer.toString (grid[i][y]);//horizontal
temp+=Integer.toString (grid[x][i]);//vertical
}
for (int i=0; i<3; i++){
for (int j=0; j<3; j++){
temp+=Integer.toString (grid[(x/3)*3+i][(y/3)*3+j]);
//square (Java doesn't round the divided no.s if they
//are fractions. It jjust outputs them as 0
}
}
int count=0, idx=0;
while((idx=temp.indexOf(Integer.toString (grid[x][y]),idx))!=-1)
{idx+=1;count+=1;}
return count==3;
}
public static void print(int[][] grid) {
System.out.println();
for(int i=0;i<9;i+=1) {
for (int j=0;j<9;j+=1) {
System.out.print(grid[i][j]);
}
System.out.println();
}
}
}