Browse code

Add implementation

Robert Cranston authored on 20/05/2025 23:55:27
Showing 4 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+/maze
... ...
@@ -2,3 +2,5 @@ CXXFLAGS += -std=c++11
2 2
 CXXFLAGS += -Wall -Wextra -Wpedantic
3 3
 CXXFLAGS += -Wconversion
4 4
 # CXXFLAGS += -Wsign-conversion
5
+
6
+maze:
... ...
@@ -2,8 +2,49 @@
2 2
 
3 3
 A simple C++11 command line maze generator.
4 4
 
5
+Features:
6
+
7
+-   Printing
8
+-   Algorithms
9
+    -   Hunt And Kill
10
+        -   Handles only odd-sized mazes
11
+        -   Random with seed
12
+        -   Fairly naive
13
+
5 14
 [`cxx-maze`]: https://git.rcrnstn.net/rcrnstn/cxx-maze
6 15
 
16
+## Example
17
+
18
+```
19
+$ make
20
+$ ./maze
21
+██  ██████████████████████████████████████████████████████████████████████████
22
+██  ██                          ██              ██      ██          ██      ██
23
+██  ██  ██  ██████████████  ██████  ██  ██████  ██  ██  ██  ██  ██  ██  ██  ██
24
+██      ██  ██          ██  ██      ██      ██      ██      ██  ██  ██  ██  ██
25
+██  ██████  ██  ██  ██  ██████  ██████  ██  ██  ██████████████  ██  ██  ██  ██
26
+██      ██      ██  ██      ██      ██  ██  ██          ██      ██      ██  ██
27
+██  ██  ██████████  ██  ██  ██████  ██  ██  ██████████████  ██████████  ██  ██
28
+██  ██      ██      ██  ██      ██  ██  ██              ██  ██      ██  ██  ██
29
+██  ██████  ██  ██████████████  ██  ██  ██████████████  ██████  ██  ██████  ██
30
+██  ██      ██              ██      ██  ██              ██      ██          ██
31
+██████  ██  ██████████████  ██████████████  ██  ██  ██████  ██████████████████
32
+██      ██  ██      ██      ██              ██  ██  ██  ██                  ██
33
+██  ██████  ██  ██████  ██  ██  ██████████████  ██  ██  ██  ██  ██████████  ██
34
+██  ██      ██          ██  ██      ██          ██      ██  ██  ██      ██  ██
35
+██  ██  ██████████████  ██  ██████  ██████████████████  ██  ██  ██  ██████  ██
36
+██  ██  ██          ██  ██  ██      ██              ██  ██  ██  ██  ██      ██
37
+██  ██  ██  ██  ██  ██  ██  ██  ██████  ██  ██████  ██  ██  ██████  ██  ██████
38
+██  ██  ██  ██  ██  ██  ██  ██  ██      ██      ██  ██  ██      ██  ██      ██
39
+██  ██████  ██  ██  ██████  ██  ██  ██████████████  ██  ██████  ██  ██████  ██
40
+██  ██      ██  ██  ██      ██  ██  ██      ██      ██      ██  ██      ██  ██
41
+██  ██  ██████████  ██  ██████  ██  ██  ██  ██  ██████████  ██  ██████  ██  ██
42
+██      ██          ██      ██      ██  ██      ██          ██      ██      ██
43
+██████████████████████████████████████████████████████████████████████████  ██
44
+```
45
+
46
+<style>#example ~ pre { line-height: 1; }</style>
47
+
7 48
 ## License
8 49
 
9 50
 Licensed under the [ISC License][] unless otherwise noted, see the
10 51
new file mode 100644
... ...
@@ -0,0 +1,96 @@
1
+#include <cstdlib>
2
+#include <iostream>
3
+#include <vector>
4
+
5
+struct Maze
6
+{
7
+    enum Cell
8
+    {
9
+        INVALID,
10
+        WALL,
11
+        PATH,
12
+    };
13
+    Maze(int w, int h, Cell initial)
14
+    :
15
+        w{w},
16
+        h{h},
17
+        cells(w * h, initial)
18
+    {}
19
+    Cell & operator ()(int x, int y)
20
+    {
21
+        static auto invalid = INVALID; // Yes, naughty.
22
+        if (0 <= x && x < w && 0 <= y && y < h)
23
+            return cells[w * y + x];
24
+        return invalid;
25
+    }
26
+    void print() const
27
+    {
28
+        for (auto y = 0; y < h; ++y, std::cout << '\n')
29
+        for (auto x = 0; x < w; ++x)
30
+            std::cout << (cells[w * y + x] == PATH ? "  " : "██");
31
+    }
32
+    int w;
33
+    int h;
34
+    std::vector<Cell> cells;
35
+};
36
+
37
+Maze hunt_and_kill(int w, int h, unsigned seed)
38
+{
39
+    auto maze = Maze(w, h, Maze::WALL);
40
+    std::srand(seed);
41
+    // Entrance.
42
+    maze(1, 0) = maze(1, 1) = Maze::PATH;
43
+    // Interior.
44
+    auto cx = 1;
45
+    auto cy = 1;
46
+    auto done = false;
47
+    while (!done)
48
+    {
49
+        // Find number of neighbors.
50
+        auto n = 0;
51
+        for (auto ny = -2; ny <= 2; ny += 2)
52
+        for (auto nx = -2; nx <= 2; nx += 2)
53
+            if (!nx != !ny)
54
+            if (maze(cx+nx, cy+ny) == Maze::WALL)
55
+                ++n;
56
+        // If we have neighbors, carve path to random one.
57
+        if (n != 0)
58
+        {
59
+            n = std::rand() % n;
60
+            for (auto ny = -2; ny <= 2; ny += 2)
61
+            for (auto nx = -2; nx <= 2; nx += 2)
62
+                if (!nx != !ny)
63
+                if (maze(cx+nx, cy+ny) == Maze::WALL && n-- == 0)
64
+                {
65
+                    maze(cx+nx/2, cy+ny/2) = maze(cx+nx, cy+ny) = Maze::PATH;
66
+                    cx = cx+nx;
67
+                    cy = cy+ny;
68
+                }
69
+            continue;
70
+        }
71
+        // No neighbors, done unless there's an uncarved cell to restart at.
72
+        done = true;
73
+        for (auto ry = 1; ry < h && done; ry += 2)
74
+        for (auto rx = 1; rx < w && done; rx += 2)
75
+            if (maze(rx, ry) == Maze::WALL)
76
+                for (auto ny = -2; ny <= 2 && done; ny += 2)
77
+                for (auto nx = -2; nx <= 2 && done; nx += 2)
78
+                    if (!nx != !ny)
79
+                    if (maze(rx+nx, ry+ny) == Maze::PATH)
80
+                    {
81
+                        cx = rx+nx;
82
+                        cy = ry+ny;
83
+                        done = false;
84
+                    }
85
+    }
86
+    // Exit.
87
+    maze(w-2, h-1) = Maze::PATH;
88
+    return maze;
89
+}
90
+
91
+int main()
92
+{
93
+    auto seed = 0;
94
+    auto maze = hunt_and_kill(80/2-1, 24-1, seed);
95
+    maze.print();
96
+}