您的位置:首页 > 编程语言 > Java开发

使用java程序帮你解数独

2012-09-24 17:12 218 查看
相信数独大家都多少有玩过吧?就是一个3x3 的9个块、每块里面又是3x3的小块

使每行每列都填充1-9的数字且只能使用一次、一般期刊后面都会有数独小游戏的、

以前也玩过数独、但是太难的就不知道该怎么解了、

今天逛了外国网站、发现一解数独的小程序、偷拿来分享、

只使用了两个类 SudokuSolver 和 Grid 、

先贴源码:

SudokuSolver

/**
* This program is executed in the following way:
*    java SudokuSolver <input-file>
* For details of the input-file format, see the Grid.java class.
*
* @author  Patrick Chan
* @version 1, 12/31/05
* @see Grid
*/
import java.io.*;
import java.util.*;

public class SudokuSolver {
public static void main(String[] args) throws Exception {
// Open the file containing the givens
String arg = "C:/ad.txt";

//File file = new File(arg);
FileReader rd = new FileReader(arg);

// Process each grid in the file
while (true) {
Grid grid = Grid.create(rd);
if (grid == null) {
// No more grids
break;
}

// Find a solution
List<Grid> solutions = new ArrayList<Grid>();
solve(grid, solutions);

printSolutions(grid, solutions);
}
}

// Recursive routine that implements the bifurcation algorithm
private static void solve(Grid grid, List<Grid> solutions) {
// Return if there is already a solution
if (solutions.size() >= 2) {
return;
}

// Find first empty cell
int loc = grid.findEmptyCell();

// If no empty cells are found, a solution is found
if (loc < 0) {
solutions.add(grid.clone());
return;
}

// Try each of the 9 digits in this empty cell
for (int n=1; n<10; n++) {
if (grid.set(loc, n)) {
// With this cell set, work on the next cell
solve(grid, solutions);

// Clear the cell so that it can be filled with another digit
grid.clear(loc);
}
}
}

private static void printSolutions(Grid grid, List<Grid> solutions) {
// Print the grid with the givens
System.out.println("Original");
System.out.println(grid);

// Print the solution
if (solutions.size() == 0) {
System.out.println("Unsolveable");
} else if (solutions.size() == 1) {
System.out.println("Solved");
} else {
System.out.println("At least two solutions");
}

// Print the solution(s)
for (int i=0; i<solutions.size(); i++) {
System.out.println(solutions.get(i));
}
System.out.println();
System.out.println();
}
}


和 Grid

/**
* @author  Patrick Chan
* @version 1, 12/31/05
* @see SudokuSolver
*/
import java.io.Reader;

