Skip to content

Commit

Permalink
Merge pull request #6 from Jayllyz/feature/darkUI&clean
Browse files Browse the repository at this point in the history
  • Loading branch information
Jayllyz authored May 1, 2023
2 parents eae17b6 + b4c478d commit e25444a
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 90 deletions.
96 changes: 24 additions & 72 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use lazy_static::lazy_static;
use rand::Rng;
use std::sync::Mutex;
use tera::{Context, Tera};
mod sudoku;

const BOARD_SIZE: usize = 9;
const SQUARE_SIZE: usize = 3;

struct Sudoku {
pub board: Mutex<Vec<Vec<usize>>>,
}
Expand Down Expand Up @@ -47,7 +45,7 @@ async fn update_table(
difficulty: web::Path<usize>,
) -> impl Responder {
let difficulty = difficulty.into_inner();
let board = generate(BOARD_SIZE, difficulty);
let board = sudoku::generate(BOARD_SIZE, difficulty);
app_state.set_board(board.clone());

let mut context = Context::new();
Expand All @@ -62,7 +60,7 @@ async fn update_table(

async fn solve_table(tera: web::Data<Tera>, data: web::Data<Sudoku>) -> impl Responder {
let mut board = data.board.lock().unwrap().clone();
resolv_backtrack(&mut board, 0, 0);
sudoku::resolv_backtrack(&mut board, 0, 0);
data.set_board(board.clone());

let mut context = Context::new();
Expand Down Expand Up @@ -106,74 +104,28 @@ async fn main() -> std::io::Result<()> {
.await
}

pub fn generate(size: usize, difficulty: usize) -> Vec<Vec<usize>> {
let mut board = vec![vec![0; size]; size];
let mut rng = rand::thread_rng();
let luck: f64;
match difficulty {
1 => luck = 0.4,
2 => luck = 0.45,
3 => luck = 0.5,
_ => luck = 0.4,
}
resolv_backtrack(&mut board, 0, 0); // generate a valid board
for i in 0..size {
for j in 0..size {
if rng.gen_bool(luck) {
board[i][j] = 0;
#[cfg(test)]
mod tests {
use crate::{sudoku::generate, sudoku::resolv_backtrack};

#[test]
fn board_valid() {
const BOARD_SIZE: usize = 9;
let board = generate(BOARD_SIZE, 1);
assert_eq!(board.len(), 9);

let mut hm = std::collections::HashMap::new();
for i in 0..BOARD_SIZE {
for j in 0..BOARD_SIZE {
if hm.contains_key(&board[i][j]) {
assert!(false);
}
if board[i][j] != 0 {
hm.insert(board[i][j], true);
}
}
hm.clear();
}
assert_eq!(resolv_backtrack(&mut board.clone(), 0, 0), true);
}
board
}
pub fn is_num_valid(board: &Vec<Vec<usize>>, row: usize, col: usize, num: usize) -> bool {
for i in 0..board.len() {
if board[row][i] == num || board[i][col] == num {
return false;
}
}

let sub_row = (row / SQUARE_SIZE) * SQUARE_SIZE;
let sub_col = (col / SQUARE_SIZE) * SQUARE_SIZE;
for i in 0..SQUARE_SIZE {
for j in 0..SQUARE_SIZE {
if board[sub_row + i][sub_col + j] == num {
return false;
}
}
}
true
}

// backtracking algorithm
// https://en.wikipedia.org/wiki/Sudoku_solving_algorithms#Backtracking
// inspired by https://gist.github.com/raeffu/8331328

pub fn resolv_backtrack(board: &mut Vec<Vec<usize>>, mut row: usize, mut col: usize) -> bool {
if col == board.len() {
col = 0;
row += 1;
if row == board.len() {
// end of board
return true;
}
}

if board[row][col] != 0 {
return resolv_backtrack(board, row, col + 1);
}

for num in 1..=board.len() {
if is_num_valid(board, row, col, num) {
board[row][col] = num;
if resolv_backtrack(board, row, col + 1) {
// found a number
return true;
}
// backtrack
board[row][col] = 0;
}
}

false
}
75 changes: 75 additions & 0 deletions src/sudoku.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use rand::Rng;

const SQUARE_SIZE: usize = 3;

pub fn generate(size: usize, difficulty: usize) -> Vec<Vec<usize>> {
let mut board = vec![vec![0; size]; size];
let mut rng = rand::thread_rng();
let luck: f64;
match difficulty {
1 => luck = 0.4,
2 => luck = 0.5,
3 => luck = 0.6,
_ => luck = 0.4,
}
resolv_backtrack(&mut board, 0, 0); // generate a valid board
for i in 0..size {
for j in 0..size {
if rng.gen_bool(luck) {
board[i][j] = 0;
}
}
}
board
}
pub fn is_num_valid(board: &Vec<Vec<usize>>, row: usize, col: usize, num: usize) -> bool {
for i in 0..board.len() {
if board[row][i] == num || board[i][col] == num {
return false;
}
}

let sub_row = (row / SQUARE_SIZE) * SQUARE_SIZE;
let sub_col = (col / SQUARE_SIZE) * SQUARE_SIZE;
for i in 0..SQUARE_SIZE {
for j in 0..SQUARE_SIZE {
if board[sub_row + i][sub_col + j] == num {
return false;
}
}
}
true
}

// backtracking algorithm
// https://en.wikipedia.org/wiki/Sudoku_solving_algorithms#Backtracking
// inspired by https://gist.github.com/raeffu/8331328

pub fn resolv_backtrack(board: &mut Vec<Vec<usize>>, mut row: usize, mut col: usize) -> bool {
if col == board.len() {
col = 0;
row += 1;
if row == board.len() {
// end of board
return true;
}
}

if board[row][col] != 0 {
return resolv_backtrack(board, row, col + 1);
}

for num in 1..=board.len() {
if is_num_valid(board, row, col, num) {
board[row][col] = num;
if resolv_backtrack(board, row, col + 1) {
// found a number
return true;
}
// backtrack
board[row][col] = 0;
}
}

false
}
65 changes: 48 additions & 17 deletions styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
box-sizing: border-box;
}

body {
display: flex;
flex-direction: column;
margin: auto;
min-height: 100vh;
background-color: #131516 !important;
}

h1 {
text-align: center;
color: #dd4814;
margin-top: 3rem;
}

table {
Expand All @@ -17,17 +27,18 @@ td.sudoku-case[data-value='0'] {
}

td {
border: 1px solid black;
border: 1px solid #8d8272;
width: 40px;
height: 40px;
font-size: 24px;
font-weight: bold;
background-color: #fff;
background-color: #191b1c;
color: #eee;
cursor: pointer;
}

td:hover {
background-color: #eee;
background-color: #2c2f30;
}

.button-container {
Expand All @@ -40,9 +51,10 @@ td:hover {
padding: 10px;
font-size: 20px;
font-weight: bold;
color: white;
color: #eee;
border: none;
cursor: pointer;
border-radius: 4px;
}

.easy-button {
Expand All @@ -64,9 +76,10 @@ td:hover {
font-size: 20px;
font-weight: bold;
background-color: #4caf50;
color: white;
color: #eee;
border: none;
cursor: pointer;
border-radius: 4px;
}

.generate-button:hover {
Expand All @@ -83,38 +96,56 @@ td:hover {
opacity: 0.8;
}

footer {
color: #eee;
padding: 20px;
text-align: center;
font-size: 14px;
margin-top: auto;
background-color: #191b1c !important;
}

footer a {
color: #dd4814;
text-decoration: none;
}

footer a:hover {
text-decoration: underline;
}

tr:nth-child(3n + 1) td:nth-child(3n + 1) {
border-top: 3px solid black;
border-left: 3px solid black;
border-top: 3px solid #8d8272;
border-left: 3px solid #8d8272;
}

tr:nth-child(3n + 1) td:nth-child(3n + 2) {
border-top: 3px solid black;
border-top: 3px solid #8d8272;
}

tr:nth-child(3n + 1) td:nth-child(3n + 3) {
border-top: 3px solid black;
border-right: 3px solid black;
border-top: 3px solid #8d8272;
border-right: 3px solid #8d8272;
}

tr:nth-child(3n + 2) td:nth-child(3n + 1) {
border-left: 3px solid black;
border-left: 3px solid #8d8272;
}

tr:nth-child(3n + 2) td:nth-child(3n + 3) {
border-right: 3px solid black;
border-right: 3px solid #8d8272;
}

tr:nth-child(3n + 3) td:nth-child(3n + 1) {
border-bottom: 3px solid black;
border-left: 3px solid black;
border-bottom: 3px solid #8d8272;
border-left: 3px solid #8d8272;
}

tr:nth-child(3n + 3) td:nth-child(3n + 2) {
border-bottom: 3px solid black;
border-bottom: 3px solid #8d8272;
}

tr:nth-child(3n + 3) td:nth-child(3n + 3) {
border-bottom: 3px solid black;
border-right: 3px solid black;
border-bottom: 3px solid #8d8272;
border-right: 3px solid #8d8272;
}
4 changes: 4 additions & 0 deletions templates/layout/footer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<footer>
<p>Made in rust with Actix.</p>
<p>Copyright &copy; <a href="https://github.com/Jayllyz">Jayllyz</a></p>
</footer>
3 changes: 2 additions & 1 deletion templates/pages/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<title>{{ title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" media="screen" href="/static/styles/main.css" />
<link rel="stylesheet" type="text/css" href="/static/styles/main.css" />
</head>
<body>
<main>
Expand All @@ -31,5 +31,6 @@ <h1>{{ title }}</h1>
</form>
</div>
</main>
{% include "layout/footer.html" %}
</body>
</html>

0 comments on commit e25444a

Please sign in to comment.