CJ今天太上午太无聊,就下了个数独玩,结果没耐心,突发奇想不如写个程序解数独,一次努力,永久福利。于是就着手了。
CJ比较直,就像先写个界面出来看看,结果就是这样。
别说话,吻我。我知道这界面很丑。不要在意细节,能用就好。下面是代码。
package Soduko;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Resolving implements Runnable {
private int k;//确认数量
private int[][] sodu = new int[9][9];
private Piece [][]piece = new Piece[9][9];
private ArrayList
> line=new ArrayList
>();//行
private List
> list=new ArrayList
>();//列 private List
> grid=new ArrayList
>();//宫格 // private HashSet
[]list;//列 // private HashSet
[]grid;//宫格 public Resolving(int[][] sodu){ this.sodu = sodu; } //初始化 public void init(){ //初始化行列宫格 for (int i = 0; i < 9; i++) { line.add(new HashSet
()); } for (int i = 0; i < 9; i++) { list.add(new HashSet
()); } for (int i = 0; i < 9; i++) { grid.add(new HashSet
()); } //初始化题目已给出的棋格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { piece[i][j]=new Piece(); if(sodu[i][j]!=0){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(sodu[i][j]); piece[i][j].setI(i); piece[i][j].setJ(j); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); } } } System.out.println("成功初始化"+k+"个棋格。"); showResult(); //初始化所有空格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if(sodu[i][j]==0){ piece[i][j].suspects.removeAll(line.get(i)); piece[i][j].suspects.removeAll(list.get(j)); piece[i][j].suspects.removeAll(grid.get(j/3+((int)i/3)*3)); // if(piece[i][j].getStatus()==1){ // // } } } } } @Override public void run() { System.out.println("初始化……"); init(); System.out.println("开始解算……"); while(true){ for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { check(i,j); } } if(k==81){ System.out.println("解算成功!"); showResult(); return; } } } //显示解算结果 public void showResult(){ for (int i = 0; i < 9; i++) { System.out.println(); if(i%3==0){ System.out.println(); } for (int j = 0; j < 9; j++) { System.out.print(piece[i][j].getValue()); if(j%3==2){ System.out.print(" "); } } } } //填入数 public void confirm(int i,int j){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(piece[i][j].getSuspects().iterator().next()); sodu[i][j]=piece[i][j].getValue(); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); System.out.println("i="+i+",j="+j+"填入数:"+sodu[i][j]+" k="+k); showResult(); update(i,j); } //检查是否可填入,如果嫌疑数只剩下一个,即填入数字。 public void check(int i,int j){ if(!piece[i][j].isStatus()&&piece[i][j].getSuspects().size()==1){ confirm(i,j); } } //更新嫌疑数。根据填入的数更新同行、列、宫格其他空格的嫌疑数。 public void update(int i,int j){ for (int m = 0; m < 9; m++) { if(!piece[i][m].isStatus()){ piece[i][m].suspects.remove(piece[i][j].getValue()); check(i,m); } } for (int m = 0; m < 9; m++) { if(!piece[m][j].isStatus()){ piece[m][j].suspects.remove(piece[i][j].getValue()); check(m,j); } } for(int m=((int)i/3)*3;m<((int)i/3)*3+3;m++){ for(int n=((int)j/3)*3;n<((int)j/3)*3+3;n++){ if(!piece[m][n].isStatus()){ piece[m][n].suspects.remove(piece[i][j].getValue()); check(m,n); } } } } }
关键还是算法,真正有趣的地方。
思路一:
private List<HashSet<Integer>> line=new ArrayList<HashSet<Integer>>();//行
private List<HashSet<Integer>> list=new ArrayList<HashSet<Integer>>();//列
private List<HashSet<Integer>> grid=new ArrayList<HashSet<Integer>>();//宫格
//初始化行列宫格
for (int i = 0; i < 9; i++) {
line.add(new HashSet<Integer>());
}
for (int i = 0; i < 9; i++) {
list.add(new HashSet<Integer>());
}
for (int i = 0; i < 9; i++) {
grid.add(new HashSet<Integer>());
}
新建这27个集合类,分别记录每一行、列、宫格已出现的数字。每个棋格排除自己所在的行、列、宫格已出现的数字,得出剩下的数字集Set<Integer> suspects。当剩下的数字集只剩下一个的时候,便是该棋格应填的数字。填入新数字后重新更新以上的集合类。
代码附上
解算代码
package Soduko;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Resolving implements Runnable {
private int k;//确认数量
private int[][] sodu = new int[9][9];
private Piece [][]piece = new Piece[9][9];
private ArrayList
> line=new ArrayList
>();//行
private List
> list=new ArrayList
>();//列 private List
> grid=new ArrayList
>();//宫格 // private HashSet
[]list;//列 // private HashSet
[]grid;//宫格 public Resolving(int[][] sodu){ this.sodu = sodu; } //初始化 public void init(){ //初始化行列宫格 for (int i = 0; i < 9; i++) { line.add(new HashSet
()); } for (int i = 0; i < 9; i++) { list.add(new HashSet
()); } for (int i = 0; i < 9; i++) { grid.add(new HashSet
()); } //初始化题目已给出的棋格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { piece[i][j]=new Piece(); if(sodu[i][j]!=0){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(sodu[i][j]); piece[i][j].setI(i); piece[i][j].setJ(j); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); } } } System.out.println("成功初始化"+k+"个棋格。"); showResult(); //初始化所有空格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if(sodu[i][j]==0){ piece[i][j].suspects.removeAll(line.get(i)); piece[i][j].suspects.removeAll(list.get(j)); piece[i][j].suspects.removeAll(grid.get(j/3+((int)i/3)*3)); // if(piece[i][j].getStatus()==1){ // // } } } } } @Override public void run() { System.out.println("初始化……"); init(); System.out.println("开始解算……"); while(true){ for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { check(i,j); } } if(k==81){ System.out.println("解算成功!"); showResult(); return; } } } //显示解算结果 public void showResult(){ for (int i = 0; i < 9; i++) { System.out.println(); if(i%3==0){ System.out.println(); } for (int j = 0; j < 9; j++) { System.out.print(piece[i][j].getValue()); if(j%3==2){ System.out.print(" "); } } } } //填入数 public void confirm(int i,int j){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(piece[i][j].getSuspects().iterator().next()); sodu[i][j]=piece[i][j].getValue(); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); System.out.println("i="+i+",j="+j+"填入数:"+sodu[i][j]+" k="+k); showResult(); update(i,j); } //检查是否可填入,如果嫌疑数只剩下一个,即填入数字。 public void check(int i,int j){ if(!piece[i][j].isStatus()&&piece[i][j].getSuspects().size()==1){ confirm(i,j); } } //更新嫌疑数。根据填入的数更新同行、列、宫格其他空格的嫌疑数。 public void update(int i,int j){ for (int m = 0; m < 9; m++) { if(!piece[i][m].isStatus()){ piece[i][m].suspects.remove(piece[i][j].getValue()); check(i,m); } } for (int m = 0; m < 9; m++) { if(!piece[m][j].isStatus()){ piece[m][j].suspects.remove(piece[i][j].getValue()); check(m,j); } } for(int m=((int)i/3)*3;m<((int)i/3)*3+3;m++){ for(int n=((int)j/3)*3;n<((int)j/3)*3+3;n++){ if(!piece[m][n].isStatus()){ piece[m][n].suspects.remove(piece[i][j].getValue()); check(m,n); } } } } }
package Soduko;
import java.util.HashSet;
import java.util.Set;
public class Piece {
private int i,j;
private boolean status = false;//状态:false表示未知,true表示已确定,1表示未确定
public Set
suspects=new HashSet
();//可能的结果
private int value;//确定的值
public Piece(){
for (int z = 1; z < 10; z++) {
suspects.add(z);
}
}
public Set
getSuspects() {
return suspects;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public void setSuspects(Set
suspects) {
this.suspects = suspects;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public int getJ() {
return j;
}
public void setJ(int j) {
this.j = j;
}
}