数独求解

数独求解

最近几个哥们抱着数独这本书玩起来了,时常拿着数独书上的题目问我,明知道我没玩过数独,还来问我,更为可恨的是,他们问我的是他们已经做出来的,那还问我干嘛,明摆虐我。所以,决心研究一下数独算法,打击一下他们的气焰。

这里写图片描述

进入正题,下面具体介绍一下数独算法

  • 将数独转化为一个二维矩阵,没填数字的地方值为0

  • 再设计check函数,判断一个数num填到x行y列是否满足数独要求,重点是判断在一个九宫格中是否满足要求,重点代码块如下

// 检查x行y列所在九宫格是否含有数字num
        // x/3 * 3, y/3 * 3即可算得x, y所在九宫格开头的数字
        for (int i = x / 3 * 3; i <= x / 3 * 3 + 2; i++)
            for (int j = y / 3 * 3; j <= y / 3 * 3 + 2; j++) {
                if (arr[i][j] == num) {
                    return false;
                }
            }
  • 最后采用递归,从左到右,依次填入合适数字,

            for (int i = 1; i <= 9; i++) {
                if (check(x, y, i, arr)) {
                    arr[x][y] = i;
                    solveSudoku(x, y + 1, arr);
                    //必须还原
                    arr[x][y] = 0;
                }
            }

一行填完便是列数达到9(列数范围是0-8)就要换另外一行,填完介绍标志便是行数达到9(行数范围是0-8),

具体代码如下

public class TestSudoku {

    public static void main(String[] args) {
        int[][] arr = { 
                { 8, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, 
                { 0, 7, 0, 0, 9, 0, 2, 0, 0 },
                { 0, 5, 0, 0, 0, 7, 0, 0, 0 }, 
                { 0, 0, 0, 0, 4, 5, 7, 0, 0 },
                { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, 
                { 0, 0, 1, 0, 0, 0, 0, 6, 0 },
                { 0, 0, 8, 5, 0, 0, 0, 1, 0 }, 
                { 0, 9, 0, 0, 0, 0, 4, 0, 0 } 
                };

        TestSudoku t = new TestSudoku();
        t.solveSudoku(0, 0, arr);

    }

    /**
     * 检查x行,y列是否可以填入数字num
     * 
     * @param x
     *            代表第x行
     * @param y
     *            代表第y列
     * @param num
     *            填入x行y列的数字
     * @param arr
     *            用来存储数独元素的二维数组
     */
    public boolean check(int x, int y, int num, int[][] arr) {
        // 检查x行是否存在数字num
        for (int j = 0; j < 9; j++) {
            if (arr[x][j] == num) {
                return false;
            }
        }

        // 检查y列是否存在数字num
        for (int i = 0; i < 9; i++) {
            if (arr[i][y] == num) {
                return false;
            }
        }

        // 检查x行y列所在九宫格是否含有数字num
        // x/3 * 3, y/3 * 3即可算得x, y所在九宫格开头的数字
        for (int i = x / 3 * 3; i <= x / 3 * 3 + 2; i++)
            for (int j = y / 3 * 3; j <= y / 3 * 3 + 2; j++) {
                if (arr[i][j] == num) {
                    return false;
                }
            }

        return true;

    }

    /**
     * 求解数独, 求解大致过程为按行填上合适数字,当一行填满后,再从另外一行开始填,最后一行填完即止
     * 
     * @param x
     *            x行
     * @param y
     *            y列
     * @param arr
     *            待求解数独数组
     */
    public void solveSudoku(int x, int y, int[][] arr) {
        int oldX, oldY;
        oldX = x; oldY = y;
        //此时求解结束
        if (x >= 9) {
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    System.out.print(arr[i][j]);
                }
                System.out.println();
            }
            System.exit(0);
        }

        //一行填完,再重下行开始填
        if (y >= 9) {
            solveSudoku(x + 1, 0, arr);
        }

        //当值为0时,表示此处未填,从1-9数字中选出合适填取
        else if (arr[x][y] == 0) {

            for (int i = 1; i <= 9; i++) {
                //检查填入数字后,是否满足数独要求
                if (check(x, y, i, arr)) {
                    arr[x][y] = i;
                    solveSudoku(x, y + 1, arr);
                    //必须还原
                    arr[x][y] = 0;
                }
            }
        //如果已经填了,向右移一个填上数字
        } else {

            solveSudoku(x, y + 1, arr);
        }



    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值