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);
}
Rust 数独计算
猜你喜欢
转载自blog.csdn.net/guiqulaxi920/article/details/80376926
今日推荐
周排行