当前位置: 首页 > article >正文

Sudoku Problem Solver (数独游戏解谜器)

最近一直在研究一个小游戏,叫Sudoku(中文名叫“数独”),据说是欧拉他老人家发明的。

游戏是这样讲的,在一个9*9的棋盘上,放置1~9的数字,使得每一行,每一列,每一个3*3的小格子(一共九个)都要包含1~9.

游戏不是从一个空的棋盘开始的。初始棋局的不同使得问题的难度差别很大。

下面是一个参考的网站:

http://www.sudokufun.com/

http://www.sudoku.org.uk/

http://www.puzzle.jp/letsplay/play_sudoku-e.html

昨天心血来潮,用Java编写了一个Sudoku解密器,可以解决各种各样的Sudoku问题。程序的设计思想还是最简单的深度优先搜索,加上一点A算法的思路。

下面是主数据结构的源代码:

package sudoku;

/**
 * <p>Title: Sudoku Problem Solver</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author 郑杨凡
 * @version 1.0
 */
import java.util.HashSet;
import java.util.Iterator;

public class Sudoku {
        public static class SudokuSoluteException extends Exception {
                public SudokuSoluteException() {
                        super();
                }
        }
        private static class IndexPair{
                private int row;
                private int column;
                /**
                 * @return Returns the column.
                 */
                public int getColumn() {
                        return column;
                }
                /**
                 * @param column The column to set.
                 */
                public void setColumn(int column) {
                        this.column = column;
                }
                /**
                 * @return Returns the row.
                 */
                public int getRow() {
                        return row;
                }
                /**
                 * @param row The row to set.
                 */
                public void setRow(int row) {
                        this.row = row;
                }
        }
        private static class SmallestNeeded{
                public static final String ROW = "ROW";
                public static final String COLUMN = "COLUMN";
                public static final String BOX = "BOX";

                private String type = "ROW";
                private int index = -1;
                private int requiredCount = 10;

                /**
                 * @return Returns the requiredCount.
                 */
                public int getRequiredCount() {
                        return requiredCount;
                }
                /**
                 * @param requiredCount The requiredCount to set.
                 */
                public void setRequiredCount(int requiredCount) {
                        this.requiredCount = requiredCount;
                }
                /**
                 * @return Returns the index.
                 */
                public int getIndex() {
                        return index;
                }
                /**
                 * @param index The index to set.
                 */
                public void setIndex(int index) {
                        this.index = index;
                }
                /**
                 * @return Returns the type.
                 */
                public String getType() {
                        return type;
                }
                /**
                 * @param type The type to set.
                 */
                public void setType(String type) {
                        this.type = type;
                }
        }

        private static class SudokuState {
                private HashSet[] numsNeededInRow = new HashSet[9];
                private HashSet[] numsNeededInCol = new HashSet[9];
                private HashSet[] numsNeededInBox = new HashSet[9];

                public SudokuState(){
                        for(int i = 0; i < 9 ; i++){
                                numsNeededInRow[i] = new HashSet();
                                numsNeededInCol[i] = new HashSet();
                                numsNeededInBox[i] = new HashSet();
                                for(int j = 1; j <= 9; j++){
                                        Byte b = new Byte((byte) j);
                                        numsNeededInRow[i].add(b);
                                        numsNeededInCol[i].add(b);
                                        numsNeededInBox[i].add(b);
                                }
                        }
                }

                public void setNum(int row,int col,byte num)throws SudokuSoluteException{
                        Byte b = new Byte(num);
                        SudokuSoluteException e = new SudokuSoluteException();

                        if(numsNeededInRow[row].contains(b))
                                numsNeededInRow[row].remove(b);
                        else
                                throw e;

                        if(numsNeededInCol[col].contains(b)){
                                numsNeededInCol[col].remove(b);
                        }else{
                                numsNeededInRow[row].add(b);
                                throw e;
                        }

                        if(numsNeededInBox[row / 3 * 3 + col / 3].contains(b)){
                                numsNeededInBox[row / 3 * 3 + col / 3].remove(b);
                        }else{
                                numsNeededInRow[row].add(b);
                                numsNeededInCol[col].add(b);
                                throw e;
                        }
                }

                public void reSetNum(int row, int col, byte num) {
                        Byte b = new Byte(num);
                        numsNeededInRow[row].add(b);
                        numsNeededInCol[col].add(b);
                        numsNeededInBox[row / 3 * 3 + col / 3].add(b);
                }

