Rust 数独计算

struct Sudoku {
    context: Vec<Vec<u8>>,//数独表格 按行列
    empty_count:usize,//空白个数
    col_step:usize,//列步长 9*9 是3
    row_step:usize,//行步长 9*9 是3
    row_num:usize, //行数
    col_num:usize, //列数
}
impl Sudoku {
    // add code here
    pub fn new4()->Sudoku {
        let mut context=Vec::new();
        let l1=vec![0,4,0,0];
        let l2=vec![0,0,0,1];
        let l3=vec![0,0,3,0];
        let l4=vec![2,0,0,0];
        context.push(l1);
        context.push(l2);
        context.push(l3);
        context.push(l4);
        let mut empty_count=0usize;
        for line in &context {
            for item in line  {
                if 0==*item{
                    empty_count+=1;
                }
            }
        }  
        Sudoku{
            context:context,
            empty_count: empty_count,
            col_step:2,
            row_step:2,
            row_num:4,
            col_num:4,
        }

    }
    pub fn new6()->Sudoku {

        let mut context=Vec::new();
        let l1=vec![0,0,1,5,4,0];
        let l2=vec![4,0,2,0,0,3];
        let l3=vec![0,0,0,2,0,4];
        let l4=vec![0,0,0,0,0,0];
        let l5=vec![0,0,0,0,5,6];
        let l6=vec![5,0,4,0,0,0];
        context.push(l1);
        context.push(l2);
        context.push(l3);
        context.push(l4);
        context.push(l5);
        context.push(l6);
        let mut empty_count=0usize;
        for line in &context {
            for item in line  {
                if 0==*item{
                    empty_count+=1;
                }
            }
        }  
        Sudoku{
            context:context,
            empty_count: empty_count,
            col_step:3,
            row_step:2,
            row_num:6,
            col_num:6,
        }

    }
    pub fn new9()->Sudoku {

        let mut context=Vec::new();
        // let l1=vec![0,5,0,0,0,0,0,2,0];
        // let l2=vec![4,0,0,2,0,6,0,0,7];
        // let l3=vec![0,0,8,0,3,0,1,0,0];
        // let l4=vec![0,1,0,0,0,0,0,6,0];
        // let l5=vec![0,0,9,0,0,0,5,0,0];
        // let l6=vec![0,7,0,0,0,0,0,9,0];
        // let l7=vec![0,0,5,0,8,0,3,0,0];
        // let l8=vec![7,0,0,9,0,1,0,0,4];
        // let l9=vec![0,2,0,0,0,0,0,7,0];

        // let l1=vec![0,1,0,0,9,0,6,0,0];
        // let l2=vec![0,0,0,0,0,0,3,0,0];
        // let l3=vec![0,7,0,5,0,1,0,4,8];
        // let l4=vec![0,0,0,0,0,0,0,0,0];
        // let l5=vec![2,0,0,3,0,0,9,7,0];
        // let l6=vec![5,0,9,0,0,7,0,8,0];
        // let l7=vec![0,0,7,0,0,0,0,0,0];
        // let l8=vec![0,0,8,0,3,0,0,0,5];
        // let l9=vec![4,2,0,7,0,5,0,0,9];

        //传说中的最难数独
        let l1=vec![8,0,0,0,0,0,0,0,0];
        let l2=vec![0,0,3,6,0,0,0,0,0];
        let l3=vec![0,7,0,0,9,0,2,0,0];
        let l4=vec![0,5,0,0,0,7,0,0,0];
        let l5=vec![0,0,0,0,4,5,7,0,0];
        let l6=vec![0,0,0,1,0,0,0,3,0];
        let l7=vec![0,0,1,0,0,0,0,6,8];
        let l8=vec![0,0,8,5,0,0,0,1,0];
        let l9=vec![0,9,0,0,0,0,4,0,0];
        context.push(l1);
        context.push(l2);
        context.push(l3);
        context.push(l4);
        context.push(l5);
        context.push(l6);
        context.push(l7);
        context.push(l8);
        context.push(l9);
        let mut empty_count=0usize;
        for line in &context {
            for item in line  {
                if 0==*item{
                    empty_count+=1;
                }
            }
        }  
        Sudoku{
            context:context,
            empty_count: empty_count,
            col_step:3,
            row_step:3,
            row_num:9,
            col_num:9,
        }

    }

