diff --git a/src/main.rs b/src/main.rs index f0b1e2b..820864e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,7 @@ struct Args { /// Create puzzle #[arg(long)] - puzzle: bool, + puzzle: Option, } @@ -58,8 +58,8 @@ fn main() { return } - let result = if args.puzzle { - solver.make_puzzle().map(|_| ()) + let result = if let Some(difficulty) = args.puzzle { + solver.make_puzzle(difficulty).map(|_| ()) } else { solver.solve(args.limit).map(|_| ()) }; diff --git a/src/solver/mod.rs b/src/solver/mod.rs index 80cef80..06890a4 100644 --- a/src/solver/mod.rs +++ b/src/solver/mod.rs @@ -139,30 +139,35 @@ impl Solver { } } - pub fn make_puzzle(&mut self) -> Result<(), WaveError> { + pub fn make_puzzle(&mut self, difficulty: usize) -> Result<(), WaveError> { self.solve_display = false; - println!("# generating full..."); + println!("\n# generating full..."); let _ = self.solve(None)?; println!("\n\n# erasing cells..."); let mut rng = rand::thread_rng(); - - let erase_cell = loop { - let pos = (rng.gen_range(1..=self.size), rng.gen_range(1..=self.size)); - if let Some(state) = self.grid[pos.0][pos.1].get_state() { - self.grid[pos.0][pos.1].reset_state(); - break (pos, state); - } - }; - let blocking_cell = cell::BlockingCell { - state: erase_cell.1, - position: erase_cell.0, - }; - - self.propagate_backtrack(erase_cell.0, blocking_cell); // get min allowed state number - // while min state number < 2 => loop + let mut min_num_allowed = 1; + while min_num_allowed <= difficulty { + let erase_cell = loop { + let pos = (rng.gen_range(0..self.size), rng.gen_range(0..self.size)); + if let Some(state) = self.grid[pos.0][pos.1].get_state() { + self.grid[pos.0][pos.1].reset_state(); + break (pos, state); + } + }; + let blocking_cell = cell::BlockingCell { + state: erase_cell.1, + position: erase_cell.0, + }; + min_num_allowed = self.propagate_backtrack(erase_cell.0, blocking_cell); + if min_num_allowed > difficulty { + let _ = self.grid[erase_cell.0.0][erase_cell.0.1].collapse(&cell::CollapseOption::Set(erase_cell.1)); + //println!("put back ({},{}) to {}", erase_cell.0.0, erase_cell.0.1, erase_cell.1); + //self.propagate_collapse(erase_cell.0, blocking_cell); + } + } println!(); self.display(ui::DisplayMode::Full); diff --git a/src/solver/sudoku.rs b/src/solver/sudoku.rs index 1ab579d..9cc335e 100644 --- a/src/solver/sudoku.rs +++ b/src/solver/sudoku.rs @@ -74,7 +74,9 @@ impl Solver { Ok(()) } - pub fn propagate_backtrack(&mut self, cell_pos: (usize, usize), removed_cell: cell::BlockingCell) { + pub fn propagate_backtrack(&mut self, cell_pos: (usize, usize), removed_cell: cell::BlockingCell) -> usize { + let mut min_allowed_number = self.size; + for index in 0..self.size { if index != cell_pos.0 { self.grid[index][cell_pos.1].add_allowed(&removed_cell); @@ -87,6 +89,12 @@ impl Solver { if square_row != cell_pos.0 || square_column != cell_pos.1 { self.grid[square_row][square_column].add_allowed(&removed_cell); } + let num_allowed = self.grid[square_row][square_column].get_num_allowed(); + if num_allowed < min_allowed_number { + min_allowed_number = num_allowed + } } + + min_allowed_number } }