Maze creation in C#
A small maze generator for use in .net.
I am currently in the process of learning how to code 3D graphics in XNA 4.0. It’s a lot of fun – and I’ve gotten pretty far with just boxes covered by different textures. However I thought that it would be fun to have a small mazegame – where you’re running around as a bewildered labrat inside the maze. For that I would need to have a random maze generated each time.
So I Googled around, found some tips, and coded a mazegenerator.
After that I took the time to comment the code and wrap it up. So if you don’t care about the inner workings, you can just add a reference to my DLL and get mazes like this:
//get a MazeCreator ready to make 9x9 mazes that start at 1,1 MazeCreator creator = new MazeCreator(9, 9, new Point(1, 1)); byte[,] maze1 = creator.CreateMaze(); byte[,] maze2 = creator.CreateMaze(); byte[,] maze3 = creator.CreateMaze();
Update - thanks to the anonymous commenter below, you can now get the point in the maze furthest from the starting point:)
If you want to know where the position in the maze that is furthest from the starting point is, you can ask the MazeCreator object after you have created the maze:
//get a MazeCreator ready to make 9x9 mazes that start at 1,1 MazeCreator creator = new MazeCreator(9, 9, new Point(1, 1)); byte[,] maze1 = creator.CreateMaze(); Point furthestPosition = creator.FurthestPoint;
Basics of maze creation
The basic algorithm of creating a maze is as follows (pseudocode)
Start at a valid starting point in the maze - then: as long as there are still tiles to try { excavate the square we are on get all valid neighbors for the curent tile if there are any interesting looking neighbors to branch off to(*) { remember the current tile, by putting it in a list of potential branch-offs (stack) move on to a random of the neighboring tiles } else { we are at a dead-end toss this tile out, thereby returning to the previous tile in the stack } }
(*) and they are valid for whatever rules you have for your maze
(Longer writeup here: http://en.wikipedia.org/wiki/Maze_generation_algorithm)
Take a look at the animated gifs on this page, and try to follow along with the steps. I have chosen to use complete tiles for walls, but you could as well have neighboring tiles with a thin wall between in your own implementation.
The MazeCreator also has a MazeChanged event that signals every time a new tile has been excavated. This makes it easy to monitor the progress, either by inspecting the Maze property (byte[,]) or by calling the maze’s ToString representation:
LEGEND
X = wall
. = tile which still needs to be checked
0 = tile being excavated
* = the point furthest from the beginning
[space] = tile which is done (no more neighbors to check)
The animated gif above was created by using gOODiDEA’s NGif component – here you can see that I subscribe to the event MazeChanged and add a new Bitmap to the AnimatedGifEncoder for every new tile excavated in the maze:
//create mazes of sizes 11 through 22 for (int size = 10; size < 12; size ++ ) { //make a new mazecreator _creator = new MazeCreator(size, size, new Point(1, 1)); //figure out a savepath with a logical name containing width and height string gifPath = string.Format("c:\\maze_{0:00}x{0:00}.gif", size); //output status to console Console.WriteLine("Creating " + gifPath); //subscribe to the mazechanged event //to get a fresh bitmap on every new tile excavated _creator.MazeChanged += new EventHandler<PointEventArgs>(CreatorMazeChanged); //create the animated GIF _gifEncoder = new AnimatedGifEncoder(); _gifEncoder.SetDelay(100); //in milliseconds _gifEncoder.SetRepeat(0); //yes - repeat (-1 is NO) _gifEncoder.SetQuality(1); //for generating palette - 1 is best, but slowest _gifEncoder.Start(gifPath); //where to save the maze var maze = _creator.CreateMaze(); //create a maze _gifEncoder.Finish(); //end //show the animated gif Process.Start(gifPath); Console.WriteLine("Furthest point: " + _creator.FurthestPoint); }
Class diagram and code
Here you can download the project which displays how to use the MazeGenerator, and see the public members of the MazeCreator. If you only want random mazes and don’t care for anything else, just grab the zipped DLL.
Just the MazeCreator.cs (right-click and choose “Save as…” to save)
More sample mazes
11 x 11 13 x 13 15 x 15
Tags: c#, Maze creation algorithm
May 20th, 2013 at 14:46
Ok, the start tile is at 1,1 - but how do you know where the end tile is?
May 20th, 2013 at 15:17
That's up to you to decide
If you want to, you could remove an edge tile on the opposite side and call it the exit.
You could also just choose any arbitrary tile inside the maze, which isn't a wall.
/Jake
May 29th, 2013 at 15:49
Well you would normally want the dead end that is farther away from the start. Since the algorithm knows when it's at a dead end, maybe it could store the distance travelled in each case.
I'll check the source anyway. Thanks.
May 30th, 2013 at 07:49
That's not a bad approach, but it has the weakness that the dead end at the point with the longest path to it, might be on the middle of the board. If that is what you want, then I could definitely implement that, but I think of a maze as a "walk-in-find-the-way-out" challenge, so for me the target would logically be an "exit" out of the maze. I am guessing the objective in the game you are making is "find-the-hidden-place-in-here" - am I right?
Kind regards - Jakob
May 30th, 2013 at 10:52
Good points there. I'll consider that. My main purpose is to force the player to walk through most of the maze, so that maps take a while to complete.
Cheers
May 31st, 2013 at 22:48
I've updated the code so you can get the furthest point from the start from the MazeCreator object after each time you've created a maze
June 10th, 2013 at 18:26
Awesome! Thank you
June 10th, 2013 at 18:31
You're most welcome - thanks for the suggestion!
March 10th, 2014 at 13:31
Great!
Its posible extract to .txt
W = Wall
E = Excaved
S = Start
F = furtest point
March 10th, 2014 at 14:30
I am downloading Code with sample project and rewrite, run perfect.
Thank you!
March 10th, 2014 at 15:23
Great to hear it was useful for you!
You're welcome
March 10th, 2014 at 15:27
Yup - I'll add some code to dump the maze to a txt file during this week
Thank you for the suggestion!
Kind regards - Jakob
March 12th, 2014 at 10:59
Hi Milor
If you look at the MazeCreator.ToString() method, you can see that it does almost what you want: convert the maze's state to a string.
If you change the output to what you want for the different values, you should have a multiline String representation of your maze, which you can then save using File.WriteAllText.
Kind regards - Jakob
June 20th, 2014 at 01:55
Excelente, funciona como lo necesitaba... muchas gracias
February 5th, 2017 at 01:25
Thanks for this example. I'm teaching my nephew how to program with unity and this will really help. I converted it to run in unity obviously but it was such an easy conversion and does precisely what I want. Excellent work
February 5th, 2017 at 11:58
Very glad to hear it was of use to you 👍👍😊
July 30th, 2017 at 08:02
That's more than great!
Thank you very much! Hope the information will be useful for your portal readers!
I'm very excited because I’m doing c# online course now and I’d tried your tutorial as well and I managed to do it)
Have a good day!
July 31st, 2017 at 20:17
Great to hear you found it useful
Cheers!