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,售后保障稳定

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 中国电子学会-青少年电子信息等级考试标准 (1-6 级)

    中国电子学会-青少年电子信息等级考试标准 (1-6 级)一级标准一、考试形式1.理论知识部分:上机考试2.实际操作部分:现场制作二、所用器件1.电子元器件——电源、电机、灯、导线、开关2.能够满足考试要求的结构件三、考核内容(一)理论知识了解人类发现电的历史 了解电的产生及用途 掌握基本电路的构成(电源、用电器、开关和导线),理解各部分的作用 理解串联电路的连接方式 了解家用照明电路组成方式 熟悉安全用电常识 掌握避免雷电伤害的生活常识 认…

  • CSS3透明属性opacity建议收藏

    例子:何问起效果查看效果:http://hovertree.com/hvtart/bjae/q3etb2qv.htm设置div元素的不透明级别:div{opacity:0.5;}opacity属

    2021年12月21日
  • EasyPlayer实现直播抓拍

    EasyPlayer实现直播抓拍对于一个裸的RTSPURL,存放在播放列表上略显单调与枯燥。大家可以看到EasyPlayer在播放完视频后会保存一帧图片到列表上。那么这个功能是如何做到的呢?如果自己实现解码的话,比如使用ffmpeg解码,这种情况下,将视频帧解码,再编码成jpeg保存下来,应该不是什么难事。相信大多数播放器都是这样处理的。H264格式的视频码流=>解码=>YUV格式的视频帧=>压缩=>jpeg=>保存到

  • awk工具详解

    awk工具详解目录awk概述awk工作原理awk命令格式awk概述AWK是一种处理文本文件的语言,是一个强大的文本分析工具。它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总

  • 服务器中”系统平均负载 Load average“含义学习

    服务器中”系统平均负载 Load average“含义学习文章目录一、什么是系统平均负载二、衡量系统性能三、行车过桥(引用)四、自我总结一、什么是系统平均负载  uptime、w、top等命令都会有系统负载loadaverage的输出,系统平均负载被定义为在特定时间间隔内运行队列中的平均进程数,包括可运行状态和不可中断状态的平均进程数,也就是活跃进程数。它和cpu使用率没有直接的关系二、衡量系统性能  如果系统平均负载的数值除以CPU的数目高于…

  • CANalyzer_InstallationQuickStartGuide[通俗易懂]

    CANalyzer_InstallationQuickStartGuide[通俗易懂]OverviewOperatingconceptIfyouarestartingupCANalyzerforthefirsttime,anditsfunctionalityandcontrolsarestillcompletelynewtoyou,thefollowingtourwillhelpyoutobecomefamiliar…

发表回复

您的电子邮箱地址不会被公开。

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