|
1 | 1 | // Maze generator in Rust.
|
2 |
| -// 2014-01-11 |
| 2 | +// 2014-01-11 <> 20151208 |
3 | 3 | // Joe Wingbermuehle
|
4 | 4 |
|
5 |
| -use std::rand; |
| 5 | +extern crate rand; |
| 6 | + |
| 7 | +use rand::Rng; |
| 8 | +use std::vec::Vec; |
| 9 | + |
| 10 | +enum Element { |
| 11 | + Wall, |
| 12 | + Passage, |
| 13 | +} |
6 | 14 |
|
7 | 15 | struct Maze {
|
8 |
| - width: int, |
9 |
| - height: int, |
10 |
| - data: ~[bool] |
| 16 | + width: usize, |
| 17 | + height: usize, |
| 18 | + data: Vec<Element>, |
11 | 19 | }
|
12 | 20 |
|
13 |
| -// Create an empty maze structure. |
14 |
| -fn init_maze(width: int, height: int) -> ~Maze { |
15 |
| - let mut maze = ~Maze { |
16 |
| - width: width, |
17 |
| - height: height, |
18 |
| - data: ~[] |
19 |
| - }; |
20 |
| - for y in range(0, height) { |
21 |
| - for x in range(0, width) { |
22 |
| - let value = |
23 |
| - if y == 0 || y == height - 1 { |
24 |
| - false |
25 |
| - } else if x == 0 || x == width - 1 { |
26 |
| - false |
27 |
| - } else { |
28 |
| - true |
29 |
| - }; |
30 |
| - maze.data.push(value); |
| 21 | +impl Maze { |
| 22 | + |
| 23 | + // Create an empty maze structure. |
| 24 | + fn init(width: usize, height: usize) -> Maze { |
| 25 | + let mut maze = Maze { |
| 26 | + width: width, |
| 27 | + height: height, |
| 28 | + data: Vec::new(), |
| 29 | + }; |
| 30 | + for y in 0 .. height { |
| 31 | + for x in 0 .. width { |
| 32 | + let value = |
| 33 | + if y == 0 || y == height - 1 { |
| 34 | + Element::Passage |
| 35 | + } else if x == 0 || x == width - 1 { |
| 36 | + Element::Passage |
| 37 | + } else { |
| 38 | + Element::Wall |
| 39 | + }; |
| 40 | + maze.data.push(value); |
| 41 | + } |
31 | 42 | }
|
| 43 | + maze |
32 | 44 | }
|
33 |
| - maze |
34 |
| -} |
35 | 45 |
|
36 |
| -// Show the maze. |
37 |
| -fn show_maze(maze: &Maze) { |
38 |
| - for y in range(0, maze.height) { |
39 |
| - for x in range(0, maze.width) { |
40 |
| - if maze.data[y * maze.width + x] { |
41 |
| - print("[]") |
42 |
| - } else { |
43 |
| - print(" ") |
| 46 | + // Show the maze. |
| 47 | + fn show(&self) { |
| 48 | + for y in 0 .. self.height { |
| 49 | + for x in 0 .. self.width { |
| 50 | + match self.data[y * self.width + x] { |
| 51 | + Element::Wall => print!("[]"), |
| 52 | + Element::Passage => print!(" "), |
| 53 | + } |
44 | 54 | }
|
| 55 | + println!("") |
45 | 56 | }
|
46 |
| - println("") |
47 | 57 | }
|
48 |
| -} |
49 | 58 |
|
50 |
| -// Carve the maze starting at x, y. |
51 |
| -fn carve_maze<R: std::rand::Rng>(rng: &mut R, x: int, y: int, maze: &mut Maze) { |
52 |
| - let xdirs = [ 1, -1, 0, 0 ]; |
53 |
| - let ydirs = [ 0, 0, 1, -1 ]; |
54 |
| - maze.data[y * maze.width + x] = false; |
55 |
| - let d = rng.gen_integer_range(0, 4); |
56 |
| - for i in range(0, 4) { |
57 |
| - let dx = xdirs[(d + i) % 4]; |
58 |
| - let dy = ydirs[(d + i) % 4]; |
59 |
| - let x2 = x + dx; |
60 |
| - let y2 = y + dy; |
61 |
| - let nx = x2 + dx; |
62 |
| - let ny = y2 + dy; |
63 |
| - if maze.data[y2 * maze.width + x2] && |
64 |
| - maze.data[ny * maze.width + nx] { |
65 |
| - maze.data[y2 * maze.width + x2] = false; |
66 |
| - carve_maze(rng, nx, ny, maze); |
| 59 | + fn is_wall(&self, x: isize, y: isize) -> bool { |
| 60 | + let (ux, uy) = (x as usize, y as usize); |
| 61 | + match self.data[(uy * self.width + ux) as usize] { |
| 62 | + Element::Wall => true, |
| 63 | + Element::Passage => false, |
67 | 64 | }
|
68 | 65 | }
|
69 | 66 |
|
70 |
| -} |
| 67 | + // Carve the maze starting at x, y. |
| 68 | + fn carve<R: rand::Rng>(&mut self, rng: &mut R, x: usize, y: usize) { |
| 69 | + let xdirs = [ 1, -1, 0, 0 ]; |
| 70 | + let ydirs = [ 0, 0, 1, -1 ]; |
| 71 | + self.data[y * self.width + x] = Element::Passage; |
| 72 | + let d = rng.gen::<usize>() % 4; |
| 73 | + for i in 0 .. 4 { |
| 74 | + let dx: isize = xdirs[(d + i) % 4]; |
| 75 | + let dy: isize = ydirs[(d + i) % 4]; |
| 76 | + let x2 = (x as isize) + dx; |
| 77 | + let y2 = (y as isize) + dy; |
| 78 | + if self.is_wall(x2, y2) { |
| 79 | + let nx = x2 + dx; |
| 80 | + let ny = y2 + dy; |
| 81 | + if self.is_wall(nx, ny) { |
| 82 | + let index = (y2 as usize) * self.width + (x2 as usize); |
| 83 | + self.data[index] = Element::Passage; |
| 84 | + self.carve(rng, nx as usize, ny as usize); |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + } |
| 90 | + |
| 91 | + // Generate a maze. |
| 92 | + fn generate(width: usize, height: usize) -> Maze { |
| 93 | + let mut maze = Maze::init(width, height); |
| 94 | + let mut rng = rand::thread_rng(); |
| 95 | + maze.carve(&mut rng, 2, 2); |
| 96 | + maze.data[1 * width + 2] = Element::Passage; |
| 97 | + maze.data[(height - 2) * width + (width - 3)] = Element::Passage; |
| 98 | + maze |
| 99 | + } |
71 | 100 |
|
72 |
| -// Generate a maze. |
73 |
| -fn generate_maze(width: int, height: int) -> ~Maze { |
74 |
| - let mut maze = init_maze(width, height); |
75 |
| - let rng = rand::task_rng(); |
76 |
| - carve_maze(rng, 2, 2, maze); |
77 |
| - maze.data[1 * width + 2] = false; |
78 |
| - maze.data[(height - 2) * width + (width - 3)] = false; |
79 |
| - maze |
80 | 101 | }
|
81 | 102 |
|
82 | 103 | fn main() {
|
83 | 104 | let width = 39; // Maze width; must be odd.
|
84 | 105 | let height = 23; // Maze height; must be odd.
|
85 |
| - let maze = generate_maze(width, height); |
86 |
| - show_maze(maze); |
| 106 | + let maze = Maze::generate(width, height); |
| 107 | + maze.show(); |
87 | 108 | }
|
0 commit comments