资讯专栏INFORMATION COLUMN

[Java] 数独生成和求解

skinner / 2726人阅读

摘要:首先在二维数组第一行随机填充个数字,然后将这个数字随机分布到整个二维数组中,然后使用求解数独的算法对此时的数组进行求解,得到一个完整的数独,然后按照用户输入的提示数量进行随机挖洞,得到最终的数独题目。

思路 1.生成数独

数独的生成总体思路是挖洞法。
首先在二维数组第一行随机填充1-9 9个数字,然后将这9个数字随机分布到整个二维数组中,然后使用求解数独的算法对此时的数组进行求解,得到一个完整的数独,然后按照用户输入的提示数量进行随机挖洞,得到最终的数独题目。
这种方法理论上可以随机生成(81!/72! = 9.5e+16)种不同的数独题目,足够人类玩上几百年了。

2.求解数独

求解数独使用的是计算机最擅长的暴力搜索中的回溯法。并结合人求解数独的思维过程增加了一点改进。
在每一层搜索中,首先计算每个格子可以填充的值的个数(我命名为不确定度),如果有格子不确定度为1,则直接填上数字就好,否则对不确定度最小的格子使用可能的数字逐个填充,并进入下一次递归。如果发现不确定度为0的格子,做说明之前的过程有问题,需要进行回溯。

代码
package sudo;

import java.util.Scanner;
/**
 * @description 数独生成和求解
 * @limit 支持从1-80的数字提示数量
 * @method 深度优先搜索/回溯法
 * @author chnmagnus
 */
public class Sudo {
    
    private int[][] data = new int[9][9]; //muti_array
    private int lef; //the number of zero in array
    private int tip; //the number of nozero_digit in array
    
    /**
     * 构造函数
     * 初始化变量
     */
    public Sudo(){
        lef = 0;
        for(int i=0;i<9;++i){
            for(int j=0;j<9;++j){
                data[i][j] = 0;
            }
        }
    }
    /**
     * 生成数独
     * 方法:挖洞法
     */
    public void genSudo(){
        System.out.println("Please input the number of digits provided:");
        Scanner scan = new Scanner(System.in);
        tip = scan.nextInt();
        scan.close();
        /*将1-9 9个数字放在二维数组中随机位置*/
        lef = 81 - 9; 
        for(int i=0;i<9;++i){
            data[0][i] = i+1;
        }
        for(int i=0;i<9;++i){
            int ta = (int)(Math.random()*10)%9;
            int tb = (int)(Math.random()*10)%9;
            int tem = data[0][ta];
            data[0][ta] = data[0][tb];
            data[0][tb] = tem;
        }
        for(int i=0;i<9;++i){
            int ta = (int)(Math.random()*10)%9;
            int tb = (int)(Math.random()*10)%9;
            int tem = data[0][i];
            data[0][i] = data[ta][tb];
            data[ta][tb] = tem;
        }
        /*通过9个数字求出一个可行解*/
        solveSudo();
        lef = 81 - tip;
        for(int i=0;i0)
                    System.out.print(data[i][j]+" ");
                else
                    System.out.print("* ");
            }
            System.out.print("
");
        }
        System.out.println("-----------------");
    }
    /**
     * 计算某格子的可填数字个数,即不确定度
     * @param r
     * @param c
     * @param mark
     * @return 不确定度
     */
    private int calcount(int r,int c,int[] mark){
        for(int ti=0;ti<10;++ti) 
            mark[ti] = 0;
        for(int i=0;i<9;++i){
            mark[data[i][c]] = 1;
            mark[data[r][i]] = 1;
        }
        int rs = (r/3)*3;
        int cs = (c/3)*3;
        for(int i=0;i<3;++i){
            for(int j=0;j<3;++j){
                mark[data[rs+i][cs+j]] = 1;
            }
        }
        int count = 0;
        for(int i=1;i<=9;++i){
            if(mark[i]==0)
                count++;
        }
        return count;
    }
    /**
     * 供solve调用的深度优先搜索
     * @return 是否有解的boolean标识
     */
    private boolean dfs(){
        if(lef==0) return true;
        int mincount = 10;
        int mini = 0,minj = 0;
        int[] mark = new int[10];
        /*找到不确定度最小的格子*/
        for(int i=0;i<9;++i){
            for(int j=0;j<9;++j){
                if(data[i][j]!=0) continue;
                
                int count = calcount(i,j,mark);
                if(count==0) return false;
                if(count
演示

以下四幅图分别是输出为0,20,60的程序运行结果。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65647.html

相关文章

  • 数独X--Android openCV识别数独并自动求解填充APP开发过程

    摘要:可以针对笔者常用的数独本文的实现都基于该,实现数独的识别求解并把答案自动填入。专家级别的平均秒完成求解包括图像数字提取,识别过程,完成全部操作。步骤四数独求解,生成答案,并生成需要填充的数字序列。 1 序   数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3...

    yvonne 评论0 收藏0
  • 数独求解javascript实现)

    摘要:数独技巧直观法候选数法相关二十格一个数字只与其所在行列及小九宫格的二十格相关我的思路精心设计了有效性判定函数,最多一次遍历个小单元格就能做出方案的有效性判定。 看《算法的乐趣》,试着用非递归穷举来解数独,看效率如何! 数独规则 数独游戏,经典的为9×9=81个单元格组成的九宫格,同时也形成了3×3=9个小九宫格,要求在81个小单元格中填入数字1~9,并且数字在每行每列及每个小九宫格中都...

    Berwin 评论0 收藏0
  • 《AI之矛》(1)【数独Agent】

    摘要:而此处针对进一步的搜索,有两个问题需要考虑如何选取搜索起点方格确定哪种搜索策略深度优先搜索,广度优先搜索关于第一个问题,无论选择哪个方格起始搜索,对于能否解决问题来说并不存在差异。 Github仓库地址 学习是为了寻找解决问题的答案,若脱离了问题只为知晓而进行的打call,那么随时间流逝所沉淀下来的,估计就只有重在参与的虚幻存在感了,自学的人就更应善于发现可供解决的问题。为了入门AI,...

    CatalpaFlat 评论0 收藏0
  • 用vue开发一个所谓的数独

    摘要:前言最近的后台管理系统页面,功能暂时没有新的需求,就在想首页放什么东西,最近我想到的就是放个所谓的数独,为什么是所谓的数独,因为规则不同于标准的数独,只要求每一行每一列数字不一样就可以了这个实例也是基于的,代码分享给大家。 1.前言 最近的后台管理系统页面,功能暂时没有新的需求,就在想首页放什么东西,最近我想到的就是放个所谓的数独,为什么是所谓的数独,因为规则不同于标准的数独,只要求每...

    shixinzhang 评论0 收藏0

发表评论

0条评论

skinner

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<