编程之美1.15构造数独-----回溯法java版

完全根据书上给的思路用java写了一下
假如程序进行到(1,7)时,可取的值只有一个list:4;在(1,7)的位置填上4,进行到(1,8),这是list=null,回溯到(1,7),list:4,进行到(1,8),list=null,回溯到(1,7).....
就会这样一直死循环下去,这时应当回溯到(1,6)再向下继续进行,添加了一个回溯次数标记位pro_num
(1,7) list:4 pro_num=0
<pre name="code" class="java">(1,8) list:null
(1,7) pro_num=1=list.size
(1,6) list:7,6 pro_num =1
 
(1,7) list:5,9 pro_num=0
(1,6) list:1,4
.........
其实这样做也不是完全严谨,假如在(1,6)又选中了使(1,7)list:4的值,则还要回溯到(1,6),这时(1,6)的pro_num=2=list.size,这样又会回溯到(1,5),但是这样最起码可以得到一个可行解
</pre><pre name="code" class="java">/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Test;

import java.util.*;

/**
 *
 * @author Administrator
 */
public class Sudoku {

    public static class Coord {

        public int x;
        public int y;

        Coord() {
            x = -1;
            y = -1;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

    }

    public static class Cell {

        public boolean isProcessed;
        public List validList;
        public int value;
        public int pro_num;

        Cell() {
            isProcessed = false;
            validList = null;
            value = -1;
            pro_num =0;
        }

        public void pickValidValue() {
            //获取随机数
            Random random = new Random();
            int result = random.nextInt(this.validList.size());
            this.value = (Integer) this.validList.get(result);
        }

        public void clear() {
            this.isProcessed = false;
            this.validList = null;
            this.value = -1;
        }

        public boolean getIsIsProcessed() {
            return isProcessed;
        }

        public void setIsProcessed(boolean isProcessed) {
            this.isProcessed = isProcessed;
        }

        public List getValidList() {
            return validList;
        }

        public void setValidList(List validList) {
            this.validList = validList;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public int getPro_num() {
            return pro_num;
        }

        public void setPro_num(int pro_num) {
            this.pro_num = pro_num;
        }
        
        

    }

    public static void main(String[] args) {
        Coord coCurrent = new Coord();
        coCurrent.setX(0);
        coCurrent.setY(0);
        int m_size = 9;
        Random random = new Random();
        Cell[][] m_cells = new Cell[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                m_cells[i][j] = new Cell();
            }
        }
        while (true) {
            System.out.println("x="+coCurrent.getX()+"y="+coCurrent.getY());
            Cell c = m_cells[coCurrent.getX()][coCurrent.getY()];
            System.out.println("c.getIsIsProcessed()="+c.getIsIsProcessed());
            List al;
            //如果该格子还未填值,获取可取的值
            if (!c.getIsIsProcessed()) {
                al = getValidValueList(coCurrent, m_cells);
                c.setValidList(al);
                System.out.println("list"+c.getValidList());
            }else{
                int pro_num =c.getPro_num()+1;
                System.out.println("回溯次数——"+pro_num);
                System.out.println("list"+c.getValidList());
                c.setPro_num(pro_num);                         
                
                if(pro_num == c.getValidList().size()){
                    c.setIsProcessed(false);
                    c.setValidList(null);
                    c.setValue(-1);
                    c.setPro_num(0);
                    coCurrent = prevCoord(coCurrent);
                    System.out.println("我要回溯到x="+coCurrent.getX()+"y="+coCurrent.getY());
                    continue;
                }
            }
            //如果有可选值
            if (c.getValidList() != null) {
                //c.pickValidValue();  //选一个填进去
                if (c.getValidList().size() > 1) {
                    int result = random.nextInt(c.getValidList().size());
                    c.setValue((Integer) c.getValidList().get(result));
                }else{
                    c.setValue((Integer) c.getValidList().get(0));
                }
                c.setIsProcessed(true);
                if (coCurrent.getX() == m_size - 1 && coCurrent.getY() == m_size - 1) {
                    break;
                } else {
                    coCurrent = nextCoord(coCurrent);
                }
            } else {//如果没有,回溯
                //如果当前是(0,0),结束while循环
                if (coCurrent.getX() == 0 && coCurrent.getY() == 0) {
                    break;
                } else {
                    c.setIsProcessed(false);
                    c.setValidList(null);
                    c.setValue(-1);
                    c.setPro_num(0);
                    coCurrent = prevCoord(coCurrent);
                    System.out.println("我要回溯到x="+coCurrent.getX()+"y="+coCurrent.getY());
                }
            }
        }

        for (int i = 0; i < m_size; i++) {
            for (int j = 0; j < m_size; j++) {
                if (j != 8) {
                    System.out.print(m_cells[i][j].getValue()+"    ");
                } else {
                    System.out.println(m_cells[i][j].getValue());
                }

            }
        }
    }

    //获取可行解
    private static List getValidValueList(Coord coCurrent, Cell[][] m_cells) {
        int x = coCurrent.getX();
        int y = coCurrent.getY();
        List list = new ArrayList();
        for (int i = 1; i < 10; i++) {
            boolean flag_x = true;
            boolean flag_y = true;
            boolean flag = true;
            int num = i;                  //如果这个地方放的值为num
            //判断同一行是否有相同的值
            for (int h = 0; h < 9; h++) {
                if (h != y && m_cells[x][h].getValue() == num) {
                    flag_y = false;
                }
            }
            //判断同一列是否有相同的值
            for (int l = 0; l < 9; l++) {
                if (l != x && m_cells[l][y].getValue() == num) {
                    flag_x = false;
                }
            }
            //判断同一个3*3的格内有没有重复的
            int n = 0;
            int m = 0;
            if (x % 3 == 0) {
                n = x;
            } else if (x % 3 == 1) {
                n = x - 1;
            } else {
                n = x - 2;
            }
            if (y % 3 == 0) {
                m = y;
            } else if (y % 3 == 1) {
                m = y - 1;
            } else {
                m = y - 2;
            }
            for (int nn = n; nn < n + 3; nn++) {
                for (int mm = m; mm < m + 3; mm++) {
                    if (nn != x && mm != y && m_cells[nn][mm].getValue() == num) {
                        flag = false;
                    }
                }
            }
            if (flag_x && flag_y && flag) {
                list.add(num);
            }
        }
        if(list.size()>0){
            return list;
        }else{
            return null;
        }
        

    }

    private static Coord prevCoord(Coord coCurrent) {
        int x = coCurrent.getX();
        int y = coCurrent.getY();
        if (y != 0) {
            y = y - 1;
        } else {
            y = 8;
            x = x - 1;
        }
        coCurrent.setX(x);
        coCurrent.setY(y);
        return coCurrent;
    }

    private static Coord nextCoord(Coord coCurrent) {
        int x = coCurrent.getX();
        int y = coCurrent.getY();
        if (y != 8) {
            y = y + 1;
        } else {
            y = 0;
            x = x + 1;
        }
        coCurrent.setX(x);
        coCurrent.setY(y);
        return coCurrent;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值