/**
* A Grid object holds the currently known values of the Sudoku puzzle.
* The grid consists of 9x9 cells that hold integer values from 0 to 9.
* A value of 0 indicates that the cell is empty.
*
* Each of the 81 cells has a location which is used to identify a
* specific cell. There are 81 locations, labelled location 0 to location 80.
* Cell locations are ordered from left-to-right and top-down.
* For example, location 0 refers to the top-leftmost cell.
* Location 8 refers to the top-righttmost cell.
* Location 71 refers to the bottom-leftmost cell.
* Location 80 refers to the bottom-rightmost cell.
*
* The grid consists of 9 columns, labelled column 0 to column 8.
* The grid consists of 9 rows, labelled row 0 to row 8.
*
* The grid consists of 9 subgrids, labelled subgrid 0 to subgrid 8.
* Each subgrid contains a subgrid of 3x3 cells.
* Subgrid 0 contains cells - 0, 1, 2, 9, 10, 11, 18, 19, 20.
* Subgrid 8 contains cells - 60, 61, 62, 69, 70, 71, 78, 79, 80
*/
public class Grid implements Cloneable {
// Array that contains values of all 81 cells in the grid.
int[] cells = new int[81];

// A set of bit-vectors that represent the known values for each column.
// Specifically, if column c contains the digits d1 and d2,
//   colsSet[c] = 2^(d1-1)|2^(d2-1)
// For example, if column 0 contains the values 1 and 4, colsSet[0] = 9.
// The information in this variable is redundant with the information
// in the cells variable. The purpose of this variable is to reduce
// the cost of determining whether a particular digit can be set in
// a particular cell.
int[] colsSet = new int[9];

// This purpose and behavior of this variable is similar to colsSet.
int[] rowsSet = new int[9];

// This purpose and behavior of this variable is similar to colsSet.
int[] subgridSet = new int[9];

/**
* This method returns a grid of givens and empty cells ready to be solved.
* The cells containing givens have values between 1 and 9.
* Empty cells have the value 0.
*
* Characters are read one at a time from the input stream and placed
* into the grid in left-to-right and top-down order.
* - The characters 0 or . indicates an empty cell.
* - The characters 1 to 9 indicates a given.
* - The character # is used for comments; subsequent characters are
*   ignored until a newline is encountered.
* - All other characters are simply ignored.
*
* @param     rd  Reader containing the givens
* @return    null if there are not enough characters in 'rd' to form a grid.
*/
public static Grid create(Reader rd) throws Exception {
Grid grid = new Grid();

// Read until all 81 cells are filled
for (int loc=0; loc<grid.cells.length; ) {
// Read a character
int ch = rd.read();

// -1 is returned if the input stream has no more characters
if (ch < 0) {
// No more characters so return null
return null;
}
if (ch == '#') {
// Skip to end-of-line
while (ch >= 0 && ch != '\n' && ch != '\r') {
ch = rd.read();
}
} else if (ch >= '1' && ch <= '9') {
// A given
grid.set(loc, ch-'0');
loc++;
} else if (ch == '.' || ch == '0') {
// Empty cell
loc++;
}
}
return grid;
}

/*
* Finds an empty cell.
* @return the location of an empty cell or -1 if there are no empty cells.
*         Values must be in the range [-1, 80].
*/
public int findEmptyCell() {
for (int i=0; i<cells.length; i++) {
if (cells[i] == 0) {
return i;
}
}
return -1;
}

/*
* Sets a number in a cell. This method checks to see if
*   1. the cell is empty
*   2. the cell is allowed to contain the specified number. E.g. if
*      the number is 5 but the row already has a 5, the cell will
*      not be set and false is returned.
* @param loc  the location of the target cell.
*             Values must be in the range [0, 80].
* @param num  the number to set in the cell.
*             Values must be in the range [1, 9].
* @return     true if the set was successful.
*/
public boolean set(int loc, int num) {
// Compute row and column
int r = loc/9;
int c = loc%9;
int blockLoc = (r/3)*3+c/3;

boolean canSet = cells[loc] == 0
&& (colsSet[c] & (1<<num)) == 0
&& (rowsSet[r] & (1<<num)) == 0
&& (subgridSet[blockLoc] & (1<<num)) == 0;
if (!canSet) {
return false;
}

cells[loc] = num;
colsSet[c] |= (1<<num);
rowsSet[r] |= (1<<num);
subgridSet[blockLoc] |= (1<<num);
return true;
}

/*
* Removes the number in a cell.
* @param loc  the location of the target cell.
*             Values must be in the range [0, 80].
*/
public void clear(int loc) {
// Compute row and column
int r = loc/9;
int c = loc%9;
int blockLoc = (r/3)*3+c/3;

int num = cells[loc];
cells[loc] = 0;
colsSet[c] ^= (1<<num);
rowsSet[r] ^= (1<<num);
subgridSet[blockLoc] ^= (1<<num);
}

/**
* Returns a copy of this grid. Any modifications to the returned
* grid will not affect this grid.
*
* @return a non-null deep copy of this grid.
*/
public Grid clone() {
Grid grid = new Grid();
grid.cells = cells.clone();
grid.colsSet = colsSet.clone();
grid.rowsSet = rowsSet.clone();
grid.subgridSet = subgridSet.clone();
return grid;
}

/**
* Returns a string representing the current contents of the grid.
* Used for debugging purposes.
*
* @return a non-null string representing the current contents of the grid.
*/
public String toString() {
StringBuffer buf = new StringBuffer();
for (int r=0; r<9; r++) {
if (r%3 == 0) {
buf.append("-------------------------\n");
}
for (int c=0; c<9; c++) {
if (c%3 == 0) {
buf.append("| ");
}
int num = cells[r*9+c];
if (num == 0) {
buf.append(". ");
} else {
buf.append(num+" ");
}
}
buf.append("|\n");
}
buf.append("-------------------------");
return buf.toString();
}
}


自己建立个文件自己定义好路径

贴上你要解的数独格式、(格式应该有很多种、我只知道2种)

先贴出来几个

1、

-------------------------

| . . 8 | . . . | 2 . . |

| . 3 . | 8 . 2 | . 6 . |

| 7 . . | . . 9 | . . 5 |

-------------------------

| . 5 . | . . . | . 1 . |

| . . 4 | . . . | 6 . . |

| . 2 . | . . . | . 7 . |

-------------------------

| 4 . . | . 8 . | . . 6 |

| . 7 . | 1 . 3 | . 9 . |

| . . 1 | . . . | 8 . . |

-------------------------

2、

0 0 8 0 0 0 2 0 0

0 3 0 8 0 2 0 3 0

7 0 0 0 0 9 0 0 5

0 5 0 0 0 0 0 1 0

0 0 4 0 0 0 6 0 0

0 2 0 0 0 0 0 7 0

4 0 0 0 8 0 0 0 6

0 7 0 1 0 3 0 9 0

0 0 1 0 0 0 8 0 0

使用方法很简单、首先要建立好一个txt文件 里面放入上面的格式、

然后就是执行SudokuSolver 的java application 的main方法、
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: