Sudoku through the end of chapter 8

This commit is contained in:
Dan Buch 2022-11-26 16:09:32 -05:00
parent 7f2f579241
commit 6c0083e094
Signed by: meatballhat
GPG Key ID: A12F782281063434
4 changed files with 110 additions and 21 deletions

View File

@ -8,17 +8,20 @@ const SIZE: usize = 9;
pub struct Cell { pub struct Cell {
pub value: u8, pub value: u8,
pub loaded: bool, pub loaded: bool,
pub invalid: bool,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Gameboard { pub struct Gameboard {
pub cells: [[Cell; SIZE]; SIZE], pub cells: [[Cell; SIZE]; SIZE],
pub completed: bool,
} }
impl Gameboard { impl Gameboard {
pub fn new() -> Gameboard { pub fn new() -> Gameboard {
Gameboard { Gameboard {
cells: [[Cell::default(); SIZE]; SIZE], cells: [[Cell::default(); SIZE]; SIZE],
completed: false,
} }
} }
@ -29,6 +32,7 @@ impl Gameboard {
ret.cells[i][j] = Cell { ret.cells[i][j] = Cell {
value: col, value: col,
loaded: col != 0, loaded: col != 0,
invalid: false,
}; };
} }
} }
@ -52,8 +56,15 @@ impl Gameboard {
pub fn set(&mut self, ind: [usize; 2], val: u8) { pub fn set(&mut self, ind: [usize; 2], val: u8) {
if !self.cells[ind[1]][ind[0]].loaded { if !self.cells[ind[1]][ind[0]].loaded {
self.validate(ind, val);
self.cells[ind[1]][ind[0]].value = val; self.cells[ind[1]][ind[0]].value = val;
} }
self.completed = self
.cells
.iter()
.flatten()
.all(|cell| !cell.invalid && cell.value != 0);
} }
pub fn load_sdm(filename: &str) -> Self { pub fn load_sdm(filename: &str) -> Self {
@ -71,12 +82,53 @@ impl Gameboard {
cells[row][col] = Cell { cells[row][col] = Cell {
value, value,
loaded: value != 0, loaded: value != 0,
invalid: false,
}; };
col += 1; col += 1;
} }
} }
Self { cells } Self {
cells,
completed: false,
}
}
fn validate(&mut self, ind: [usize; 2], val: u8) {
let [b, a] = ind;
for i in 0..SIZE {
if i == a {
continue;
}
if self.cells[a][i].value == val {
self.cells[a][b].invalid = true;
return;
}
}
for i in 0..SIZE {
if i == b {
continue;
}
if self.cells[i][b].value == val {
self.cells[a][b].invalid = true;
return;
}
}
let (row, col) = (a / 3, b / 3);
for i in 3 * row..3 * row + 3 {
for j in 3 * col..3 * col + 3 {
if i == a && j == b {
continue;
}
if self.cells[i][j].value == val {
self.cells[a][b].invalid = true;
return;
}
}
}
self.cells[a][b].invalid = false;
} }
} }

View File

@ -20,6 +20,9 @@ pub struct GameboardViewSettings {
pub selected_cell_background_color: Color, pub selected_cell_background_color: Color,
pub text_color: Color, pub text_color: Color,
pub loaded_cell_background_color: Color, pub loaded_cell_background_color: Color,
pub invalid_cell_background_color: Color,
pub invalid_selected_cell_background_color: Color,
pub completed_background_color: Color,
} }
impl GameboardViewSettings { impl GameboardViewSettings {
@ -38,6 +41,9 @@ impl GameboardViewSettings {
selected_cell_background_color: [0.9, 0.9, 1.0, 1.0], selected_cell_background_color: [0.9, 0.9, 1.0, 1.0],
text_color: [0.0, 0.0, 0.1, 1.0], text_color: [0.0, 0.0, 0.1, 1.0],
loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0], loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0],
invalid_cell_background_color: [1.0, 0.0, 0.0, 1.0],
invalid_selected_cell_background_color: [1.0, 0.0, 0.5, 1.0],
completed_background_color: [0.0, 1.0, 0.0, 1.0],
} }
} }
} }
@ -70,7 +76,20 @@ impl GameboardView {
settings.size, settings.size,
]; ];
Rectangle::new(settings.background_color).draw(board_rect, &c.draw_state, c.transform, g); if controller.gameboard.completed {
Rectangle::new(settings.completed_background_color).draw(
board_rect,
&c.draw_state,
c.transform,
g,
);
} else {
Rectangle::new(settings.background_color).draw(
board_rect,
&c.draw_state,
c.transform,
g,
);
for i in 0..9 { for i in 0..9 {
for j in 0..9 { for j in 0..9 {
@ -82,18 +101,32 @@ impl GameboardView {
c, c,
g, g,
); );
} else if controller.gameboard.cells[i][j].invalid {
color_cell(
settings,
[j, i],
settings.invalid_cell_background_color,
c,
g,
);
} }
} }
} }
if let Some(ind) = controller.selected_cell { if let Some(ind) = controller.selected_cell {
let color = if !controller.gameboard.cells[ind[1]][ind[0]].loaded { let cell = controller.gameboard.cells[ind[1]][ind[0]];
let color = if !cell.loaded {
if !cell.invalid {
settings.selected_cell_background_color settings.selected_cell_background_color
} else {
settings.invalid_selected_cell_background_color
}
} else { } else {
settings.loaded_cell_background_color settings.loaded_cell_background_color
}; };
color_cell(settings, ind, color, c, g); color_cell(settings, ind, color, c, g);
} }
}
let text_image = Image::new_color(settings.text_color); let text_image = Image::new_color(settings.text_color);
let cell_size = settings.size / 9.0; let cell_size = settings.size / 9.0;

View File

@ -27,7 +27,10 @@ fn main() {
let mut events = Events::new(EventSettings::new().lazy(true)); let mut events = Events::new(EventSettings::new().lazy(true));
let mut gl = GlGraphics::new(opengl); let mut gl = GlGraphics::new(opengl);
let gameboard = Gameboard::load_sdm("static/puzzle.sdm"); let args: Vec<_> = std::env::args().collect();
let infile = args.get(1).expect("usage: sudoku <sdm-file>");
let gameboard = Gameboard::load_sdm(infile);
let mut gameboard_controller = GameboardController::new(gameboard); let mut gameboard_controller = GameboardController::new(gameboard);
let gameboard_view_settings = GameboardViewSettings::new(); let gameboard_view_settings = GameboardViewSettings::new();
let gameboard_view = GameboardView::new(gameboard_view_settings); let gameboard_view = GameboardView::new(gameboard_view_settings);

View File

@ -0,0 +1 @@
517962483236847915498351762371695248654218397829734156765129834142583679983476520