From 7f2f579241e752ef1da718c8f4c24fe893fe68ac Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Sat, 26 Nov 2022 09:42:41 -0500 Subject: [PATCH] Sudoku up through chapter 7 --- piston-tutorials/sudoku/src/gameboard.rs | 67 +++++++++++++------ piston-tutorials/sudoku/src/gameboard_view.rs | 56 ++++++++++++---- piston-tutorials/sudoku/src/main.rs | 2 +- 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/piston-tutorials/sudoku/src/gameboard.rs b/piston-tutorials/sudoku/src/gameboard.rs index 9c87b05..ec06e3f 100644 --- a/piston-tutorials/sudoku/src/gameboard.rs +++ b/piston-tutorials/sudoku/src/gameboard.rs @@ -1,21 +1,42 @@ //! Game board logic. +use std::fs::read_to_string; + const SIZE: usize = 9; +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Cell { + pub value: u8, + pub loaded: bool, +} + #[derive(Debug, PartialEq)] pub struct Gameboard { - pub cells: [[u8; SIZE]; SIZE], + pub cells: [[Cell; SIZE]; SIZE], } impl Gameboard { pub fn new() -> Gameboard { Gameboard { - cells: [[0; SIZE]; SIZE], + cells: [[Cell::default(); SIZE]; SIZE], } } + pub fn from_cells(cells: [[u8; SIZE]; SIZE]) -> Gameboard { + let mut ret = Gameboard::new(); + for (i, row) in cells.iter().enumerate() { + for (j, &col) in row.iter().enumerate() { + ret.cells[i][j] = Cell { + value: col, + loaded: col != 0, + }; + } + } + ret + } + pub fn char(&self, ind: [usize; 2]) -> Option { - Some(match self.cells[ind[1]][ind[0]] { + Some(match self.cells[ind[1]][ind[0]].value { 1 => '1', 2 => '2', 3 => '3', @@ -30,14 +51,14 @@ impl Gameboard { } pub fn set(&mut self, ind: [usize; 2], val: u8) { - self.cells[ind[1]][ind[0]] = val; + if !self.cells[ind[1]][ind[0]].loaded { + self.cells[ind[1]][ind[0]].value = val; + } } pub fn load_sdm(filename: &str) -> Self { - use std::fs::read_to_string; - let data = read_to_string(filename).expect("failed to read SDM file"); - let mut cells = [[0; SIZE]; SIZE]; + let mut cells = [[Cell::default(); SIZE]; SIZE]; let mut row = 0; let mut col = 0; for c in data.chars() { @@ -45,8 +66,12 @@ impl Gameboard { col = 0; row += 1; } - if let Some(d) = c.to_digit(10) { - cells[row][col] = d as u8; + if let Some(v) = c.to_digit(10) { + let value = v as u8; + cells[row][col] = Cell { + value, + loaded: value != 0, + }; col += 1; } } @@ -62,19 +87,17 @@ mod tests { #[test] fn load_sdm() { let got = Gameboard::load_sdm("static/puzzle.sdm"); - let want = Gameboard { - cells: [ - [0, 1, 6, 4, 0, 0, 0, 0, 0], - [2, 0, 0, 0, 0, 9, 0, 0, 0], - [4, 0, 0, 0, 0, 0, 0, 6, 2], - [0, 7, 0, 2, 3, 0, 1, 0, 0], - [1, 0, 0, 0, 0, 0, 0, 0, 3], - [0, 0, 3, 0, 8, 7, 0, 4, 0], - [9, 6, 0, 0, 0, 0, 0, 0, 5], - [0, 0, 0, 8, 0, 0, 0, 0, 7], - [0, 0, 0, 0, 0, 6, 8, 2, 0], - ], - }; + let want = Gameboard::from_cells([ + [0, 1, 6, 4, 0, 0, 0, 0, 0], + [2, 0, 0, 0, 0, 9, 0, 0, 0], + [4, 0, 0, 0, 0, 0, 0, 6, 2], + [0, 7, 0, 2, 3, 0, 1, 0, 0], + [1, 0, 0, 0, 0, 0, 0, 0, 3], + [0, 0, 3, 0, 8, 7, 0, 4, 0], + [9, 6, 0, 0, 0, 0, 0, 0, 5], + [0, 0, 0, 8, 0, 0, 0, 0, 7], + [0, 0, 0, 0, 0, 6, 8, 2, 0], + ]); assert_eq!(got, want); } } diff --git a/piston-tutorials/sudoku/src/gameboard_view.rs b/piston-tutorials/sudoku/src/gameboard_view.rs index a1c9d39..d6beb0e 100644 --- a/piston-tutorials/sudoku/src/gameboard_view.rs +++ b/piston-tutorials/sudoku/src/gameboard_view.rs @@ -19,6 +19,7 @@ pub struct GameboardViewSettings { pub cell_edge_radius: f64, pub selected_cell_background_color: Color, pub text_color: Color, + pub loaded_cell_background_color: Color, } impl GameboardViewSettings { @@ -36,6 +37,7 @@ impl GameboardViewSettings { cell_edge_radius: 1.0, selected_cell_background_color: [0.9, 0.9, 1.0, 1.0], text_color: [0.0, 0.0, 0.1, 1.0], + loaded_cell_background_color: [1.0, 1.0, 1.0, 1.0], } } } @@ -70,21 +72,27 @@ impl GameboardView { Rectangle::new(settings.background_color).draw(board_rect, &c.draw_state, c.transform, g); + for i in 0..9 { + for j in 0..9 { + if controller.gameboard.cells[i][j].loaded { + color_cell( + settings, + [j, i], + settings.loaded_cell_background_color, + c, + g, + ); + } + } + } + if let Some(ind) = controller.selected_cell { - let cell_size = settings.size / 9.0; - let pos = [ind[0] as f64 * cell_size, ind[1] as f64 * cell_size]; - let cell_rect = [ - settings.position[0] + pos[0], - settings.position[1] + pos[1], - cell_size, - cell_size, - ]; - Rectangle::new(settings.selected_cell_background_color).draw( - cell_rect, - &c.draw_state, - c.transform, - g, - ); + let color = if !controller.gameboard.cells[ind[1]][ind[0]].loaded { + settings.selected_cell_background_color + } else { + settings.loaded_cell_background_color + }; + color_cell(settings, ind, color, c, g); } let text_image = Image::new_color(settings.text_color); @@ -147,3 +155,23 @@ impl GameboardView { ); } } + +fn color_cell( + settings: &GameboardViewSettings, + ind: [usize; 2], + color: [f32; 4], + c: &Context, + g: &mut G, +) { + use graphics::Rectangle; + + let cell_size = settings.size / 9.0; + let pos = [ind[0] as f64 * cell_size, ind[1] as f64 * cell_size]; + let cell_rect = [ + settings.position[0] + pos[0], + settings.position[1] + pos[1], + cell_size, + cell_size, + ]; + Rectangle::new(color).draw(cell_rect, &c.draw_state, c.transform, g); +} diff --git a/piston-tutorials/sudoku/src/main.rs b/piston-tutorials/sudoku/src/main.rs index 6f8138b..7391dfb 100644 --- a/piston-tutorials/sudoku/src/main.rs +++ b/piston-tutorials/sudoku/src/main.rs @@ -27,7 +27,7 @@ fn main() { let mut events = Events::new(EventSettings::new().lazy(true)); let mut gl = GlGraphics::new(opengl); - let gameboard = Gameboard::new(); + let gameboard = Gameboard::load_sdm("static/puzzle.sdm"); let mut gameboard_controller = GameboardController::new(gameboard); let gameboard_view_settings = GameboardViewSettings::new(); let gameboard_view = GameboardView::new(gameboard_view_settings);