|
@@ -43,6 +43,7 @@ impl error::Error for GameLoadError {}
|
|
/// Currently board limited to < 8x8 boards because of u8 limit. (8x8 say WAT?!)
|
|
/// Currently board limited to < 8x8 boards because of u8 limit. (8x8 say WAT?!)
|
|
/// Also limited on display (we handle 5X5 boards A-Y). Anything > 5, we would have
|
|
/// Also limited on display (we handle 5X5 boards A-Y). Anything > 5, we would have
|
|
/// figure out something else for display output.
|
|
/// figure out something else for display output.
|
|
|
|
+/// - Should I be doing a Vec<Result<u8>> ? Some/None?
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
pub struct AnyBoard {
|
|
pub struct AnyBoard {
|
|
/// Size of board (cell width)
|
|
/// Size of board (cell width)
|
|
@@ -54,6 +55,7 @@ pub struct AnyBoard {
|
|
/// Actual board data
|
|
/// Actual board data
|
|
/// 0 = blank (not 1!)
|
|
/// 0 = blank (not 1!)
|
|
/// 1..=width+1 = values
|
|
/// 1..=width+1 = values
|
|
|
|
+ /// Maybe Option<u8> instead and get rid of our off by one issue?
|
|
pub board: Vec<u8>,
|
|
pub board: Vec<u8>,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -529,6 +531,11 @@ impl AnyBoard {
|
|
X values don't change or move.
|
|
X values don't change or move.
|
|
Uppercase letter gets swapped with lower case.
|
|
Uppercase letter gets swapped with lower case.
|
|
|
|
|
|
|
|
+ (1,0) = a
|
|
|
|
+ (0,1) = A
|
|
|
|
+ (2,1) = c
|
|
|
|
+ (1,2) = C
|
|
|
|
+
|
|
╔═══╦═══╦═══╗
|
|
╔═══╦═══╦═══╗
|
|
║Xab║dfi║lp ║
|
|
║Xab║dfi║lp ║
|
|
║AXc║ehk║o ║
|
|
║AXc║ehk║o ║
|
|
@@ -550,9 +557,16 @@ impl AnyBoard {
|
|
// (x1,y1) = lower case
|
|
// (x1,y1) = lower case
|
|
// (x2,y2) = upper case
|
|
// (x2,y2) = upper case
|
|
|
|
|
|
|
|
+ // The last position on the board, there's nothing for us to do.
|
|
|
|
+ // So we don't include it in our for loop. (self.width-1)
|
|
|
|
+
|
|
for idx in 0..self.width - 1 {
|
|
for idx in 0..self.width - 1 {
|
|
// println!("idx: {idx}");
|
|
// println!("idx: {idx}");
|
|
for pass in 0..2 {
|
|
for pass in 0..2 {
|
|
|
|
+ // pass 0: values that are 🡷🡵 to x1 + 1 and y2 +1.
|
|
|
|
+ // pass 1: values that are 🡷🡵 to the midpoint.
|
|
|
|
+
|
|
|
|
+ // Start x1,y1 and x2,y2 at same midpoint.
|
|
x1 = idx;
|
|
x1 = idx;
|
|
x2 = idx;
|
|
x2 = idx;
|
|
y1 = idx;
|
|
y1 = idx;
|
|
@@ -563,10 +577,13 @@ impl AnyBoard {
|
|
y2 += 1;
|
|
y2 += 1;
|
|
} else {
|
|
} else {
|
|
if idx == 0 {
|
|
if idx == 0 {
|
|
|
|
+ // We'd be out of bounds (of board and of u8)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ // Move (x1,y1) 🡵
|
|
x1 += 1;
|
|
x1 += 1;
|
|
y1 -= 1;
|
|
y1 -= 1;
|
|
|
|
+ // Move (x2,y2) 🡷
|
|
x2 -= 1;
|
|
x2 -= 1;
|
|
y2 += 1;
|
|
y2 += 1;
|
|
}
|
|
}
|
|
@@ -577,10 +594,13 @@ impl AnyBoard {
|
|
(self[(x1, y1)], self[(x2, y2)]) = (self[(x2, y2)], self[(x1, y1)]);
|
|
(self[(x1, y1)], self[(x2, y2)]) = (self[(x2, y2)], self[(x1, y1)]);
|
|
|
|
|
|
if (y1 == 0) || (x2 == 0) {
|
|
if (y1 == 0) || (x2 == 0) {
|
|
|
|
+ // We would be moving out of bounds (of board and u8).
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ // Move (x1,y1) 🡵
|
|
x1 += 1;
|
|
x1 += 1;
|
|
y1 -= 1;
|
|
y1 -= 1;
|
|
|
|
+ // Move (x2,y2) 🡷
|
|
x2 -= 1;
|
|
x2 -= 1;
|
|
y2 += 1;
|
|
y2 += 1;
|
|
|
|
|
|
@@ -622,7 +642,7 @@ impl AnyBoard {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /// Rotate board Clockwise
|
|
|
|
|
|
+ /// Rotate board Clockwise ↻
|
|
///
|
|
///
|
|
/// Which is same as flip + flip_x.
|
|
/// Which is same as flip + flip_x.
|
|
pub fn rotate_cw(&mut self) {
|
|
pub fn rotate_cw(&mut self) {
|
|
@@ -639,7 +659,7 @@ impl AnyBoard {
|
|
*/
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
- /// Rotate board Counter-Clockwise
|
|
|
|
|
|
+ /// Rotate board Counter-Clockwise ↺
|
|
///
|
|
///
|
|
/// Which is flip + flip_y.
|
|
/// Which is flip + flip_y.
|
|
pub fn rotate_ccw(&mut self) {
|
|
pub fn rotate_ccw(&mut self) {
|
|
@@ -966,7 +986,7 @@ pub struct AnySolver {
|
|
/// Groups (Rows, Columns, Cells)
|
|
/// Groups (Rows, Columns, Cells)
|
|
pub group: AnyGroup,
|
|
pub group: AnyGroup,
|
|
// Is this value set in the given cell?
|
|
// Is this value set in the given cell?
|
|
- pub cell_poss: Vec<Flags>,
|
|
|
|
|
|
+ // pub cell_poss: Vec<Flags>,
|
|
}
|
|
}
|
|
|
|
|
|
impl AnySolver {
|
|
impl AnySolver {
|
|
@@ -981,7 +1001,7 @@ impl AnySolver {
|
|
board: AnyBoard::new(board_size),
|
|
board: AnyBoard::new(board_size),
|
|
possible: AnyPossible::new(board_size),
|
|
possible: AnyPossible::new(board_size),
|
|
group: AnyGroup::new(board_size),
|
|
group: AnyGroup::new(board_size),
|
|
- cell_poss: vec![default_poss; width as usize * width as usize],
|
|
|
|
|
|
+ // cell_poss: vec![default_poss; width as usize * width as usize],
|
|
};
|
|
};
|
|
s.reset_possible();
|
|
s.reset_possible();
|
|
s
|
|
s
|
|
@@ -996,10 +1016,12 @@ impl AnySolver {
|
|
board: initial_board.clone(),
|
|
board: initial_board.clone(),
|
|
possible: AnyPossible::new(initial_board.size),
|
|
possible: AnyPossible::new(initial_board.size),
|
|
group: AnyGroup::new(initial_board.size),
|
|
group: AnyGroup::new(initial_board.size),
|
|
|
|
+ /*
|
|
cell_poss: vec![
|
|
cell_poss: vec![
|
|
default_poss;
|
|
default_poss;
|
|
initial_board.width as usize * initial_board.width as usize
|
|
initial_board.width as usize * initial_board.width as usize
|
|
],
|
|
],
|
|
|
|
+ */
|
|
};
|
|
};
|
|
s.reset_possible();
|
|
s.reset_possible();
|
|
s
|
|
s
|
|
@@ -1024,10 +1046,9 @@ impl AnySolver {
|
|
/// Process a move
|
|
/// Process a move
|
|
/// - Remove value from rows, columns, and cells.
|
|
/// - Remove value from rows, columns, and cells.
|
|
/// - Clear possibles from (x,y) position, it's filled.
|
|
/// - Clear possibles from (x,y) position, it's filled.
|
|
- /// - Added finalize parameter
|
|
|
|
/// - Use it when doing a single move.
|
|
/// - Use it when doing a single move.
|
|
/// - Don't do it when setting up the board. Call finalize_move then.
|
|
/// - Don't do it when setting up the board. Call finalize_move then.
|
|
- pub fn process_move(&mut self, x: u8, y: u8, value: u8, finalize: bool) {
|
|
|
|
|
|
+ pub fn process_move(&mut self, x: u8, y: u8, value: u8) {
|
|
debug_assert!(
|
|
debug_assert!(
|
|
x <= self.board.width && y <= self.board.width,
|
|
x <= self.board.width && y <= self.board.width,
|
|
"Expected ({}, {}) <= {}",
|
|
"Expected ({}, {}) <= {}",
|
|
@@ -1060,17 +1081,6 @@ impl AnySolver {
|
|
let idx = self.possible.pos(x, y);
|
|
let idx = self.possible.pos(x, y);
|
|
self.possible.possible[idx] = Flags::new(self.board.width as usize);
|
|
self.possible.possible[idx] = Flags::new(self.board.width as usize);
|
|
self.board.board[idx] = value;
|
|
self.board.board[idx] = value;
|
|
-
|
|
|
|
- // Tests are run as debug, and this kills things...
|
|
|
|
- // Like the invalid board in validated_board test.
|
|
|
|
- let cell_index = self.group.which_cell(x, y);
|
|
|
|
-
|
|
|
|
- self.cell_poss[cell_index as usize].set(value as usize - 1, false);
|
|
|
|
-
|
|
|
|
- if finalize {
|
|
|
|
- self.finalize_possible();
|
|
|
|
- // self.finalize_cell(cell_index);
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1088,7 +1098,7 @@ impl AnySolver {
|
|
const OUTPUT: bool = false;
|
|
const OUTPUT: bool = false;
|
|
|
|
|
|
if OUTPUT {
|
|
if OUTPUT {
|
|
- println!("finalize_possible starts");
|
|
|
|
|
|
+ println!("finalize_possible starts");
|
|
};
|
|
};
|
|
|
|
|
|
// I might want to save the pair information.
|
|
// I might want to save the pair information.
|
|
@@ -1366,7 +1376,7 @@ impl AnySolver {
|
|
}
|
|
}
|
|
|
|
|
|
if OUTPUT {
|
|
if OUTPUT {
|
|
- println!("finalize_possible ends...");
|
|
|
|
|
|
+ println!("finalize_possible ends...");
|
|
}
|
|
}
|
|
return updated;
|
|
return updated;
|
|
|
|
|
|
@@ -1803,6 +1813,7 @@ impl AnySolver {
|
|
// TOFIX:
|
|
// TOFIX:
|
|
// See: AnyPossible's find_value_pos!
|
|
// See: AnyPossible's find_value_pos!
|
|
|
|
|
|
|
|
+ /*
|
|
// Check columns - (of given cell) for logical removes (see logic_test for example)
|
|
// Check columns - (of given cell) for logical removes (see logic_test for example)
|
|
for value in 0..width {
|
|
for value in 0..width {
|
|
// Find what columns value is allowed. (in which cells).
|
|
// Find what columns value is allowed. (in which cells).
|
|
@@ -1843,6 +1854,8 @@ impl AnySolver {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ */
|
|
|
|
+
|
|
if NOISY {
|
|
if NOISY {
|
|
println!("finalize_cell ends...");
|
|
println!("finalize_cell ends...");
|
|
}
|
|
}
|
|
@@ -1884,9 +1897,11 @@ impl AnySolver {
|
|
let mut default_poss = Flags::new(self.board.width as usize);
|
|
let mut default_poss = Flags::new(self.board.width as usize);
|
|
default_poss.set_range(0..self.board.width as usize);
|
|
default_poss.set_range(0..self.board.width as usize);
|
|
|
|
|
|
|
|
+ /*
|
|
for x in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
self.cell_poss[x as usize] = default_poss.clone();
|
|
self.cell_poss[x as usize] = default_poss.clone();
|
|
}
|
|
}
|
|
|
|
+ */
|
|
|
|
|
|
for y in 0..self.board.width {
|
|
for y in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
@@ -1902,7 +1917,7 @@ impl AnySolver {
|
|
// self.board.display();
|
|
// self.board.display();
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- self.process_move(x, y, value, false);
|
|
|
|
|
|
+ self.process_move(x, y, value);
|
|
} else {
|
|
} else {
|
|
// Below, we check to see if blanks have possible values.
|
|
// Below, we check to see if blanks have possible values.
|
|
|
|
|
|
@@ -1946,15 +1961,17 @@ impl AnySolver {
|
|
let mut default_poss = Flags::new(self.board.width as usize);
|
|
let mut default_poss = Flags::new(self.board.width as usize);
|
|
default_poss.set_range(0..self.board.width as usize);
|
|
default_poss.set_range(0..self.board.width as usize);
|
|
|
|
|
|
|
|
+ /*
|
|
for x in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
self.cell_poss[x as usize] = default_poss.clone();
|
|
self.cell_poss[x as usize] = default_poss.clone();
|
|
}
|
|
}
|
|
|
|
+ */
|
|
|
|
|
|
for y in 0..self.board.width {
|
|
for y in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
for x in 0..self.board.width {
|
|
let value = self.board.get(x, y);
|
|
let value = self.board.get(x, y);
|
|
if value != 0 {
|
|
if value != 0 {
|
|
- self.process_move(x, y, value, false);
|
|
|
|
|
|
+ self.process_move(x, y, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1966,8 +1983,7 @@ impl AnySolver {
|
|
/// - This updates the board.
|
|
/// - This updates the board.
|
|
/// - This updates all the possibles (row,column,cell).
|
|
/// - This updates all the possibles (row,column,cell).
|
|
/// - Clears the possible for (x,y) [See process_move].
|
|
/// - Clears the possible for (x,y) [See process_move].
|
|
- /// TO FIX: I think set also needs finalize ... to pass to process_move.
|
|
|
|
- pub fn set(&mut self, x: u8, y: u8, value: u8, finalize: bool) {
|
|
|
|
|
|
+ pub fn set(&mut self, x: u8, y: u8, value: u8) {
|
|
debug_assert!(
|
|
debug_assert!(
|
|
x < self.board.width && y < self.board.width,
|
|
x < self.board.width && y < self.board.width,
|
|
"Expected ({}, {}) < {}",
|
|
"Expected ({}, {}) < {}",
|
|
@@ -1984,7 +2000,7 @@ impl AnySolver {
|
|
|
|
|
|
self.board.set(x, y, value);
|
|
self.board.set(x, y, value);
|
|
if value != 0 {
|
|
if value != 0 {
|
|
- self.process_move(x, y, value, finalize);
|
|
|
|
|
|
+ self.process_move(x, y, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2039,7 +2055,7 @@ impl AnySolver {
|
|
for value in available.into_iter() {
|
|
for value in available.into_iter() {
|
|
assert!(value != 0);
|
|
assert!(value != 0);
|
|
|
|
|
|
- self.set(x, y, value, true);
|
|
|
|
|
|
+ self.set(x, y, value);
|
|
// self.board.display();
|
|
// self.board.display();
|
|
// self.possible.display();
|
|
// self.possible.display();
|
|
|
|
|
|
@@ -2050,9 +2066,11 @@ impl AnySolver {
|
|
self.board.copy(&backup.board);
|
|
self.board.copy(&backup.board);
|
|
self.possible.copy(&backup.possible);
|
|
self.possible.copy(&backup.possible);
|
|
|
|
|
|
|
|
+ /*
|
|
for i in 0..backup.cell_poss.len() {
|
|
for i in 0..backup.cell_poss.len() {
|
|
self.cell_poss[i] = backup.cell_poss[i].clone();
|
|
self.cell_poss[i] = backup.cell_poss[i].clone();
|
|
}
|
|
}
|
|
|
|
+ */
|
|
// self.cell_poss.copy( backup.cell_poss);
|
|
// self.cell_poss.copy( backup.cell_poss);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2092,7 +2110,7 @@ impl AnySolver {
|
|
value = self.get(x, y);
|
|
value = self.get(x, y);
|
|
}
|
|
}
|
|
|
|
|
|
- self.set(x, y, 0, true);
|
|
|
|
|
|
+ self.set(x, y, 0);
|
|
|
|
|
|
// clone, and solve by logic.
|
|
// clone, and solve by logic.
|
|
let mut puzcopy = self.clone();
|
|
let mut puzcopy = self.clone();
|
|
@@ -2105,7 +2123,7 @@ impl AnySolver {
|
|
|
|
|
|
// Not solvable, restore and return false.
|
|
// Not solvable, restore and return false.
|
|
// Since this failed, don't bother to finalize.
|
|
// Since this failed, don't bother to finalize.
|
|
- self.set(x, y, value, false);
|
|
|
|
|
|
+ self.set(x, y, value);
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2135,7 +2153,7 @@ impl AnySolver {
|
|
let value = self.possible.possible[i].iter().next().unwrap() + 1;
|
|
let value = self.possible.possible[i].iter().next().unwrap() + 1;
|
|
let pos = self.board.xy(i);
|
|
let pos = self.board.xy(i);
|
|
// println!("SET {}({},{})={}", i, pos.0 + 1, pos.1 + 1, value);
|
|
// println!("SET {}({},{})={}", i, pos.0 + 1, pos.1 + 1, value);
|
|
- self.set(pos.0, pos.1, value as u8, true);
|
|
|
|
|
|
+ self.set(pos.0, pos.1, value as u8);
|
|
found_something = true;
|
|
found_something = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2146,6 +2164,7 @@ impl AnySolver {
|
|
// - Record that we did something.
|
|
// - Record that we did something.
|
|
pass1 = true;
|
|
pass1 = true;
|
|
pass1_again = true;
|
|
pass1_again = true;
|
|
|
|
+ self.finalize_possible();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pass1
|
|
pass1
|
|
@@ -2205,7 +2224,7 @@ impl AnySolver {
|
|
let xy = this.board.xy(pos);
|
|
let xy = this.board.xy(pos);
|
|
// this.possible.display();
|
|
// this.possible.display();
|
|
// this.board.display();
|
|
// this.board.display();
|
|
- this.set(xy.0, xy.1, (v + 1) as u8, true);
|
|
|
|
|
|
+ this.set(xy.0, xy.1, (v + 1) as u8);
|
|
// println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
|
|
// println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
|
|
|
|
|
|
found_something = true;
|
|
found_something = true;
|