使用java程序帮你解数独
2012-09-24 17:12
218 查看
相信数独大家都多少有玩过吧?就是一个3x3 的9个块、每块里面又是3x3的小块
使每行每列都填充1-9的数字且只能使用一次、一般期刊后面都会有数独小游戏的、
以前也玩过数独、但是太难的就不知道该怎么解了、
今天逛了外国网站、发现一解数独的小程序、偷拿来分享、
只使用了两个类 SudokuSolver 和 Grid 、
先贴源码:
SudokuSolver
和 Grid
自己建立个文件自己定义好路径
贴上你要解的数独格式、(格式应该有很多种、我只知道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方法、
使每行每列都填充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方法、
相关文章推荐
- 使用Java程序片段动态生成表格
- Java中使用Runtime和Process类运行外部程序
- 使用JAVA程序操作FTP服务器
- 使用代码块和JAVA程序来接收游标返回数据集合
- 使用java理解程序逻辑第四章
- 使用JSmooth将java程序转换成windows上的.exe文件(彻底解决相对目录问题)
- 使用Fiddler捕获Java程序中的HTTP请求
- 使用JPype实现Python调用JAVA程序
- JAVA使用jar命令制作可执行GUI程序
- 使用Java程序从数据库中查询大量的数据时出现异常:java.lang.OutOfMemoryError: Java heap space
- java程序通过密钥方式使用JSch API访问SSH(转帖)
- 在Java中,如何把一个程序的结果需要保存起来,供下一个程序使用的方式
- Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能
- 如何使用Java读取串口的程序
- 使用Java语言编写程序最容易犯的21种错误
- 使用JSmooth将java程序转换成windows上的.exe文件(彻底解决相对目录问题)
- 使用命令行编译和运行java程序
- 关于java程序实现自动选人系统 使用I/O流完成
- 使用eclipse创建java程序可执行jar包