Sudoku through the end of chapter 8
This commit is contained in:
parent
7f2f579241
commit
6c0083e094
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,29 +76,56 @@ 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 {
|
||||||
if controller.gameboard.cells[i][j].loaded {
|
if controller.gameboard.cells[i][j].loaded {
|
||||||
color_cell(
|
color_cell(
|
||||||
settings,
|
settings,
|
||||||
[j, i],
|
[j, i],
|
||||||
settings.loaded_cell_background_color,
|
settings.loaded_cell_background_color,
|
||||||
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]];
|
||||||
settings.selected_cell_background_color
|
let color = if !cell.loaded {
|
||||||
} else {
|
if !cell.invalid {
|
||||||
settings.loaded_cell_background_color
|
settings.selected_cell_background_color
|
||||||
};
|
} else {
|
||||||
color_cell(settings, ind, color, c, g);
|
settings.invalid_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);
|
let text_image = Image::new_color(settings.text_color);
|
||||||
|
@ -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);
|
||||||
|
1
piston-tutorials/sudoku/static/puzzle-almost-solved.sdm
Normal file
1
piston-tutorials/sudoku/static/puzzle-almost-solved.sdm
Normal file
@ -0,0 +1 @@
|
|||||||
|
517962483236847915498351762371695248654218397829734156765129834142583679983476520
|
Loading…
Reference in New Issue
Block a user