    //设置指定位置location(row,col)的值
    pub fn set_location_value(&mut self,location:(usize,usize),value:u8){
        self.context[location.0][location.1]=value;
        self.empty_count-=1;
    }
    //重设指定位置location(row,col)的值
    pub fn reset_location_value(&mut self,location:(usize,usize)){
        self.context[location.0][location.1]=0u8;
        self.empty_count+=1;
    }
    //获得某个位置location(row,col)可能的值

    fn get_condianates(&self,location:(usize,usize))->Vec<u8> {
        let mut count=0;
        //bool数组,元素为false表示当前索引值不冲突,可以作为候选值
        let mut flag=Vec::<bool>::new();
        for i in 0..self.col_step*self.row_step{
            flag.push(false);
        }

        //排除行冲突的值
        for  row in 0..self.row_num   {
            let value = self.context[row][location.1];
            //print!("{:?} ",value);
            if 0!=value&&location.0!=row{
               // print!("{:?} ",value);
                count+=1;
                flag[(value-1) as usize ]=true;
            }
        }
        //println!("");
        //排除列冲突的值
        for  col in 0..self.col_num   {
            let value = self.context[location.0][col];
            //print!("{:?} ",value);
            if 0!=value&&location.1!=col{
                //print!("{:?} ",value);
                flag[(value-1) as usize ]=true;
            }
        }
         //println!("");
         //排除周围冲突的值
        let  row_start:usize={
            (location.0/self.row_step)*self.row_step
        };
        let row_end=row_start+self.row_step;

        let  col_start:usize={
            (location.1/self.col_step)*self.col_step
        };
        let col_end=col_start+self.col_step;
        //print!("row_start:{:?},row_end:{:?},col_start:{:?},col_end:{:?} ",row_start,row_end,col_start,col_end);    
        for row in row_start..row_end  {
            // println!("");
            for col in col_start..col_end {

                let value = self.context[row][col];
                //print!("{:?} ",value);
                if 0!=value&&location!=(row,col){

                    count+=1;
                    flag[(value-1) as usize ]=true;
                }
            }
        }
        //索引转为数字
        let mut candiantes=Vec::<u8>::new();
        let mut cand=1u8;
        for v in flag{
            if !v{
                candiantes.push(cand);
            }
            cand+=1;
        }
        candiantes

    }

    //获得候选值最少的位置
    pub fn get_best_location(&mut self)->(usize,usize){
        let mut row=0usize;
        let mut col=0usize;
        let mut cand_count=self.col_step*self.row_step;
        let mut best_cand_location=(0usize,0usize);
        for row in 0..self.row_num {
            for col in 0..self.col_num  {
                if 0==self.context[row][col]{

                    let candinates=self.get_condianates((row,col));
                    //println!("{:?},{:?}",(row,col),candinates);
                    if cand_count>candinates.len(){
                        cand_count=candinates.len();
                        best_cand_location=(row,col);
                    }
                    if 1==cand_count{
                        return best_cand_location;
                    }
                }
            }
        }
        return best_cand_location;  
    }
    //是否解决了
    pub fn is_solved(&self)->bool{
        return 0==self.empty_count;
    }

}
//回溯,深度优先遍历
fn back_trace(sudoku: &mut Sudoku){
    if sudoku.is_solved() {
        //println!("{:?}",sudoku.context);
        for line in &sudoku.context {
            for item in line  {
                print!("{:?},",item);
            }
            println!("");
        }  
        return;
        }
    else{
        //获得候选 最少的位置进行填写
        let best_location=sudoku.get_best_location();
        let candinates=sudoku.get_condianates(best_location);
        for value in candinates {
            sudoku.set_location_value(best_location,value);
            back_trace(sudoku);
            sudoku.reset_location_value(best_location);
        }

    }
}

fn main() {
    let mut sudoku=Sudoku::new9();
    back_trace(&mut sudoku);

}

猜你喜欢

转载自blog.csdn.net/guiqulaxi920/article/details/80376926
今日推荐