                public byte[] getNeededNums(SmallestNeeded needed){
                        String type = needed.getType();
                        HashSet set = null;
                        if(type.equals(SmallestNeeded.ROW)){
                                set = numsNeededInRow[needed.getIndex()];
                        }else if(type.equals(SmallestNeeded.COLUMN)){
                                set = numsNeededInCol[needed.getIndex()];
                        }else{
                                set = numsNeededInBox[needed.getIndex()];
                        }
                        byte[] ret = new byte[set.size()];
                        int i = 0;
                        for(Iterator iter = set.iterator(); iter.hasNext();){
                                ret[i++] = ((Byte)iter.next()).byteValue();
                        }
                        return ret;
                }

                public SmallestNeeded getSmallestNeeded(){
                        SmallestNeeded needed = new SmallestNeeded();
                        for(int i = 0; i < 9; i++){
                                int required = numsNeededInRow[i].size();
                                if(required > 0 && needed.getRequiredCount() > required){
                                        needed.setRequiredCount(required);
                                        needed.setIndex(i);
                                        needed.setType(SmallestNeeded.ROW);
                                }

                                required = numsNeededInCol[i].size();
                                if(required > 0 && needed.getRequiredCount() > required){
                                        needed.setRequiredCount(required);
                                        needed.setIndex(i);
                                        needed.setType(SmallestNeeded.COLUMN);
                                }

                                required = numsNeededInBox[i].size();
                                if(required > 0 && needed.getRequiredCount() > required){
                                        needed.setRequiredCount(required);
                                        needed.setIndex(i);
                                        needed.setType(SmallestNeeded.BOX);
                                }
                        }
                        return needed;
                }
        }
        private byte[][] chessBoard = new byte[9][9];
        private SudokuState state = null;
        private void init(){
                for(int i = 0; i < 9; i++){
                        for(int j = 0;j < 9; j++){
                                chessBoard[i][j] = -1;
                        }
                }
                state = new SudokuState();
        }

        public Sudoku(){
                init();
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

        public Sudoku(byte[][] board) throws SudokuSoluteException{
                this();
                for(int i = 0; i < 9 ; i++){
                        for(int j = 0; j < 9; j++){
                                if(board[i][j] != -1){
                                        setNumber(i,j,board[i][j]);
                                }else{
                                        chessBoard[i][j] = -1;
                                }
                        }
                }
        }

        public void setNumber(int row,int col,byte num) throws SudokuSoluteException{
                byte originalNum = chessBoard[row][col];
                chessBoard[row][col] = num;
                try{
                        state.setNum(row,col,num);
                }catch(SudokuSoluteException ex){
                        chessBoard[row][col] = originalNum;
                        throw ex;
                }
        }

        public IndexPair getNextIndexPair(SmallestNeeded needed){
                IndexPair pair = new IndexPair();
                String type = needed.getType();
                if(type.equals(SmallestNeeded.ROW)){
                        int i = needed.getIndex();
                        for(int j = 0; j < 9; j++ ){
                                if(chessBoard[i][j] == -1){
                                        pair.setRow(i);
                                        pair.setColumn(j);
                                        break;
                                }
                        }
                }else if(type.equals(SmallestNeeded.COLUMN)){
                        int j = needed.getIndex();
                        for(int i = 0; i < 9; i++ ){
                                if(chessBoard[i][j] == -1){
                                        pair.setRow(i);
                                        pair.setColumn(j);
                                        break;
                                }
                        }
                }else{
                        // BOX
                        int k = needed.getIndex();

                        int startRow = k / 3 * 3;
                        int startCol = k % 3 * 3;

                        for(int i = startRow; i < startRow+3;i++){
                                for(int j = startCol; j < startCol + 3; j++){
                                        if(chessBoard[i][j] == -1){
                                                pair.setRow(i);
                                                pair.setColumn(j);
                                                return pair;
                                        }
                                }
                        }
                }
                return pair;
        }

        public byte  getNumAt(int i, int j){
            return chessBoard[i][j];
        }

        public boolean solve(){
                SmallestNeeded needed = state.getSmallestNeeded();
                if(needed.getRequiredCount() > 9){
                        // find the solution
                        return true;
                }
                IndexPair pair = getNextIndexPair(needed);
                byte[] needNums = state.getNeededNums(needed);

                for(int i = 0; i < needNums.length;i++){
                        byte b = needNums[i];
                        try{
                                setNumber(pair.getRow(),pair.getColumn(),b);
                                // System.out.println("SET " + (pair.getRow()+1) + "行," + (pair.getColumn()+1) + "列为" + b);
                                if(solve()){
                                        return true;
                                }
                                reSetNumber(pair.getRow(),pair.getColumn(),b);
                                // System.out.println("RESET " + (pair.getRow()+1) + "行," + (pair.getColumn()+1) + "列为" + b);
                        }catch(SudokuSoluteException ex){
                                continue;
                        }
                }
                return false;
        }

        public void reSetNumber(int row, int col, byte num) {
                chessBoard[row][col] = -1;
                state.reSetNum(row,col,num);
        }

        public void print(){
                for(int i = 0; i < 9 ; i++){
                        for(int j = 0 ; j < 9 ; j++){
                                if(chessBoard[i][j] != -1)
                                        System.out.print(chessBoard[i][j]);
                                System.out.print('/t');
                        }
                        System.out.println();
                }
        }


        /**
         * @param args
         * @throws SudokuSoluteException
         */
        public static void main(String[] args) throws SudokuSoluteException {
//  byte[][] board = {
//   {-1,5,-1,-1,-1,1,4,-1,-1},
//   {2,-1,3,-1,-1,-1,7,-1,-1},
//   {-1,7,-1,3,-1,-1,1,8,2},
//   {-1,-1,4,-1,5,-1,-1,-1,7},
//   {-1,-1,-1,1,-1,3,-1,-1,-1},
//   {8,-1,-1,-1,2,-1,6,-1,-1},
//   {1,8,5,-1,-1,6,-1,9,-1},
//   {-1,-1,2,-1,-1,-1,8,-1,3},
//   {-1,-1,6,4,-1,-1,-1,7,-1}
//  };

//  byte[][] board ={
//    {6,-1,-1,1,-1,-1,-1,5,-1},
//   {-1,4,-1,-1,-1,2,-1,-1,3},
//   {-1,-1,3,-1,5,-1,1,-1,-1},
//   {-1,1,-1,-1,-1,3,-1,-1,4},
//   {-1,-1,5,-1,6,-1,9,-1,-1},
//   {2,-1,-1,9,-1,-1,-1,1,-1},
//   {-1,-1,6,-1,8,-1,7,-1,-1},
//   {3,-1,-1,7,-1,-1,-1,6,-1},
//   {-1,2,-1,-1,-1,6,-1,-1,1}
//   };
                byte[][] board ={
                                {2,-1,-1,6,7,-1,-1,-1,-1},
                                {-1,-1,6,-1,-1,-1,2,-1,1},
                                {4,-1,-1,-1,-1,-1,8,-1,-1},
                                {5,-1,-1,-1,-1,9,3,-1,-1},
                                {-1,3,-1,-1,-1,-1,-1,5,-1},
                                {-1,-1,2,8,-1,-1,-1,-1,7},
                                {-1,-1,1,-1,-1,-1,-1,-1,4},
                                {7,-1,8,-1,-1,-1,6,-1,-1},
                                {-1,-1,-1,-1,5,3,-1,-1,8}
                };
                Sudoku ku = new Sudoku(board);
                if(ku.solve())
                        ku.print();
                else
                        System.out.println("No Solution");
        }

    private void jbInit() throws Exception {
    }

}

后来又为这个程序加了一个Swing的界面,可以作为一个小游戏或者解密器来玩了

传不上去图片和附件,需要的朋友请与我联系

hippozheng@tom.com

http://www.lryc.cn/news/2414737.html

相关文章:

  • 什么是腾讯云轻量应用服务器?2023年腾讯云轻量与云服务器对比区别有哪些?
  • 洗牌算法
  • 网站设计基础:简述各类有创意的导航方式
  • AutobahnPython: 功能强大的实时通信框架
  • 如何在 Linux下进行文件切割操作?
  • .net面试问答(大汇总)
  • 记一次配置华为路由器DDNS(花生壳)动态域名解析
  • awstats的安装和配置
  • C# System.NullReferenceException 异常与回调函数初始化
  • CSDN积分获取方法(转)
  • 101个微软提供的Visual Studio 2005示例
  • 谷歌浏览器GoogleChrome“无法访问此网站”问题解决
  • Video_player_for_3DS 开源项目教程
  • EventHandler(事件处理器)学习
  • VBA中 InputBox 函数
  • 论文速读之SUNet、MAXIM、Restormer、MIRNet、SwinIR、HINet、MPRNet、CSRNet
  • ARM Cortex M3 基础(学习笔记)
  • CopyFile 使用方法
  • 数据库系统原理
  • 【CTS测试】CTS测试环境搭建
  • C++图片保存,加载(LoadImage()),编辑,资源句柄(HBITMAP )的使用总结
  • Root你的设备
  • BBS论坛系统的设计与实现
  • linux的 lseek 函数
  • 【JAVA语言-第1话】初识java、环境搭建、入门程序
  • 作家生涯人物访谈报告知乎_即使您不认为自己是作家,写作也会如何改善您的职业生涯
  • 发现一款 xcel 数据筛选工具,开源项目,可以继续自己发挥
  • matlab 自定义函数及调用
  • error LNK2001: unresolved external symbol memset
  • 国产人工智能语言大模型相关网站