java数独解法[通俗易懂]

java数独解法[通俗易懂]玩了好久的数独,前几天突发奇想写一个解法,看了好多文章和源码,像回溯法和唯一解法,都不太理解其思路,于是就自己动手写了一个,效率还算可以,有优化的空间,但是懒得优化了。整体的解法思路就是列出每个空格的备选数,然后逐一尝试,可谓是最笨的解法了,分享给大家图个乐,还希望大佬看到了可以指点一下里面的不足之处。同样因为懒,就没做成web应用,一个main方法自己跑着玩了就。代码里面包含了1-5级的数独…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

玩了好久的数独,前几天突发奇想写一个解法,看了好多文章和源码,像回溯法和唯一解法,都不太理解其思路,于是就自己动手写了一个,效率还算可以,有优化的空间,但是懒得优化了。
整体的解法思路就是列出每个空格的备选数,然后逐一尝试,可谓是最笨的解法了,分享给大家图个乐,还希望大佬看到了可以指点一下里面的不足之处。同样因为懒,就没做成web应用,一个main方法自己跑着玩了就。
代码里面包含了1-5级的数独谜题例子(测试用的,就没删除),还有一个从控制台获取谜底的方法。
第一次发文章有些紧张啊,转载的话表明一下出处就行了,废话不多说,上代码

import java.util.*;


public class ShuDuKey { 
   
    static boolean done = false;
    public static void  main(String[] args) throws Exception { 
   
        Integer[][] maps1 = { 
   
                { 
   0,0,0,0,0,0,0,0,3},
                { 
   8,9,7,6,3,4,5,2,1},
                { 
   5,4,0,1,9,0,0,0,0},
                { 
   4,0,0,0,1,5,0,7,0},
                { 
   0,0,0,8,0,6,0,0,0},
                { 
   0,1,0,3,4,0,0,0,2},
                { 
   0,0,0,0,2,3,0,6,4},
                { 
   0,3,5,0,0,7,2,1,8},
                { 
   6,0,0,0,0,0,0,0,0}
        };
        Integer[][] maps2 = { 
   
                { 
   0,1,0,0,0,6,2,0,0},
                { 
   0,0,0,5,3,0,9,0,8},
                { 
   6,9,0,2,4,0,0,0,0},
                { 
   7,0,0,0,0,0,3,9,0},
                { 
   0,3,5,0,6,0,8,4,0},
                { 
   0,8,4,0,0,0,0,0,7},
                { 
   0,0,0,0,5,4,0,3,1},
                { 
   4,0,6,0,8,3,0,0,0},
                { 
   0,0,1,9,0,0,0,0,0}
        };
        Integer[][] maps3 = { 
   
                { 
   4,6,8,0,5,0,0,7,0},
                { 
   5,0,0,9,7,0,0,0,3},
                { 
   0,0,0,0,0,1,0,0,8},
                { 
   0,0,7,0,0,0,0,5,0},
                { 
   0,9,0,0,2,0,0,4,0},
                { 
   0,5,0,0,0,0,8,0,0},
                { 
   6,0,0,2,0,0,0,0,0},
                { 
   2,0,0,0,6,5,0,0,4},
                { 
   9,7,0,0,0,0,2,8,6}
        };
        Integer[][] maps4 = { 
   
                { 
   6,4,0,0,3,8,7,0,9},
                { 
   5,0,8,9,0,0,0,0,0},
                { 
   0,0,0,0,1,0,0,0,0},
                { 
   0,3,0,0,0,0,5,0,0},
                { 
   0,0,0,7,2,1,0,0,0},
                { 
   0,0,9,0,0,0,0,7,0},
                { 
   0,0,0,0,9,0,0,0,0},
                { 
   0,0,0,0,0,6,4,0,3},
                { 
   3,0,1,4,7,0,0,8,5}
        };
        Integer[][] maps5 = { 
   
                { 
   0,0,4,2,0,0,8,0,0},
                { 
   0,0,0,0,0,0,0,0,0},
                { 
   0,9,0,0,0,7,0,3,0},
                { 
   0,0,5,6,8,0,7,0,0},
                { 
   0,3,0,0,1,0,0,9,0},
                { 
   0,0,7,0,5,9,1,0,0},
                { 
   0,2,0,8,0,0,0,7,0},
                { 
   0,0,0,0,0,0,0,0,0},
                { 
   0,0,8,0,0,4,2,0,0}
        };
        Integer[][] mapsMax = { 
   
                { 
   0,0,5,3,0,0,0,0,0},
                { 
   8,0,0,0,0,0,0,2,0},
                { 
   0,7,0,0,1,0,5,0,0},
                { 
   4,0,0,0,0,5,3,0,0},
                { 
   0,1,0,0,7,0,0,0,6},
                { 
   0,0,3,2,0,0,0,8,0},
                { 
   0,6,0,5,0,0,0,0,9},
                { 
   0,0,4,0,0,0,0,3,0},
                { 
   0,0,0,0,0,9,7,0,0}
        };
        Integer[][] sMap = scanMap();
        doShuDu(sMap);
        //doShuDu(maps5);
    }

    //获得数独谜题
    private static Integer[][] scanMap() { 
   
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入数独谜题,数字以空格隔开,空白处数字以0代替");
        Integer[][] result = new Integer[9][9];
        for (int i = 0; i < result.length; i++) { 
   
            System.out.println("请输入第"+(i+1)+"行的数字:");
            String[] strArr;
            while (true) { 
   
                String str = sc.nextLine();
                if("exit".equals(str)){ 
   
                    System.exit(0);
                }
                strArr = str.split("\\s+|,|,");
                if(strArr.length != 9){ 
   
                    System.out.println("输入错误,请重新输入"+(i+1)+"行数字!");
                    continue;
                }
                break;
            }
            for (int j = 0; j < result[i].length; j++) { 
   
                result[i][j] = Integer.parseInt(strArr[j]);
            }
        }
        System.out.println("谜题输入完毕,正在解析中。。。");
        return result;
    }

    //解析数独谜题
    public static void doShuDu(Integer[][] maps){ 
   
        long start = System.currentTimeMillis();
        List<String>[][] first = doShuDu1(maps);
        if(done){ 
   
            printMap(first);
            System.out.println("共用时:"+(System.currentTimeMillis()-start));
            return;
        }
        System.out.println("执行第二步————————————————————————————————————————》》》");
        List<String>[][] second = doShuDu2(maps,first);
        if(done){ 
   
            printMap(second);
            System.out.println("共用时:"+(System.currentTimeMillis()-start));
            return;
        }
        System.out.println("执行第三步————————————————————————————————————————》》》");
    }

    //简单数独谜题解析
    private static List<String>[][] doShuDu1(Integer[][] maps){ 
   
        List<String>[][] result = new List[9][9];
        boolean flag = true;
        while(flag){ 
   
            done = true;
            flag = false;
            for (int i = 0; i < maps.length; i++) { 
   
                for (int j = 0; j < maps[i].length; j++) { 
   
                    if(maps[i][j] == 0){ 
   
                        result[i][j] = getNumList(i,j,maps);
                        if(result[i][j] == null){ 
   
                            return null;
                        }
                        if(result[i][j].size() == 1){ 
   
                            maps[i][j] = Integer.parseInt(result[i][j].get(0));
                            flag = true;
                        }
                        done = false;
                    }else{ 
   
                        if(result[i][j] == null){ 
   
                            result[i][j] = new ArrayList<>();
                            result[i][j].add(maps[i][j].toString());
                        }
                    }
                }
            }
        }
        return result;
    }

    //复杂数独谜题解析
    private static List<String>[][] doShuDu2(Integer[][] maps, List<String>[][] first) { 
   
        Map<String,List<String>[][]> resultMap = new HashMap<>();
        Integer[][] tempMaps = arrayCopy(maps);
        List<String>[][] result = new List[first.length][];
        for (int i = 0; i < first.length; i++) { 
   
            result[i] = first[i].clone();
        }
        int[][] count = new int[9][9];
        boolean flag = true;
        while(flag){ 
   
            flag = false;
            i:for (int i = 0; i < first.length; i++) { 
   
                for (int j = 0; j < first[i].length; j++) { 
   
                    if(result[i][j].size() > 1){ 
   
                        boolean re = true;
                        while(re){ 
   
                            re = false;
                            //无法生成符合要求的二维数组,换数字重新来过
                            if(count[i][j] < result[i][j].size()){ 
   
                                tempMaps[i][j] = Integer.parseInt(result[i][j].get(count[i][j]++));
                                Integer[][] iarr = arrayCopy(tempMaps);
                                List<String>[][] ls = doShuDu1(iarr);
                                if(ls != null) { 
   
                                    resultMap.put(i+","+j,result);
                                    result = ls;
                                }else{ 
   
                                    re = true;
                                }
                            }else { 
   
                                //该位置的数组应用完毕,仍未得到可用解,则置零
                                count[i][j] = 0;
                                //找到上一个选择的数字的位置
                                for (int k = 0; k < count.length; k++) { 
   
                                    for (int l = 0; l < count[k].length; l++) { 
   
                                        if(count[k][l] > 0){ 
   
                                            i = k;
                                            j = l;
                                        }
                                    }
                                }
                                result = resultMap.get(i+","+j);
                                for (int k = i; k < 9; k++) { 
   
                                    for (int l = 0; l < 9; l++) { 
   
                                        if(k == i && l == 0){ 
   
                                            l = j;
                                        }
                                        tempMaps[k][l] = maps[k][l];
                                    }
                                }
                                j--;
                                break;
                            }

                        }
                        flag = true;
                    }else{ 
   
                        tempMaps[i][j] = Integer.parseInt(result[i][j].get(0));
                    }
                }
            }
        }
        return result;
    }

