100-days-of-rust/Week-03/Day-21_Random-Maze-Generator/day21/src/lib.rs
2024-08-15 21:45:17 +02:00

107 lines
3.2 KiB
Rust

use std::time::{SystemTime, UNIX_EPOCH};
pub fn draw_maze(height: usize, width: usize) -> String {
let mut maze = vec![vec![(false, false, false); width]; height];
let mut rng = Rng::new();
bfs_make_maze(
(
rng.random_number(0, height as u128) as usize,
rng.random_number(0, width as u128) as usize,
),
&mut maze,
&mut rng,
);
let mut res = "+---".repeat(width) + "+";
for c in 0..height {
res = format!("{}\n|", res);
for r in maze.get(c).unwrap() {
res = format!("{} ", res);
if r.1 {
res = format!("{} ", res);
} else {
res = format!("{}|", res);
}
}
res = format!("{}\n+", res);
for r in maze.get(c).unwrap() {
if r.0 {
res = format!("{} +", res);
} else {
res = format!("{}---+", res);
}
}
}
res
}
fn bfs_make_maze(position: (usize, usize), maze: &mut Vec<Vec<(bool, bool, bool)>>, rng: &mut Rng) {
maze[position.0][position.1].2 = true;
let mut nums = [0, 1, 2, 3];
for i in (0..4).rev() {
let rand_index = rng.random_number(0, i + 1);
nums.swap(rand_index as usize, i as usize);
}
for num in nums {
if num == 0 && position.1 + 1 < maze[0].len() && !maze[position.0][position.1 + 1].2 {
let mut new_position = position;
new_position.1 += 1;
maze[position.0][position.1].1 = true;
bfs_make_maze(new_position, maze, rng);
}
if num == 1 && position.1 > 0 && !maze[position.0][position.1 - 1].2 {
let mut new_position = position;
new_position.1 -= 1;
maze[new_position.0][new_position.1].1 = true;
bfs_make_maze(new_position, maze, rng);
}
if num == 2 && position.0 + 1 < maze.len() && !maze[position.0 + 1][position.1].2 {
let mut new_position = position;
new_position.0 += 1;
maze[position.0][position.1].0 = true;
bfs_make_maze(new_position, maze, rng);
}
if num == 3 && position.0 > 0 && !maze[position.0 - 1][position.1].2 {
let mut new_position = position;
new_position.0 -= 1;
maze[new_position.0][new_position.1].0 = true;
bfs_make_maze(new_position, maze, rng);
}
}
}
pub struct Rng {
seed: u128,
}
impl Rng {
pub fn new() -> Rng {
let time_since_epoch = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Error in getting time")
.as_millis();
Rng {
seed: time_since_epoch,
}
}
fn linear_congruent_generator(&mut self, a: u128, c: u128, m: u128) -> u128 {
let result = (a * self.seed + c) % m;
self.seed = result;
result
}
pub fn random_number(&mut self, from: u128, to: u128) -> u128 {
let random_number = self.linear_congruent_generator(1103515245, 12345, 2u128.pow(31));
(random_number % (to - from)) + from
}
}
impl Default for Rng {
fn default() -> Self {
Self::new()
}
}