数独求解的java实现

用穷举法来求解数独问题。大概思路就是:
1、先挑出以及存在的数字,不作处理。
2、未知数从上到下,从左到右开始枚举,假如第一个数字是[0][0],先假设是1,判断它所在行是否有重复,再判断它所在的列是否有重复,最后判断它所在的9宫格是否有重复。要是都没有重复,就到下一个未知数。如果有重复,就自增。
3、要是自增到10,说明之前的数字有误,就回溯到上一个未知数。
4、要是一行的第一个数字自增到10,就回溯到上一行的最后一个数字。
ps.这种做法感觉好弱智,一些高大上的算法又看不懂。。。

package com.zttech.demo.sudoku;

import static org.hamcrest.CoreMatchers.instanceOf;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

import com.zttech.demo.excel.ExcelOperate;

/**
 * 数据求解
 * @author guoqicheng
 * @date 2018年4月20日
 */
public class Sudoku {

    @Test
    public void test() throws IOException {
        String filePath = "E:\\项目相关\\demo\\sudoku.xlsx";

        boolean isExcel2003 = true;  

        if (ExcelOperate.isExcel2007(filePath)) {  
            isExcel2003 = false;  
        }  

        File file = new File(filePath);

        String[][] result = ExcelOperate.getData(file, 0, isExcel2003);
        int rowLength = result.length;
        for (int i = 0; i < rowLength; i++) {
            for (int j = 0; j < result[i].length; j++) {
                System.out.print(result[i][j] + "|");
            }
            System.out.println("\t\t");
        }

        /** 把从excel读取出来的二维数组转换成int形式的二维数据,未知数用0来表示 */
        int[][] arrays = new int[9][9];
        for (int i = 0; i < 9; i ++) {
            for (int j = 0; j < 9; j++) {
                if (result[i][j] == null || "".equals(result[i][j])) {
                    arrays[i][j] = 0;
                } else {
                    arrays[i][j] = Integer.parseInt(result[i][j]);
                }
            }
        }


        System.out.println("-----------------------------------------------");
        arrays = calculate(arrays);
        for (int i = 0; i < arrays.length; i++) {
            for (int j = 0; j < arrays[i].length; j++) {
                System.out.print(arrays[i][j] + "|");
            }
            System.out.println("\t\t");
        }
        System.out.println("success");
    }

    /**
     * 求解过程
     * @param arrays
     * @return
     */
    public static int[][] calculate(int[][] arrays) {
        int count = 0; //步数
        //获取已经存在的数字位置
        int[][] indexs = getIndex(arrays);
        for (int i = 0; i < 9; i ++) {
            for (int j = 0; j < 9; j ++) { //遍历整个数组
                if (indexs[i][j] != -1) { //如果是未知数

                    //判断
                    do {
                        arrays[i][j] ++;
                        count++;
                    } while (!(compareRow(arrays, i, j) && compareCol(arrays, i, j) && compareLattice(arrays, i, j)));
                    if (arrays[i][j] > 9) {
                        if (indexs[i][j] != -1) {
                            arrays[i][j] = 0;
                            while (j != 0 && indexs[i][j-1] == -1) {
                                j = j - 1;
                            }
                        }
                        j = j - 2; //回退一步
                    }
                } else {
                    continue;
                }
                if (j < -1) {
                    i = i - 1;
                    j = 8;
                    while (indexs[i][j] == -1) {
                        j =  j - 1;
                    }
                    j --;
                }
            }
        }
        System.out.println(count);
        return arrays;
    }

    /**
     * 比较是否和这一行的数字重复
     * @param arrays 数组
     * @param row 所在的行
     * @param col 所在的列
     * @return false有重复,true没重复
     */
    public static boolean compareRow(int[][] arrays, int row, int col) {
        for (int i = col + 1; i < 9; i ++) {
            if (arrays[row][col] == arrays[row][i]) {
                return false;
            }
        }
        for (int i = col - 1; i >= 0; i --) {
            if (arrays[row][col] == arrays[row][i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较是否和这一列的数字重复
     * @param arrays 数组
     * @param row 所在的行
     * @param col 所在的列
     * @return false有重复,true没重复
     */
    public static boolean compareCol(int[][] arrays, int row, int col) {
        for (int i = row + 1; i < 9; i ++) {
            if (arrays[row][col] == arrays[i][col]) {
                return false;
            }
        }
        for (int i = row - 1; i >= 0; i --) {
            if (arrays[row][col] == arrays[i][col]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较是否和九宫格里面的数字重复
     * @param arrays 数组
     * @param row 所在的行
     * @param col 所在的列
     * @return false有重复,true没重复
     */
    public static boolean compareLattice(int[][] arrays, int row, int col) {
        int temp = 0;
        for (int k = 0; k <= 8; k += 3) {
            for (int l = 0; l <= 8; l += 3) {
                if (row >= k && row <= k + 2 && col >= l && col <= l + 2) {
                    for (int i = k; i <= k + 2; i ++) {
                        for (int j = l; j <= l + 2; j ++) {
                            if (arrays[row][col] == arrays[i][j]) {
                                temp ++; //只能有一次重复(和自己)
                            }
                        }
                    }
                }
            }
        }

        if (temp == 1) {
            return true;
        }else {
            return false;
        }
    }

    /**
     * 获取以及存在数字的位置
     * @param arrays
     * @return 如果哪位位置上的值是-1,就代表他是原才存在的
     */
    public static int[][] getIndex(int[][] arrays) {
        int[][] temp = new int[9][9];
        for (int i = 0; i < 9; i ++) {
            for (int j = 0; j < 9; j ++) {
                if (arrays[i][j] != 0) {
                    temp[i][j] = -1;
                }
            }
        }
        return temp;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值