# 编程之美1.15构造数独-----回溯法java版

完全根据书上给的思路用java写了一下
假如程序进行到(1,7)时，可取的值只有一个list:4;在(1,7)的位置填上4，进行到(1,8),这是list=null,回溯到（1,7），list:4,进行到(1,8),list=null,回溯到(1,7).....
就会这样一直死循环下去，这时应当回溯到(1,6)再向下继续进行，添加了一个回溯次数标记位pro_num
(1,7) list:4 pro_num=0
<pre name="code" class="java">(1,8) list:null
(1,7) pro_num=1=list.size
(1,6) list:7,6 pro_num =1

(1,7) list:5,9 pro_num=0
(1,6) list:1,4
.........
其实这样做也不是完全严谨，假如在(1,6)又选中了使(1,7)list:4的值，则还要回溯到(1,6),这时（1,6）的pro_num=2=list.size,这样又会回溯到(1,5)，但是这样最起码可以得到一个可行解
</pre><pre name="code" class="java">/*
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Test;

import java.util.*;

/**
*
*/
public class Sudoku {

public static class Coord {

public int x;
public int y;

Coord() {
x = -1;
y = -1;
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

}

public static class Cell {

public boolean isProcessed;
public List validList;
public int value;
public int pro_num;

Cell() {
isProcessed = false;
validList = null;
value = -1;
pro_num =0;
}

public void pickValidValue() {
//获取随机数
Random random = new Random();
int result = random.nextInt(this.validList.size());
this.value = (Integer) this.validList.get(result);
}

public void clear() {
this.isProcessed = false;
this.validList = null;
this.value = -1;
}

public boolean getIsIsProcessed() {
return isProcessed;
}

public void setIsProcessed(boolean isProcessed) {
this.isProcessed = isProcessed;
}

public List getValidList() {
return validList;
}

public void setValidList(List validList) {
this.validList = validList;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public int getPro_num() {
return pro_num;
}

public void setPro_num(int pro_num) {
this.pro_num = pro_num;
}

}

public static void main(String[] args) {
Coord coCurrent = new Coord();
coCurrent.setX(0);
coCurrent.setY(0);
int m_size = 9;
Random random = new Random();
Cell[][] m_cells = new Cell[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
m_cells[i][j] = new Cell();
}
}
while (true) {
System.out.println("x="+coCurrent.getX()+"y="+coCurrent.getY());
Cell c = m_cells[coCurrent.getX()][coCurrent.getY()];
System.out.println("c.getIsIsProcessed()="+c.getIsIsProcessed());
List al;
//如果该格子还未填值，获取可取的值
if (!c.getIsIsProcessed()) {
al = getValidValueList(coCurrent, m_cells);
c.setValidList(al);
System.out.println("list"+c.getValidList());
}else{
int pro_num =c.getPro_num()+1;
System.out.println("回溯次数——"+pro_num);
System.out.println("list"+c.getValidList());
c.setPro_num(pro_num);

if(pro_num == c.getValidList().size()){
c.setIsProcessed(false);
c.setValidList(null);
c.setValue(-1);
c.setPro_num(0);
coCurrent = prevCoord(coCurrent);
System.out.println("我要回溯到x="+coCurrent.getX()+"y="+coCurrent.getY());
continue;
}
}
//如果有可选值
if (c.getValidList() != null) {
//c.pickValidValue();  //选一个填进去
if (c.getValidList().size() > 1) {
int result = random.nextInt(c.getValidList().size());
c.setValue((Integer) c.getValidList().get(result));
}else{
c.setValue((Integer) c.getValidList().get(0));
}
c.setIsProcessed(true);
if (coCurrent.getX() == m_size - 1 && coCurrent.getY() == m_size - 1) {
break;
} else {
coCurrent = nextCoord(coCurrent);
}
} else {//如果没有，回溯
//如果当前是(0,0)，结束while循环
if (coCurrent.getX() == 0 && coCurrent.getY() == 0) {
break;
} else {
c.setIsProcessed(false);
c.setValidList(null);
c.setValue(-1);
c.setPro_num(0);
coCurrent = prevCoord(coCurrent);
System.out.println("我要回溯到x="+coCurrent.getX()+"y="+coCurrent.getY());
}
}
}

for (int i = 0; i < m_size; i++) {
for (int j = 0; j < m_size; j++) {
if (j != 8) {
System.out.print(m_cells[i][j].getValue()+"    ");
} else {
System.out.println(m_cells[i][j].getValue());
}

}
}
}

//获取可行解
private static List getValidValueList(Coord coCurrent, Cell[][] m_cells) {
int x = coCurrent.getX();
int y = coCurrent.getY();
List list = new ArrayList();
for (int i = 1; i < 10; i++) {
boolean flag_x = true;
boolean flag_y = true;
boolean flag = true;
int num = i;                  //如果这个地方放的值为num
//判断同一行是否有相同的值
for (int h = 0; h < 9; h++) {
if (h != y && m_cells[x][h].getValue() == num) {
flag_y = false;
}
}
//判断同一列是否有相同的值
for (int l = 0; l < 9; l++) {
if (l != x && m_cells[l][y].getValue() == num) {
flag_x = false;
}
}
//判断同一个3*3的格内有没有重复的
int n = 0;
int m = 0;
if (x % 3 == 0) {
n = x;
} else if (x % 3 == 1) {
n = x - 1;
} else {
n = x - 2;
}
if (y % 3 == 0) {
m = y;
} else if (y % 3 == 1) {
m = y - 1;
} else {
m = y - 2;
}
for (int nn = n; nn < n + 3; nn++) {
for (int mm = m; mm < m + 3; mm++) {
if (nn != x && mm != y && m_cells[nn][mm].getValue() == num) {
flag = false;
}
}
}
if (flag_x && flag_y && flag) {
}
}
if(list.size()>0){
return list;
}else{
return null;
}

}

private static Coord prevCoord(Coord coCurrent) {
int x = coCurrent.getX();
int y = coCurrent.getY();
if (y != 0) {
y = y - 1;
} else {
y = 8;
x = x - 1;
}
coCurrent.setX(x);
coCurrent.setY(y);
return coCurrent;
}

private static Coord nextCoord(Coord coCurrent) {
int x = coCurrent.getX();
int y = coCurrent.getY();
if (y != 8) {
y = y + 1;
} else {
y = 0;
x = x + 1;
}
coCurrent.setX(x);
coCurrent.setY(y);
return coCurrent;
}
}


• 本文已收录于以下专栏：

举报原因： 您举报文章：编程之美1.15构造数独-----回溯法java版 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)