补全数独

这是一个可以根据现有数独的一部分,然后将整个数独补全的程序。大概思路就是采用回溯算法,然后每个点对每个数进行尝试,如果可以,那么继续向前尝试,如果当前格子放入1-9 的所有数字都不行,那么说明前一个,或者几个都放错了,然后回溯到之前,即退回到上一个格子的情况,进行重新尝试,如果失败,那么继续这个过程。直到数独被填满。以下是代码。

package com.anzhuo.util.sd;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class ShuduB {

    /**
     * 校驗是否成功
     * @param targetArray
     * @return
     */
    private static boolean checkStatus(int[][] targetArray) {
        boolean flag = true;
        w:
        for (int i = 0; i < 9; i++) {
            List<Integer> col = new ArrayList<>();
            for (int k = 0; k < 9; k++) {
                if (targetArray[k][i] != 0 && col.indexOf(targetArray[k][i]) != -1) {
                    flag = false;
                    break w;
                }
                col.add(targetArray[k][i]);
            }
            List<Integer> hang = new ArrayList<>();
            for (int j = 0; j < 9; j++) {
                if (targetArray[i][j] != 0 && hang.indexOf(targetArray[i][j]) != -1) {
                    flag = false;
                    break w;
                }
                hang.add(targetArray[i][j]);


            }

            for (int x = 0; x < 9; x++) {
                List<Integer> block = new ArrayList<>();
                int i1 = i / 3;
                int j2 = x / 3;
                int i3 = i1 * 3;
                int j3 = j2 * 3;

                judge:
                for (int v = 0; v < 3; v++) {
                    int currentX = i3 + v;
                    for (int t = 0; t < 3; t++) {
                        int startY = j3 + t;
                        if(currentX == i && startY== x){
                            continue ;
                        }
                        if (targetArray[i][x] != 0 && block.indexOf(targetArray[i][x]) != -1) {
                            flag = false;
                            break w;
                        }
                        block.add(targetArray[currentX][startY]);
                    }
                }
            }
        }
        return flag;

    }






    private static void getShudu(int [][] array){

        putOneNum(array,null,new Stack<SdPoint>());

    }



    private static SdPoint getFreeBlock(int [][] array){
        for(int i = 0;i<9;i++){
            for(int j =0 ;j<9;j++){

                if(array[i][j]  == 0){

                    SdPoint sdPoint = new SdPoint();
                    sdPoint.setX(i);
                    sdPoint.setY(j);
                    return sdPoint ;

                }
            }
        }
        return null ;
    }


    private static void putOneNum(int [][] array, SdPoint lastPoint, Stack<SdPoint> stack){


        System.out.println("当前填充了"+stack.size());


        boolean flag = true ;
        SdPoint freeBlock = getFreeBlock(array);
        if( freeBlock == null){
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    System.out.print(array[i][j] + ",");
                }
                System.out.println("");
            }
            return;
        }else{
        // 格子需要装填
            if(lastPoint != null){

//                if(stack.size() == 0){
//
//
//                    System.out.println("sssssss");
//                    System.out.println(lastPoint.getValue());
//                }

                for(int x =1 ;x<10 ;x++){
                    if(x <= lastPoint.getValue()){
                        continue;
                    }
                    array[freeBlock.getX()][freeBlock.getY()] = x ;
                    if(checkStatus(array)){
                        freeBlock.setValue(x);
                        stack.push(freeBlock);
                        putOneNum(array,null,stack);
                        flag = false ;
                        break;
                    }
                }
                if(flag){
                    array[freeBlock.getX()][freeBlock.getY()] = 0 ;
                    SdPoint pop = stack.pop();
                    array[pop.getX()][pop.getY()] = 0 ;
                    putOneNum(array,pop,stack);
                }

            }else {
                for(int x =1 ;x<10 ;x++){
                    array[freeBlock.getX()][freeBlock.getY()] = x ;
                    if(checkStatus(array)){
                        freeBlock.setValue(x);
                        stack.push(freeBlock);
                        putOneNum(array,null,stack);
                        flag = false ;
                        break;
                    }
                }
                if(flag){
                    array[freeBlock.getX()][freeBlock.getY()] = 0 ;
                    // 回退
                    SdPoint pop = stack.pop();
                    array[pop.getX()][pop.getY()] = 0 ;
                    putOneNum(array,pop,stack);
                }

            }




        }


    }


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

        getShudu(integers);

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值