    //获取该位置的候选数字
    private static List<String> getNumList(int i, int j, Integer[][] maps) { 
   
        List<String> temp = getList();
        for (int jj = 0; jj < maps[i].length; jj++) { 
   
            //移除当前同行已经出现的数字
            temp.remove(maps[i][jj]+"");
        }
        for (int ii = 0; ii < maps.length; ii++) { 
   
            //移除当前同列已经出现的数字
            temp.remove(maps[ii][j]+"");
        }
        //移除九宫格已经确定的数字
        int d = i/3*3;
        int h = j/3*3;
        for (int k = d; k < d+3; k++) { 
   
            for (int l = h; l < h+3; l++) { 
   
                temp.remove(maps[k][l]+"");
            }
        }
        if(temp.size() > 0){ 
   
            return temp;
        }
        return null;
    }

    //获取1-9的集合
    private static List<String> getList(){ 
   
        List<String> result = new ArrayList<>();
        for (int i = 1; i < 10; i++) { 
   
            result.add(i+"");
        }
        return result;
    }

    //复制二维数组
    private static Integer[][] arrayCopy(Integer[][] oo){ 
   
        Integer[][] result = new Integer[oo.length][];
        for (int i = 0; i < oo.length; i++) { 
   
            result[i] = oo[i].clone();
        }
        return result;
    }

    //打印二维数组
    public static void printMap(Object[][] map){ 
   
        for (int i = 0; i < 9; i++) { 
   
            if(i%3==0 && i!=0){ 
   
                System.out.println("---------------------");
            }
            for (int j = 0; j < 9; j++) { 
   
                if (j==8) { 
   
                    System.out.println(map[i][j]);
                } else if(j == 2 || j == 5) { 
   
                    System.out.print(map[i][j]+" | ");
                }else{ 
   
                    System.out.print(map[i][j]+" ");
                }
            }
        }
    }

}

Jetbrains全家桶1年46,售后保障稳定

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200731.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JAVA中反射机制六(java.lang.reflect包)

    JAVA中反射机制六(java.lang.reflect包)一、简介java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口。反射API允许对程序访问有关加载类的字段,方法和构造函数的信息进行编程访问。它允许在安全限制内使用反射的字段,

    2022年7月3日
    27
  • Kali网络渗透–UDP攻击–Hping3[通俗易懂]

    Kali网络渗透–UDP攻击–Hping3[通俗易懂]使用系统:Kalilinux2019.4使用渗透工具:Hping3打开系统终端在终端输一下命令hping3-c1000-d120-S-w64-p80–flood–rand-sourcecsdn.

    2022年10月2日
    1
  • QQFishing QQ钓鱼站点搭建

    QQFishing QQ钓鱼站点搭建答:为什么要写这个代码?当然不是做黑产去盗别人扣扣,也没有啥查看别人隐私信息的癖好,搭建该站点的适用对象为->使用社会工程学定向钓鱼攻击的安全渗透人员另外管理员界面后端写的很丑+很烂,除了我

    2022年7月2日
    33
  • kalman滤波融合原理及其matlab仿真「建议收藏」

    kalman滤波融合原理及其matlab仿真「建议收藏」1、kalman原理卡尔曼滤波是一种递推式滤波方法,不须保存过去的历史信息,新数据结合前一刻已求得的估计值及系统本身的状态方程按一定方式求得新的估计值。1.1、线性卡尔曼假设线性系统状态是k,卡尔曼原理可用以下五个公式表达:X(k|k-1)=AX(k-1|k-1)+BU(k)………..(1)P(k|k-1)=AP(k-1|k-1)A’+Q…………

    2022年5月28日
    48
  • Python处理Excel数据-pandas篇

    Python处理Excel数据-pandas篇Python处理Excel数据-pandas篇非常适用于大量数据的拼接、清洗、筛选及分析在计算机编程中,pandas是Python编程语言的用于数据操纵和分析的软件库。特别是,它提供操纵数值表格和时间序列的数据结构和运算操作。它的名字衍生自术语“面板数据”(paneldata),这是计量经济学的数据集术语,它们包括了对同一个体的在多个时期上的观测。它的名字是短语“Pythondataanalysis”自身的文字游戏。目录Python处理Excel数据-pandas篇一、安装环境1、打开以下文

    2025年7月1日
    4
  • ParameterizedThreadStart与ThreadStart的区别[通俗易懂]

    ParameterizedThreadStart与ThreadStart的区别[通俗易懂]classProgram  {    //publicstaticvoidCalculate()    //{    //  doubleDiameter=0.5;    //  Console.Write(“TheAreaOfCirclewithaDiameterof{0}is{1}”,Diame

    2022年7月15日
    15

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号