Skip to main content
GameDev.net gamedev.net
📌 Pinned 🔒 Locked

You may now post code

Started by JWalsh Aug 4, 2007 at 12:37 AM 40 replies 29.5k views
Original Post
JWalsh
JWalsh
With the project half way over, feel free to begin uploading source examples or links to zip files. For people still trying to work this out, feel free to look over other people's code, that's a natural part of learning correct design and programming. But be aware, not everyone does things "correctly" and there is, strictly speaking, no "right" or "wrong" way to implement something. You may find you were doing something completely different than someone else. Don't feel the need to scratch your work and start over simply because someone else took a different approach. Perhaps your approach is just as valid. Evaluate the differences critically and then decide if you made a mistake, or simply did something differently. Cheers!
Gyna
Gyna
Hey! I think I took a bit of a different route in the way the map is stored.

I have it like this:

11111
10101
11111

Where the 1's are walls and the 0's are free spaces. The outer walls enclosing the whole maze are also stored in this array.

I think doing it like this complicated things a bit when trying to assign two rooms to a wall and when calculating the wall position in the array to knock down a wall. But see for yourself, all comments and critique is welcome!

Main.cs - includes main loop, introduction, and input/output:

using System;namespace Workshop_Project_1{    class Program    {        static void Main(string[] args)        {            bool quit = false;            ConsoleKeyInfo key;            int width, height;            Console.Clear();            Console.Title = "Perfect Maze Generator";            Console.WriteLine("\n\nWelcome to the perfect maze generator!\n");            while (!quit)            {                do                {                    Console.WriteLine("\nWidth (2-50): ");                    int.TryParse(Console.ReadLine(), out width);                    if (width < 2 || width > 50) Console.WriteLine("Invalid input, try again\n");                } while (width < 2 || width > 50);                do                {                    Console.WriteLine("\nHeight (2-50): ");                    Int32.TryParse(Console.ReadLine(), out height);                    if (height < 2 || height > 50) Console.WriteLine("Invalid input, try again\n");                } while (height < 2 || height > 50);                Maze m = new Maze(width, height);                Console.SetWindowSize(width < 40 ? 80 : width * 2 + 1, height < 10 ? 21 : (height < 30 ? height*2+1 + 20 : 79));                m.knockdown();                m.print();                Console.WriteLine("\nContinue? (y/n)");                do                {                    key = Console.ReadKey(true);                } while (key.KeyChar != 'y' && key.KeyChar != 'n');                if (key.KeyChar != 'y') quit = true;            }        }    }}


Maze.cs - stores all data about maze ( maze map, number of walls, rooms, room sets, wall sequence; does all logic, including making random entrance/exit points, randomizing the wall sequence, and finally knocking down the walls and printing them to the console.

using System;namespace Workshop_Project_1{    class Maze    {        private int[,] arr;        private int[] wallseq;        private int height, width, rooms, walls;        private bool[,] sets;        private Random rand;        public struct assignedrooms        {            public int room1;            public int room2;        }        public assignedrooms[] ar;        public Maze(int w, int h)        {            int tmp1, tmp2;            height = h*2+1;            width = w*2+1;            rooms = w * h;            walls = rooms * 2 - h - w;            wallseq = new int[walls];            ar = new assignedrooms[walls];            sets = new bool[rooms, rooms];            arr = new int[width, height];            rand = new Random();            // init map            for (int j = 0; j < height; j++)            {                if (j % 2 == 0) for (int i = 0; i < width; i++)                    {                        arr[i, j] = 1;                    }                else for (int i = 0; i < width; i++)                    {                        if (i % 2 == 0) arr[i, j] = 1;                    }            }            //init start + end point            arr[(rand.Next(rooms) % w) * 2 + 1, (rand.Next(rooms) / w) * 2 + 1] = 2;            arr[(rand.Next(rooms) % w) * 2 + 1, (rand.Next(rooms) / w) * 2 + 1] = 2;            // init room sets            // [set, rooms in this set]            for (int i = 0; i < rooms; i++) sets[i, i] = true;            // init and randomize wall sequence            for (int i = 0; i < walls; i++) wallseq = i;            //debug            //foreach (int i in wallseq) Console.Write(i + " ");            //Console.Write("\n");            for (int i = 0; i < walls; i++)            {                tmp1 = rand.Next(walls);                tmp2 = wallseq;                wallseq = wallseq[tmp1];                wallseq[tmp1] = tmp2;            }            //debug            //foreach (int i in wallseq) Console.Write(i + " ");            //Console.Write("\n");            //init assigned rooms            int tmp=0, row=0;            for (int i = 0; i < walls; ) {                tmp=0;                while (tmp < w - 1)                {                    ar.room1 = tmp+row*w;                    ar.room2 = tmp+row*w + 1;                    i++;                    tmp++;                }                tmp = 0;                while (tmp < w && i < walls)                {                    ar.room1 = tmp + row * w;                    ar.room2 = tmp + (row + 1) * w;                    i++;                    tmp++;                }                row++;            }            //for (int i=0; i < walls; i++)            //{            //    Console.WriteLine("Wall {0} : Rooms {1} and {2}", i, ar.room1, ar.room2);            //}        }        public void print()        {            for (int j = 0; j < height; j++)            {                for (int i = 0; i < width; i++)                {                    if (arr[i, j] == 0) Console.Write(" ");                    else if (arr[i, j] == 2) Console.Write("x");                    else if (j % 2 == 0) Console.Write("-");                    else Console.Write('|');                }                Console.Write("\n");            }            //debug            //for (int j = 0; j < height; j++)            //{            //    for (int i = 0; i < width; i++)            //    {            //       Console.Write(arr[i,j]);            //    }            //    Console.Write("\n");            //}        }        public void knockdown() {            for (int i=0; i< walls; i++)            {                // if both rooms in same set -> continue                int j, k;                for (j = 0; j < walls; j++) if (sets[j, ar[wallseq].room1] == true) break;                // debug Console.WriteLine("room 1 from wall number {0} in wallsequence is in set {1}", i, j);                if (sets[j, ar[wallseq].room2] == true) continue;                // else knock down wall, move all rooms from room 2's set to room 1's set                // combine sets, empty set 2                for (k = 0; k < walls; k++) if (sets[k, ar[wallseq].room2] == true) break;                for (int h = 0; h < rooms; h++)                {                    sets[j, h] = sets[k, h] | sets[j, h];                    sets[k, h] = false;                }                // modify map (arr)                int x = 2;                int y = 1;                int row = 0;                int counter=((width-1)/2)-1;                while (true)                {                    if (wallseq - counter >= 0)                    {                        counter += ((width-1)/2);                        if (wallseq - counter >= 0)                        {                            row++;                            counter += (((width-1)/2) - 1);                        }                        else                        {                            x = (wallseq - (counter - ((width-1)/2))) * 2 + 1;                            y = row * 2 + 2;                            break;                        }                    }                    else                    {                        x = (wallseq - (counter - (((width-1)/2) - 1)))*2 + 2;                        y = row * 2 + 1;                        break;                    }                }                arr[x, y] = 0;                //debug print();             }        }    }}


Again, feel free to add critique / comments!

Edit: One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside? I'm thinking of C++ here, with declaring inside:

Class bla {
public:
void hello();
};

void bla::hello() {
}

It makes the classes so much tidier and easier to see the big picture imo.

Edit 2: On second though, maybe some more explanation of my Maze.cs is in order. I use two different widths and heights. The first, which is passed to the constructor of Maze is the number of cells horizontally and vertically. In the Maze class, width and height refer to the number of spaces in the map array - which is 2*c+1 ( c is the number of cells).
One cell:

111
101
111

Two cells:

11111
10101
11111

etc.
EternalNewbie
EternalNewbie
Ok here's my version its not very pretty but it works. It needs alot of commenting and refactoring. Which I'll work on later.
The drawing code is particularly ugly I think. And I think roomset has functions that are never used.


using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            Console.Title = "Maze Program1";            Console.WriteLine("Welcome to maze generator");            string str;            do            {                Console.WriteLine("Please Specify maze width: ");                str = Console.ReadLine();                int width = 0;                while (!Int32.TryParse(str, out width) || width < 2 || width > 50)                {                    Console.WriteLine("Please specify a numeric value betweeen 2 and 50: ");                    str = Console.ReadLine();                };                Console.WriteLine("Please Specify maze height: ");                str = Console.ReadLine();                int height;                while (!Int32.TryParse(str, out height) || height < 2 || height > 50)                {                    Console.WriteLine("Please specify a numeric value betweeen 2 and 50: ");                    str = Console.ReadLine();                };                Maze myMaze = new Maze(width, height);                myMaze.GenerateMaze();            } while (PlayAgain());            Console.WriteLine("Press any key to continue");            Console.ReadKey();        }        static bool PlayAgain()        {            Console.Write("Play Again? ");            string str = Console.ReadLine();            if (str[0] == 'y' || str[0] == 'Y')            {                Console.Clear();                return true;            }            return false;        }    }        public struct Wall    {        public bool up;        public int room1, room2;    }    public class RoomSet    {        int[] rooms;        public RoomSet(params int[] arr)        {            rooms = new int[arr.Length];            for(int i = 0; i < arr.Length; i++)                rooms = arr;        }        public bool IsInSet(int room)        {            for (int i = 0; i < rooms.Length; i++)            {                if (room == rooms)                    return true;            }            return false;        }        public bool AddRoom(int room)        {            if (IsInSet(room))                return false;            int[] newRooms = new int[rooms.Length + 1];            for (int i = 0; i < rooms.Length; i++)                newRooms = rooms;            newRooms[rooms.Length] = room;            rooms = newRooms;            return true;        }        public bool AddRoomSet(RoomSet room)        {            int newSize = rooms.Length + room.rooms.Length;            int[] newRooms = new int[newSize];            int i = 0;            for (; i < rooms.Length; i++)                newRooms = rooms;            for (; i < newSize; i++)                newRooms = room.rooms[i - rooms.Length];            rooms = newRooms;            return true;        }        public void Clear()        {            rooms = new int[0];        }    }    public class Maze    {        private int width, height;        private int numRooms, numWalls;        private Wall[] walls;        private RoomSet[] roomSets;        private int[] wallPerm;        public Maze(int width, int height) {            this.width = width;            this.height = height;            numRooms = width * height;            numWalls = ((width - 1) * height) + ((height - 1) * width);            walls = new Wall[numWalls];            roomSets = new RoomSet[numRooms];        }        public void Init()        {            int i = 0;            // Init Walls            for (int x = 0; x < height; x++)            {                for (int y = 0; y < (width - 1); y++, i++)                {                    walls.up = true;                    walls.room1 = (x * width) + y;                    walls.room2 = walls.room1 + 1;                }            }            for (int x = 0; x < (height - 1); x++)            {                for (int y = 0; y < width; y++, i++)                {                    walls.up = true;                    walls.room1 = (x * width) + y;                    walls.room2 = walls.room1 + width;                }            }            //Init RoomSets            for (i = 0; i < numRooms; i++)                roomSets = new RoomSet(i);            //Create random wall Permutations            wallPerm = new int[numWalls];            for (i = 0; i < numWalls; i++)                wallPerm = i;            Random rand = new Random(); //Specify seed when debugging so we always get the same maze            int temp, randVal;            //Swap values in wallPerm randomly (i.e shuffle)            for (i = 0; i < numWalls; i++)            {                randVal = rand.Next(i);                temp = wallPerm[randVal];                wallPerm[randVal] = wallPerm;                wallPerm = temp;            }        }        int FindRoomSet(int room)        {            for (int i = 0; i < numRooms; i++)            {                if (roomSets.IsInSet(room))                    return i;            }            return -1;        }        public void GenerateMaze()        {            Init();            for (int i = 0; i < numWalls; i++)            {                int wallIndx = wallPerm;                int roomSet1 = FindRoomSet(walls[wallIndx].room1);                int roomSet2 = FindRoomSet(walls[wallIndx].room2);                if (roomSet1 != roomSet2)                {                    //Knock down wall                    walls[wallIndx].up = false;                    roomSets[roomSet1].AddRoomSet(roomSets[roomSet2]);                    roomSets[roomSet2].Clear();                }            }            DrawMaze();        }        void DrawMaze()        {            int mazeWidth = ((width * 2) + 1);             int mazeHeight = ((height * 2) + 1);            int mazeSize = mazeWidth * mazeHeight;            char[] maze = new char[mazeSize];            //Init to blank            for (int i = 0; i < mazeSize - mazeWidth; i++) {                maze = ' ';            }            //Draw Border            int lastline = mazeSize - mazeWidth;            for (int i = 0; i < mazeWidth; i++) {                maze = '#';                maze[lastline + i] = '#';            }            for (int i = 1; i < mazeHeight - 1; i++)            {                maze[i * mazeWidth] = '#';                maze[(i * mazeWidth) + mazeWidth - 1] = '#';            }            //Draw Vertical Walls            int mazeStart = mazeWidth + 1;            int a = mazeStart + 1;            int wallCnt = 0;            for (int y = 0; y < height; y++)            {                for (int x = 0; x < width - 1; x++, wallCnt++, a += 2)                {                    if (walls[wallCnt].up)                        maze[a] = '#';                    //else                 //Draw "doorways" for debugging                    //    maze[a] = '.';                }                a += mazeWidth + 3;            }            //Draw Horizontal Walls            a = mazeStart + mazeWidth;            for (int y = 0; y < height - 1; y++)            {                for (int x = 0; x < width; x++, wallCnt++, a += 2)                {                    if (walls[wallCnt].up)                        maze[a] = '#';                    //else                    //    maze[a] = '.';                     maze[a + 1] = '#';                }                a += mazeWidth + 1;            }            // Display Maze            a = 0;            for (int y = 0; y < mazeHeight; y++)            {                for (int x = 0; x < mazeWidth; x++, a++)                {                    Console.Write(maze[a]);                }                Console.WriteLine();            }        }    }}
Telastyn
Telastyn
Quote:

One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside?


No, not really. Methods should be short. Long ones should be an indicator that you might want to abstract something there. Though if you still find it cluttered, Edit > Outlining > Collapse to Definitions will make classes look like C++ headers, which you can then expand to edit or view details of at your whimsy.
GameDev Doctor
GameDev Doctor
This looks pretty nasty, but oh well...
using System;namespace ConsoleApplication1{    struct Wall : IComparable<Wall>    {        public int randint;        public int wall; //id        public bool destroyed;        public int CompareTo(Wall w)        {            return (this.randint.CompareTo(w.randint));        }    }    class Program    {        static Wall GetWallById(Wall[] walls, int id)        {            foreach (Wall w in walls)            {                if (w.wall == id)                    return (w);            }            throw new Exception("Fuckup");        }        static void destroy(int[,] rooms, int first, int second, int rows, int cols) //puts rooms in same set        {            for (int i = 0; i < rows; i++)            {                for (int j = 0; j < cols; j++)                {                    if(rooms[i,j] == first)                        rooms[i,j] = second; //All your base...                }            }        }        static int PromptIntInRange(string prompt, int lowbound, int highbound)        {            while (true)            {                Console.WriteLine(prompt + " ({0},{1})", lowbound, highbound);                try                {                    int input = Int32.Parse(Console.ReadLine());                    if (input >= lowbound && input <= highbound)                        return (input);                    Console.WriteLine("ur int wuz not in teh specified raeng LOL!!!\n");                }                catch (FormatException)                {                    Console.WriteLine("LOLZ nublet U shud try inpt a valid integr!!1one\n");                }            }        }        static void Main(string[] args)        {            string titlestring = "Welcome to Dale's maze generator!";            Console.WriteLine(titlestring + "\n");            Console.Title = titlestring;            const int maxwidth = 50;            const int maxheight = 50;            const int minsize = 2;            string inp; //input,used to prompt if the user wants to try again;            do            {                inp = "";                int rows, cols;                rows = PromptIntInRange("How many rows?", minsize, maxheight);                cols = PromptIntInRange("How many columns?", minsize, maxwidth);                if (rows + 1 > Console.WindowHeight) //If window isn't big enough, make it big enough or as big as possible if "big enough" can't fit                {                    if (rows + 1 > Console.LargestWindowHeight)                        Console.WindowHeight = Console.LargestWindowHeight; //only need an error message for width                    else                        Console.WindowHeight = rows + 1;            //if it isnt high enough, people can just scroll down :)                }                if (cols * 2 + 2 > Console.WindowWidth)                {                    if (cols * 2 + 2 > Console.LargestWindowWidth)                    {                        Console.WriteLine("Your screen is not wide enough to display a maze of this size");                        continue;                    }                    else                        Console.WindowWidth = cols*2+2;                }                int numwalls = cols * (rows - 1) + rows * (cols - 1);                int[,] rooms = new int[rows, cols];                Wall[] walls = new Wall[numwalls];                Random rand = new Random(); //                for (int i = 0; i < numwalls; i++)                {                    walls.wall = i;                    walls.destroyed = false;                    walls.randint = rand.Next(500);//                }                for (int i = 0; i < rows; i++)                {                    for (int j = 0; j < cols; j++)                    {                        rooms[i, j] = cols * i + j; //give each a unique number                    }                }                //Randomly permutate walls here (last thing to do, lazy)                Array.Sort(walls);                for (int i = 0; i < numwalls; i++) //each (Wall w in walls)                {                    /* Wall layout!!!                     * horizontal walls first, then vertical                     * so the first (cols-1)*rows are vertical | walls, the rest ( (rows-1)*cols ) are horizontal _                     */                    int wall = walls.wall;                    if (wall >= (cols - 1) * rows) // horizontal                    {                        int horizwall = wall - (cols - 1) * rows;                        int wallindex = horizwall % cols;                        int wallrow = horizwall / cols;                        if (rooms[wallrow, wallindex] != rooms[wallrow + 1, wallindex])                        {                            //BREAKIT!                            destroy(rooms, rooms[wallrow, wallindex], rooms[wallrow + 1, wallindex], rows, cols);                            walls.destroyed = true;                        }                    }                    else //vertical                    {                        int wallindex = wall % (cols - 1); // column index                        int wallrow = wall / (cols - 1); // row index                        if (rooms[wallrow, wallindex] != rooms[wallrow, wallindex + 1])                        {                            //BREAKIT!                            destroy(rooms, rooms[wallrow, wallindex], rooms[wallrow, wallindex + 1], rows, cols);                            walls.destroyed = true;                        }                    }                }                for (int i = 0; i < (cols * 2) + 1; i++) //Start drawing!                {                    Console.Write("_");                }                Console.WriteLine();                for (int r = 0; r < rows; r++)                {                    for (int c = 0; c < cols; c++)                    {                        if (c == 0) //always create a vertical wall on the first set (left wall)                        {                            Console.Write("|");                        }                        else        //check |                        {                            int wallindex = r * (cols - 1) + c - 1;                            if (GetWallById(walls, wallindex).destroyed)                                Console.Write("_");                            else                                Console.Write("|");                        }                        // check _ here                        if (r == rows - 1)                        {                            Console.Write("_"); //always create bottom walls on bottom row                        }                        else                        {                            int wallindex = (cols - 1) * rows + r * cols + c; //EWW                            if (GetWallById(walls, wallindex).destroyed)                                Console.Write(" ");                            else                                Console.Write("_");                        }                    }                    Console.WriteLine("|");                }                while (inp == "")                {                    Console.WriteLine("Do you want to generate another maze? (y/yes/n/no)");                    inp = Console.ReadLine();                    if (inp != "n" && inp != "y" && inp != "yes" && inp != "no")                        inp = "";                }            } while (inp == "yes" || inp == "y");        }    }}


I like this line
int wallindex = (cols - 1) * rows + r * cols + c; //EWW
I mean, why would you get your medical advice anywhere else?
Mike.Popoloski
Mike.Popoloski
Quote:
Original post by Telastyn
Quote:

One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside?


No, not really. Methods should be short. Long ones should be an indicator that you might want to abstract something there. Though if you still find it cluttered, Edit > Outlining > Collapse to Definitions will make classes look like C++ headers, which you can then expand to edit or view details of at your whimsy.


I like to put sections of each class into #region's in order to make it more readable and navigable. Usually, I have the regions broken down into variables, properties, events, constructor(s), methods, event handlers, and private helper methods.
Mike Popoloski | Journal | SlimDX
superpig
superpig
Quote:
Original post by Mike.Popoloski
Quote:
Original post by Telastyn
Quote:

One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside?


No, not really. Methods should be short. Long ones should be an indicator that you might want to abstract something there. Though if you still find it cluttered, Edit > Outlining > Collapse to Definitions will make classes look like C++ headers, which you can then expand to edit or view details of at your whimsy.


I like to put sections of each class into #region's in order to make it more readable and navigable. Usually, I have the regions broken down into variables, properties, events, constructor(s), methods, event handlers, and private helper methods.


That's a good plan. You might also want to further group things by functionality - one region for maze-building functions, one region for maze-drawing functions, etcetera.
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
foolios
foolios
I haven't gotten anywhere near finished. But since I am now stuck I will post what I have to see if what I've got so far is at least a decent start.
I can not figure out how I'm going to keep the drawing of the border of the maze separate and yet somehow control the difference between whether I am working with a border wall or one of the inner walls. This is more complicated than I thought at first.

Well, this is the first time I ever finally realized how to create a class and an object from that class with what I think is success. So, I've at least come that far.
I'm kinda disenchanted at the moment. After looking at some of the posted code so far, I realize I'm a long ways away from anywhere. But here goes anyways, I'm appreciative that I have learned a lot of new things.

The class that contains Main:

using System;using System.Collections.Generic;using System.Text;namespace MazeGen{    class MazeGenerator    {        static void Main(string[] args)        {            // Set the title of the Console Window            Console.Title = "Random Maze Generator";            // Write a greeting to the user            Console.WriteLine("Welcome to The C# Maze Generator Program");            // Enter a blank line            Console.WriteLine();            // Ask for dimensions once then ask if repetition is desired            do            {                // Code for getting response from user                MazeQuery();                // Check for actual input by user            } while (YesNo());        }        static void MazeQuery()        {            // Prompt for maze height            Console.Write("How many rows do you want the maze to have 2-50: ");            // Get rid of whitespace on each end of input received by user            string strHeight = Console.ReadLine().Trim();            // Create an integer variable to hold the converted string            int mazeHeight;            int mazeWidth;            // Try the casting of the string in strHeight to int and return it to the int variable            if (Int32.TryParse(strHeight, out mazeHeight))            {                // Variable mazeHeight contains the integer that was typed                // Check that the number chosen was between 2 and 50 inclusive                if (mazeHeight >= 2 && mazeHeight <= 50)                {                    // Code to continue when number is 2 - 50                    // Enter a blank line                    Console.WriteLine();                    // Prompt for maze width                    Console.Write("How many columns do you want the maze to have 2-50: ");                    // Get rid of whitespace on each end of input received by user                    string strWidth = Console.ReadLine().Trim();                    if (Int32.TryParse(strWidth, out mazeWidth))                    {                        MazeClass MazeObject = new MazeClass(mazeHeight, mazeWidth);                    }                }                else                {                    // The number is not 2 - 50                    Console.WriteLine("Please follow instructions.");                }            }            else            {                Console.Write("Not a valid number");            }        }        static Boolean YesNo()        {            Console.Write("Would you like to create another maze?");            string answer_y_n = Console.ReadLine();            if (answer_y_n == "t" || answer_y_n == "true" || answer_y_n == "y" || answer_y_n == "yes")            {                Console.WriteLine();                return true;            }            else            {                return false;            }        }    }}


The class that will be used to create maze objects:

using System;using MazeGen;/// <summary>/// Summary description for Class1/// </summary>namespace MazeGen{    public class MazeClass    {        // Each object will have it's own height and width        int mazeHeight;        int mazeWidth;        // Default constructor        public MazeClass()        {            //            // TODO: Add constructor logic here            //        }        // Custom constructor        public MazeClass(int h, int w)        {            // Assign parameters to object variables            mazeHeight = h;            mazeWidth = w;            // Write out the mazeHeight for testing purposes            Console.WriteLine("Rows high: " + mazeHeight);            Console.WriteLine("Rows wide: " + mazeWidth);            Console.WriteLine();        }    }}


Thanks in advance for your time in looking at it and for offering suggestions.
I rate users. Its just not having much impact as my rating is low...
Rule3o3
Rule3o3
First, JWalsh thank you so very much for this workshop. I have really been enjoying this workshop (and this first project was a lot of fun - Not sure if my wifes "enthusiasm" matched mine when I got my perfect maze to work, but shes a good sport!). And my apologies now for not being an active contributor to the workshop forums. My programming prior to this has been very rudimentary so I'm nowhere near comfortable enough yet to be on the advising side. And so far others have beaten me to needed questions and the tutors here helping are in a word, awesome.

For those tutoring here, you guys Rock! Your time and knowledge is greatly appreciated and is not wasted with me.

Now on to the maze code...

I have two primary classes, Project1 and PerfectMaze.
Project1 class has the main loop and the i/o methods.
PerfectMaze class contains all the maze generation and drawing code.
There are also two structures contained within the PerfectMaze class, one for the maze walls, the other for the maze rooms.

I've done a pass over of my programs structure and I'm getting happier with it, but where I feel I need a lot of improvement is in my naming of methods and fields. I'm going to spend some needed time on the MSDN naming conventions guide.

using System;using System.Collections.Generic;using System.Text;namespace Rule3o3{    class Project1    {        static void Main()        {            string Welcome_Message;            Welcome_Message = "Welcome to the C# Perfect Maze Generator";            bool run = true;            PerfectMaze MyPerfectMaze = new PerfectMaze();            int number_rows;            int number_columns;            Console.Title = Welcome_Message;            Console.WriteLine(Welcome_Message);            Console.WriteLine();            while (run)            {                Console.WriteLine();                Console.WriteLine("What dimensions do you want the maze to be?");                Console.Write("Enter the number of rows (min 2, max 50): ");                number_rows = GetMazeDimension();                Console.Write("Enter the number of columns (min 2, max 50): ");                number_columns = GetMazeDimension();                ResizeConsole(number_columns, number_rows);                MyPerfectMaze.GenerateMaze(number_rows, number_columns);                MyPerfectMaze.DrawMaze();                Console.WriteLine();                Console.WriteLine("Behold! Your perfect {0} by {1} maze.", number_rows, number_columns);                Console.WriteLine();                run = GetRepeatMazeFlag();            }        }        static int GetMazeDimension()        {            Boolean repeat = false;            string in_dimension;            int dimension = 0;            do            {                in_dimension = Console.ReadLine();                try                {                    dimension = Convert.ToInt32(in_dimension);                    if (dimension > 1 && dimension < 51)                    {                        repeat = false;                    }                    else                    {                        Console.Write("Invalid entry! Please enter a number between 2 and 50: ");                        repeat = true;                    }                }                catch                {                    Console.Write("Invalid entry! Please enter a number between 2 and 50: ");                    repeat = true;                }            } while (repeat);            return (dimension);        }        static bool GetRepeatMazeFlag()        {            bool repeat;            bool run = false;            string response;            Console.Write("Would you like to generate another maze? ");            do            {                Console.Write("Enter [y]es or [n]o: ");                response = Console.ReadLine();                response = response.ToLower();                if (response == "n" || response == "no" || response == "y" || response == "yes")                {                    if (response.StartsWith("n"))                    {                        run = false;                    }                    else if (response.StartsWith("y"))                    {                        run = true;                    }                    repeat = false;                }                else                {                    Console.Write("Incorrect response! ");                    repeat = true;                }            } while (repeat);            return (run);        }        static void ResizeConsole(int width, int height)        {            int display_width = Console.WindowWidth;            int display_height = Console.WindowHeight;            if (width > 39)            {                display_width = 2 * (width+1);                if (display_width > Console.LargestWindowWidth)                {                    display_width = Console.LargestWindowWidth;                }            }            if (height > 20)            {                display_height = 2 * (height+1);                if (display_height > Console.LargestWindowHeight)                {                    display_height = Console.LargestWindowHeight;                }                        }                        Console.SetWindowSize(display_width, display_height);        }    }    class PerfectMaze    {        //characters needed to draw maze        static string wall = "|";        static string floor = "_";        //maze dimensions        int number_rows = 0;        int number_columns = 0;        //Maze variables        MazeRoom[] MazeRooms;        MazeWall[] MazeWalls;        public void GenerateMaze(int number_rows, int number_columns)        {            this.number_rows = number_rows;            this.number_columns = number_columns;            int num_rooms;            num_rooms = number_rows * number_columns;            this.MazeRooms = InitializeMazeRooms(num_rooms);            this.MazeWalls = InitializeMazeWalls();            BuildMaze(ref this.MazeWalls, ref this.MazeRooms);                    }        public void DrawMaze()        {            //Drawing top row (ceiling)            Console.Write(" ");            for (int i = 0; i < (number_columns + number_columns - 1); i++)            {                Console.Write(floor);            }            Console.Write(" ");            Console.Write("\n");            Console.Write(wall);            //Drawing each room            foreach (MazeRoom mazeroom in this.MazeRooms)            {                if (mazeroom.SouthWall == true)                {                    Console.Write(floor);                }                else if (mazeroom.SouthWall == false)                {                    Console.Write(" ");                }                if (mazeroom.EastWall == true)                {                    Console.Write(wall);                }                else if (mazeroom.EastWall == false)                {                    Console.Write(floor);                }                //Border room in this case is the last row. Newline and then draw first wall                if (mazeroom.BorderRoom == true)                {                    Console.Write("\n");                    if (mazeroom.RoomNumber != this.MazeRooms.Length)                    {                        Console.Write(wall);                    }                }            }        }        private MazeRoom[] InitializeMazeRooms(int num_rooms)        {            MazeRoom[] MazeRooms = new MazeRoom[num_rooms];            int room_number = 0;            for (int i = 0; i < num_rooms; i++)            {                room_number = i + 1;                MazeRoom mazeroom = new MazeRoom();                mazeroom.RoomNumber = i + 1;                mazeroom.RoomCell = i;                mazeroom.NorthWall = true;                mazeroom.SouthWall = true;                mazeroom.WestWall = true;                mazeroom.EastWall = true;                //Sets border rooms (last column)                int border_check;                border_check = room_number % number_columns;                if (border_check == 0)                {                    mazeroom.BorderRoom = true;                }                else                {                    mazeroom.BorderRoom = false;                }                         MazeRooms = mazeroom;            }            return (MazeRooms);        }        private MazeWall[] InitializeMazeWalls()        {            int number_walls = 0;            number_walls = number_rows * (number_columns - 1) + number_columns * (number_rows - 1);            MazeWall[] MazeWalls = new MazeWall[number_walls];            int x = 1;            int y = 1;            int wallcount = 0;            int index = 0;            int[] Mazewalls_index = new int[number_walls];            int num_wall_inrow = 2 * number_columns - 1;            Mazewalls_index = RandomIndexArray(Mazewalls_index.Length);            //Even wall on a row == floor wall            //Odd wall on a row == side wall            //Rows            for (int i = 0; i < number_rows; i++)            {   //Columns                for (int j = 0; j < num_wall_inrow; j++)                {                    if (wallcount < Mazewalls_index.Length)                    {                        index = Mazewalls_index[wallcount];                    }                    MazeWall mazewall = new MazeWall();                    mazewall.WallNumber = wallcount;                    //Even wall => adjacent rooms are above and below                    //additionally, don't initialze floors on last row                    if (j % 2 == 0 && i != number_rows - 1)                    {                        mazewall.FloorWall = true;                        mazewall.SideWall = false;                        mazewall.AdjacentRoom1 = x;                        mazewall.AdjacentRoom2 = x + number_columns;                        x++;                        MazeWalls[index] = mazewall;                        wallcount++;                    }                    //Odd wall => adjacent rooms are to the left and right                    else if (j % 2 != 0)                    {                        mazewall.SideWall = true;                        mazewall.FloorWall = false;                        mazewall.AdjacentRoom1 = y;                        mazewall.AdjacentRoom2 = y + 1;                        y++;                        MazeWalls[index] = mazewall;                        wallcount++;                    }                      }                y++; //increment inside walls when at end of row            }             return (MazeWalls);        }        private void BuildMaze(ref MazeWall[] mazewalls, ref MazeRoom[] mazerooms)        {            int room1 = 0;            int room2 = 0;            int room1_cell = 0;            int room2_cell = 0;            MazeRoom mazeroom1 = new MazeRoom();            MazeRoom mazeroom2 = new MazeRoom();            foreach (MazeWall mazewall in mazewalls)            {                room1 = mazewall.AdjacentRoom1 - 1;                room2 = mazewall.AdjacentRoom2 - 1;                mazeroom1 = (MazeRoom)mazerooms[room1];                mazeroom2 = (MazeRoom)mazerooms[room2];                room1_cell = mazeroom1.RoomCell;                room2_cell = mazeroom2.RoomCell;                //Checking to see if mazerooms are already connected.                //If not, continue and knock down appropriate walls.                if (mazeroom1.RoomCell != mazeroom2.RoomCell)                {                    mazeroom2.RoomCell = mazeroom1.RoomCell;                    //Moves all mazerooms in room2 cell to room1 cell                    for (int i = 0; i < mazerooms.Length; i++)                    {                        if (mazerooms.RoomCell == room2_cell)                        {                            mazerooms.RoomCell = room1_cell;                        }                    }                    //Wall knockdowns                    if (mazewall.SideWall == true)                    {                        mazeroom1.EastWall = false;                        mazeroom2.WestWall = false;                    }                    if (mazewall.FloorWall == true)                    {                        mazeroom1.SouthWall = false;                        mazeroom2.NorthWall = false;                    }                    mazerooms[room1] = mazeroom1;                    mazerooms[room2] = mazeroom2;                }            }        }        //This function return an array of unique integers randomly arranged.        private int[] RandomIndexArray(int array_length)        {            int[] walls_index = new int[array_length];            int[] random_walls_index = new int[array_length];            Random random_number = new Random();            int random_index;            int temp;            int shift_index;            //Initilize array of wall indexes.            for (int i = 0; i < array_length; i++)            {                walls_index = i;            }            for (int j = walls_index.Length-1; j >= 0; j--)            {                                random_index = random_number.Next(0, j);                random_walls_index[j] = walls_index[random_index];                temp = walls_index[random_index];                shift_index = 0;                for (shift_index = random_index; shift_index < walls_index.Length - 1; shift_index++)                {                    walls_index[shift_index] = walls_index[shift_index + 1];                }                walls_index[shift_index] = temp;            }            return(random_walls_index);        }        struct MazeRoom        {            public int RoomNumber;            public int RoomCell;            public bool BorderRoom;            public bool NorthWall;            public bool WestWall;            public bool SouthWall;            public bool EastWall;        }        struct MazeWall        {            public int WallNumber;            public int AdjacentRoom1;            public int AdjacentRoom2;            public bool SideWall;            public bool FloorWall;        }    }}


cNoob
cNoob
Ok I havn't finished all of project 1 just yet but what I do have is how I'm going to implement it on paper. I've seen that theres a few people having problems with displaying there mazes so I will post my maze display method.

[WARNING]
Please note that this is not the only way there is to display the maze and is most defiantly not going to be the best way of displaying the maze, but it does however work for how I have designed my code for this project. So I'm not posting this code to say this is how it should be done. I'm simply posting my display method to give some of you guys that are struggling some ideas.
[/WARNING]

public void Display(){    // This is the outer edge drawn at the top of the maze    // minus one from maze (width * 2) so the edge doesnt stick when drawn    string topEdge = new string('_', (mazeWidth * 2)-1);    // Draw a space character before the edge for neat formating    Console.Write(" " + topEdge);    // Loop through every row in the maze    for (int y = 0; y < mazeHeight; y++)    {        // Each time starting a new row draw a new line and the left edge        Console.Write("\n|");        // loop through every column for each row        for (int x = 0; x < mazeWidth; x++)        {            // Work out what room we are working with            int curRoom = y * mazeWidth + x;            // Find out how what state the room is in            switch(rooms[curRoom].wallsStanding)            {                // This room has no walls                case 0:                {                    Console.Write("  ");                }break;                // This room has a wall to the right                case 1:                {                    Console.Write(" |");                }break;                // This room has a floor                case 2:                {                    Console.Write("_ ");                }break;                // This room has both walls                case 3:                {                    Console.Write("_|");                }break;            }        }    }    // Draw 2 new lines for neat formating purposes    Console.WriteLine("\n");}


So there you have it, you have probably noticed that I have a member field of type Int32 in my Room structure which holds the amount of walls that room currently has. Then simply using nested for loops I looped through each room and drawn the right number of walls.

[OFF TOPIC]
Hope this gives you guys a couple of ideas, also if theres anything you need help on don't be afriad to ask for help, thats what this workshop is for. I'm pretty sure the tutors would rather spend a day writing answers than have students struggle until they cant go no further and decide to give up.
[/OFF TOPIC]

EDIT: Added comments to my code

[Edited by - cNoob on August 6, 2007 1:06:07 AM]
zz2
zz2
Well, here's my maze generator. Its not prefect code but it does generate perfect maze. [grin]
Any comments and critique is welocme.

Program class:
class Program    {        static void Main(string[] args)        {            int defaultHeight = Console.WindowHeight;            int defaultWidth = Console.WindowWidth;            Console.Title = "Maze Factory";            Console.WriteLine("Welcome to Maze Factory!");            Console.WriteLine();            bool exit = false;            do            {                int rows, columns;                rows = getNumber("rows");                columns = getNumber("columns");                Maze maze = new Maze(columns, rows);                maze.Draw();                exit = exitProgram();                resetConsole(defaultWidth, defaultHeight);            } while (!exit);                    }        private static bool exitProgram()        {            do            {                Console.Write("Would you like to create another maze ([y]es,|[n]o): ");                ConsoleKeyInfo key = Console.ReadKey();                if (key.KeyChar == 'y' || key.KeyChar == 'Y')                    return false;                else if (key.KeyChar == 'n' || key.KeyChar == 'N')                    return true;                Console.WriteLine();            } while (true);        }        private static int getNumber(string numOfWhat)        {            int number;            bool OK = false;            do            {                Console.WriteLine();                Console.Write("Enter number of {0} (2-50): ", numOfWhat);                if (int.TryParse(Console.ReadLine().ToString(), out number))                {                    if (number < 2 || number > 50)                        Console.WriteLine("Sorry, that's an invalid number. Please try a number between 2 and 50.");                    else                        OK = true;                }                else                    Console.WriteLine("You have not entered a number! Please try a number between 2 and 50.");            } while (!OK);            return number;        }        private static void resetConsole(int width, int height)        {            Console.Clear();            Console.WindowWidth = width;            Console.WindowHeight = height;        }    }


Maze class:
class Maze    {        #region Fields        int x, y;        Room[][] RoomSets;        Room[] Rooms;        Wall[] Walls;        Room[,] Table;        #endregion        #region Constructor        public Maze(int x, int y)        {            this.x = x;            this.y = y;            int numOfRooms = x * y;            Rooms = new Room[numOfRooms];            RoomSets = new Room[numOfRooms][];            Table = new Room[x, y];            //fill Rooms, RoomSets and Table with rooms            for (int i = 0; i < (x * y); i++)            {                Rooms = new Room(i, i);                RoomSets = new Room[1] { Rooms };                Table[i % x, i / x] = Rooms;            }            //fill Walls list            int numOfWalls = x * (y - 1) + y * (x - 1);            Walls = new Wall[numOfWalls];            int thisRoom = 0;            int nextRoom = 1;            for (int i = 0; i < numOfWalls; i++)            {                Walls = new Wall(Rooms[thisRoom], Rooms[nextRoom]);                thisRoom++;                nextRoom++;                if (nextRoom % x == 0)                {                    if (nextRoom - x == thisRoom)                        nextRoom -= (x - 1);                    else                        thisRoom -= (x - 1);                }            }            //create perfect maze            Random random = new Random();            while (Walls.Length > 0)            {                int randomWall = random.Next(Walls.Length - 1);                if (Walls[randomWall].Room1.Set != Walls[randomWall].Room2.Set)                {                    deleteRoomsWall(Walls[randomWall].Room1, Walls[randomWall].Room2);                    copyRoomsToOneSet(Walls[randomWall].Room1.Set, Walls[randomWall].Room2.Set);                }                this.Walls = deleteWall(randomWall);            }        }         #endregion        #region Public Methods        public void Draw()        {            //check bounds            //x            int width = this.x * 2 + 3;            if (Console.BufferWidth<width)                Console.BufferWidth = width;            if (Console.WindowWidth < width)            {                if (Console.LargestWindowWidth < width)                    Console.WindowWidth = Console.LargestWindowWidth;                else                    Console.WindowWidth = width;            }            //y            int height = this.y + 2;            if (Console.BufferHeight < height)                Console.BufferHeight = height;            if (Console.WindowHeight < height)            {                if (Console.LargestWindowHeight < height)                    Console.WindowHeight = Console.LargestWindowHeight;                else                    Console.WindowHeight = height;            }                        //draw            Console.Clear();            for (int x = 0; x < this.x; x++)            {                for (int y = 0; y < this.y; y++)                {                    drawSquare(Table[x, y]);                }            }            Console.CursorLeft = 0;            Console.CursorTop = this.y+1;        }         #endregion        #region Private Methods        private void copyRoomsToOneSet(int set1, int set2)        {            int numOfCombinedRooms = this.RoomSets[set1].Length + this.RoomSets[set2].Length;            Room[] rooms = new Room[numOfCombinedRooms];            int i = 0;            foreach (Room room in this.RoomSets[set1])            {                room.Set = set1;                rooms = room;                i++;            }            foreach (Room room in this.RoomSets[set2])            {                room.Set = set1;                rooms = room;                i++;            }            this.RoomSets[set1] = rooms;            this.RoomSets[set2] = new Room[0];        }        private void deleteRoomsWall(Room room1, Room room2)        {            if (room1.Number + 1 == room2.Number)            {                room1.RightWall = false;                room2.LeftWall = false;            }            else if (room1.Number == room2.Number + 1)            {                room2.RightWall = false;                room1.LeftWall = false;            }            else if (room2.Number - x == room1.Number)            {                room1.BottomWall = false;                room2.TopWall = false;            }            else if (room1.Number - x == room2.Number)            {                room2.BottomWall = false;                room1.TopWall = false;            }        }        private Wall[] deleteWall(int wallToDelete)        {            Wall[] Walls = new Wall[this.Walls.Length - 1];            for (int i = 0; i < this.Walls.Length; i++)            {                if (i != wallToDelete)                {                    if (i < wallToDelete)                        Walls = this.Walls;                    else                        Walls[i - 1] = this.Walls;                }            }            return Walls;        }        private void drawSquare(Room room)        {            int x, y;            x = room.Number % this.x;            y = room.Number / this.x;            x *= 2;            Console.CursorLeft = x + 1;            Console.CursorTop = y;            if (room.TopWall)                Console.Write('_');            Console.CursorLeft = x;            Console.CursorTop = y + 1;            if (room.LeftWall)                Console.Write('|');            else                Console.CursorLeft++;            if (room.BottomWall)                Console.Write('_');            else                Console.CursorLeft++;            if (room.RightWall)                Console.Write('|');        }         #endregion        #region Nested Types        class Room        {            public int Number;            public int Set;            public bool LeftWall, RightWall, TopWall, BottomWall;            public Room(int Number, int Set)            {                this.Number = Number;                this.Set = Set;                LeftWall = RightWall = TopWall = BottomWall = true;            }        }        class Wall        {            public Room Room1, Room2;            public Wall(Room Room1, Room Room2)            {                this.Room1 = Room1;                this.Room2 = Room2;            }        }        #endregion    }
Endar
Endar
I was told that Lists are beyond the scope of the project, but I saw nothing prohibiting their use (and I already know all about arrays anyway), so take a look.

P.S. For those beginners who are taking a look, just think of a list as a dynamic array (not technically correct, but correct enough to look at my code). Nothing complicated, it just makes common/easy operations (add, remove, sort) even easier without the programmer having to worry so much about memory management.

Program.cs:
using System;using System.Collections.Generic;using System.Text;namespace CSharp_Workshop_Project_1___Maze_Generation{    class Program    {        static void Main(string[] args)        {            bool generate_maze = true;            Console.Title = "C# Workshop Project 1 - Perfect Maze Generation";            Console.WriteLine("Welcome to the C# Workshop Perfect Maze Generator.\n\n");            int rows, columns;            while (true)            {                // if we're no longer generating mazes                if (!generate_maze)                    break;                GetUserInput(out rows, out columns);                // resize the console bigger than the correct size                if (Console.WindowHeight < rows)                    Console.WindowHeight = rows + 10;                if (Console.WindowWidth < (columns*2)+10)                    Console.WindowWidth = (columns * 2) + 10;                //System.IO.TextWriter file = new System.IO.StreamWriter("maze.txt");                Maze maze = new Maze(rows, columns);                maze.GenerateMaze();    // generate the maze                maze.OutputMaze(Console.Out);      // output the maze to the output stream                //maze.OutputMaze(file);      // output the maze to the output stream                //file.Close();                string str = "";                while (str.Length == 0)                {                    Console.Write("\n\nWould you like to generate another maze? ([y]es|[n]o): ");                    str = Console.ReadLine();                    str = str.ToLower();                    if (str == "yes" || str == "y")                        break;                    else if (str == "no" || str == "n")                    {                        generate_maze = false;                        break;                    }                    else                    {                        str = "";                        Console.Write("\nInvalid input. Please answer either 'yes' or 'no'");                    }                }// while str is empty            }// while        }        static void GetUserInput(out int r, out int c)        {            string str;            int rows, columns;            Console.Write("\nGenerating a maze:\n");            // read the number of rows            Console.Write("\nEnter the number of rows for the maze (2-50): ");            str = Console.ReadLine();            while (true)            {                if (!Int32.TryParse(str, out rows))                {                    Console.Write("\nInvalid input, please try again.");                }                else if (rows < 2 || rows > 50)                {                    Console.Write("\nInvalid number of rows (must be between 2 and 50), please try again.");                }                else                    break;                Console.Write("\nEnter the number of rows for the maze (2-50): ");                str = Console.ReadLine();            }// while            // read the number of columns            Console.Write("\nEnter the number of columns for the maze (2-50): ");            str = Console.ReadLine();            while (true)            {                if (!Int32.TryParse(str, out columns))                {                    Console.Write("\nInvalid input, please try again.");                }                else if (columns < 2 || columns > 50)                {                    Console.Write("\nInvalid number of columns (must be between 2 and 50), please try again.");                }                else                    break;                Console.Write("\nEnter the number of columns for the maze (2-50): ");                str = Console.ReadLine();            }// while            r = rows;            c = columns;        }// GetUserInput    }}


Maze.cs:
using System;using System.Collections.Generic;using System.Text;namespace CSharp_Workshop_Project_1___Maze_Generation{    class Maze    {        private int NumRooms, NumRows, NumColumns, NumWalls, NumVertWallsPerRow, NumHorWallsPerRow;        private List<List<int>> RoomSets;   // the sets of the rooms that have a path to each other        private List<int> WallsUp;          // a list of the walls up        public Maze(int r, int c)        {            NumRows = r;            NumColumns = c;            NumRooms = NumRows * NumColumns;            NumVertWallsPerRow = NumColumns - 1;            NumHorWallsPerRow = NumColumns;            RoomSets = new List<List<int>>();            WallsUp = new List<int>();            // init all rooms into a set each            for (int i = 0; i < NumRooms; ++i)            {                List<int> temp = new List<int>();                temp.Add(i);                RoomSets.Add(temp);            }            // calc the number of walls            NumWalls = ((r * (c - 1)) + (c * (r - 1)));            // init all walls as up            for (int i = 0; i < NumWalls; ++i)                WallsUp.Add(i);            Random rand = new Random();            // randomize the WallsUp array            for (int i = 0; i < WallsUp.Count; ++i)            {                int temp, temp_index = rand.Next() % (WallsUp.Count - i) + i;                temp = WallsUp;                WallsUp = WallsUp[temp_index];                WallsUp[temp_index] = temp;            }        }        public void OutputMaze(System.IO.TextWriter stream)        {            stream.Write("\n\n");            stream.Write(' ');            // print out the top border            for (int i = 0; i < (NumColumns * 2)-1; ++i)                stream.Write('_');            // Output the walls based on the walls that are still up - iterate through all the rooms            // and if there should be a wall there, output it, else, output a space.            for (int i = 0; i < NumRows; ++i)            {                stream.Write("\n|");                for (int j = 0; j < NumColumns; ++j)                {                    // calc the room number we should be looking at                    int room_num = (i * NumColumns) + j;                    int wall1,  // vertical wall for room                        wall2;  // horizontal wall for room (at bottom of room)                    GetWallsFromRoom(room_num, out wall1, out wall2);                    // for the first character (horizontal wall)                    if (WallsUp.Contains(wall2))                        stream.Write('_');                    // else just a space                    else                    {                        // if we're on the last row of rooms, it will never have a horizontal wall,                         // but it needs a border.                        if (i == NumRows - 1)                            stream.Write('_');                        // else this is just a room with no horizontal wall                        else                            stream.Write(' ');                    }                    // for the second character (vertical wall)                    if (WallsUp.Contains(wall1))                        stream.Write('|');                    // else just a space                    else                    {                        // if we're on the last room in the row, it will never have a wall, but it needs the border                        if (j == NumColumns - 1)                            stream.Write('|');                        // if we're on the last row of rooms, and there is no vertical wall, we have to write it                        // as the border.                        else if (i == NumRows - 1)                            stream.Write('_');                        // else this is just a room with no vertical wall                        else                            stream.Write(' ');                    }                }// for j < NumColumns            }// for i < NumRows            stream.Write("\n\n");        }        public void GenerateMaze()        {            // DEBUG            //Console.WriteLine("Number of rows: " + NumRows.ToString());            //Console.WriteLine("Number of columns: " + NumColumns.ToString());            //Console.WriteLine("Number of walls: " + NumWalls.ToString());            // DEBUG            Console.WriteLine("\nGenerating maze");            /////// Generate the maze ///////            for (int i = 0; i < WallsUp.Count; ++i )            {                int room1, room2;                GetRoomsFromWall(WallsUp, out room1, out room2);                List<int> room1_set = FindSetThatContains(room1);                List<int> room2_set = FindSetThatContains(room2);                // if the two rooms are not in the same set                if (room1_set != room2_set)                {                    // knock down the wall between them                    WallsUp.RemoveAt(i);                    --i;    // so when we increment at the beginning of the loop, we end up at the same index                            // which is the next item since we just deleted one.                    // Put everything from room2_set into room1_set                    // This is because if two rooms are in a set, that means that there is a path between them                    // so, if we have three rooms in two sets: (A) and (B,C), if a path opens up between A and B,                    // then there is automatically a path from A to C.                    room1_set.AddRange(room2_set);                    room2_set.Clear();                }                // else the two rooms are in the same set, so leave the wall up            }        }        /**         * Return the two walls that bound a particular room. If the room only has 1 wall, ie. it is on the         * boundary of the maze, the other var will be set to '-1'         * \param wall1 The vertical wall for the room         * \param wall2 The horizontal wall for the room         */         private void GetWallsFromRoom(int room, out int wall1, out int wall2)        {            if( room < 0 || room >= NumRooms )                throw new Exception("Invalid room index: " + room.ToString());            // integer division to find the row the room is on            int row = room / NumColumns;            // the index of the first room on the row            int start_room = row * NumColumns;            // the first index of the first vertical wall on the first row            int start_vert = (NumVertWallsPerRow + NumHorWallsPerRow) * row;            int start_hor = NumVertWallsPerRow + ((NumHorWallsPerRow + NumVertWallsPerRow) * row);            // find the offset of the room index into the current row            int room_offset = room - start_room;            wall1 = start_vert + room_offset;            wall2 = start_hor + room_offset;            // The vertical wall for the last room is not considered to be a wall. It is the border of the maze.            // It is ignored.            if (wall1 >= NumVertWallsPerRow + start_vert)                wall1 = -1;            // The bottom border of the maze are not considered to be walls. They are ignored.            if (wall2 >= NumWalls || wall2 >= NumHorWallsPerRow + start_hor)                wall2 = -1;        }        /**         * Find the two rooms that are connected by the given wall.         */         private void GetRoomsFromWall(int wall, out int room1, out int room2)        {            if (wall >= NumWalls || wall < 0)                throw new Exception("Invalid wall index: " + wall.ToString());            int start_vert = 0,                     // the index of the first vertical wall in the row                start_hor = NumVertWallsPerRow;     // the index of the first horizontal wall in the row            for (int i = 0; i < NumRows; ++i)            {                // where 'i' is the row index                int start_room = i * NumColumns;                // if 'wall' is a verical wall in row 'i'                if (wall >= start_vert && wall <= ((start_vert + NumVertWallsPerRow) - 1))                {                    int wall_offset = wall - start_vert;                    room1 = start_room + wall_offset;                    room2 = start_room + 1 + wall_offset;                    return;                }                // if 'wall' is a horizontal wall in row 'i'                else if (wall >= start_hor && wall <= ((start_hor + NumHorWallsPerRow) - 1))                {                    int wall_offset = wall - start_hor;                    room1 = start_room + wall_offset;                    room2 = room1 + NumColumns;                    return;                }                // get ready for the next row                start_vert += NumVertWallsPerRow + NumHorWallsPerRow;                start_hor += NumHorWallsPerRow + NumVertWallsPerRow;            }// for            room1 = -1;            room2 = -1;            throw new Exception("Error: invalid wall index, or something. I reached the end of a function I shouldn't have.");        }        /**         * Return the set that contains the given element         */        public List<int> FindSetThatContains(int item)        {            foreach (List<int> temp in RoomSets)            {                if (temp.Contains(item))                {                    List<int> return_temp = temp;                    return return_temp;                }            }            return null;        }        public List<int> FindBiggestRoomSet()        {            int index = 0, size = RoomSets[0].Count;            for (int i = 1; i < RoomSets.Count; ++i)            {                if (RoomSets.Count > size)                {                    index = i;                    size = RoomSets.Count;                }            }            return RoomSets[index];        }    }}


Have fun.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Xeio
Xeio
Ok, first, I decided to use classes to represent my walls and rooms rather than structures. Partially out of preference, though I also added several methods to simplify the code in the main part of the program. I also, like Endar, used the List class, mostly because I already know it, as it handles most of the common operations for you.

Also, instead of using one primary set of rooms lists, I gave each room a self-contained list that would hold all the rooms its connected to. Each wall also knows which rooms it is connected to, and the rooms know which walls they are connected to.

Program.cs
using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            //welcome and title            Console.Title = "Maze Generator 32354 by Xeio";            Console.WriteLine("Welcome to a Random Maze Generator 32354, yet another way to make random mazes.");            //loop used to coninue if user wishes to make multiple mazes            do            {                //gets size of maze from user, passes them back to main method                int height, width;                querySize(out height, out width);                //creates rooms and walls, passes back 2d array of rooms and list of all walls to main method                Room[,] mazeRooms;                List<Wall> wallList;                createFullMaze(height, width, out mazeRooms, out wallList);                //destroys random walls untill all rooms are connected                breakWalls(wallList);                //draws the maze using the room array                drawMaze(mazeRooms);                //checks if the user wishes to continue and make another maze            } while (queryContinue());            //pauses program waiting for enter key to exit            Console.WriteLine("Press any key to continue...");            Console.ReadLine();        }        private static void querySize(out int height, out int width)        {            height = 0;            width = 0;            //querys user for number of rows (width)            Console.WriteLine("Enter the number of rows for the maze between 2 and 50:");            do            {                //try block, used to catch non-numbers and int overflows when the computer parses the entry                try                {                    //parses the entered number                    width = int.Parse(Console.ReadLine());                    //checks if the number is valid, if not, prints a message that you need to re-enter it                    if (width < 2 || width > 50)                        Console.WriteLine("Invalid entry, please retry:" + width);                }                catch (FormatException) { Console.WriteLine("Not a number, please enter a number between 1 and 50"); }                catch (OverflowException) { Console.WriteLine("Invalid entry, please try again."); }                //repeats the loop as long as the number is still invalid            } while (width < 2 || width > 50);            //querys user for number of colums (height)            Console.WriteLine("Enter the number of columns for the maze between 2 and 50:");            do            {                //try block, used to catch non-numbers and int overflows when the computer parses the entry                try                {                    //parses the entered number                    height = int.Parse(Console.ReadLine());                    //checks if the number is valid, if not, prints a message that you need to re-enter it                    if (height < 2 || height > 50)                        Console.WriteLine("Invalid entry, please retry:" + height);                }                catch (FormatException) { Console.WriteLine("Not a number, please enter a number between 1 and 50"); }                catch (OverflowException) { Console.WriteLine("Invalid entry, please try again."); }                //repeats the loop as long as the number is still invalid            } while (height < 2 || height > 50);        }        private static void createFullMaze(int height, int width, out Room[,] mazeRooms, out List<Wall> wallList)        {            //creates list for walls, and the array for the maze rooms (using the passed in width and height)            mazeRooms = new Room[height, width];            wallList = new List<Wall>();            //creates rooms and puts in multidimensional array (2d)            int count = 0;            for (int h = 0; h < height; h++)                for (int w = 0; w < width; w++)                    mazeRooms[h, w] = new Room(count++);            //creates walls then adds walls to rooms            for (int h = 0; h < height; h++)                for (int w = 0; w < width; w++)                {                    //loops iterate through every room                    //horizontal walls                    if (!(w == width - 1))                    {                        //as long as room is not on right end of maze, adds a wall (dis)connecting it to the right room                        Wall wall = new Wall(mazeRooms[h, w], mazeRooms[h, w + 1]);                        wallList.Add(wall);                        mazeRooms[h, w].right = wall;                        mazeRooms[h, w + 1].left = wall;                    }                    //verticle walls                    if (!(h == height - 1))                    {                        //as long as room is not on bottom end of maze, adds a wall (dis)connecting it to the below room                        Wall wall = new Wall(mazeRooms[h, w], mazeRooms[h + 1, w]);                        wallList.Add(wall);                        mazeRooms[h, w].down = wall;                        mazeRooms[h + 1, w].up = wall;                    }                }        }        private static void breakWalls(List<Wall> wallList)        {            //seeds a random for wall destruction            Random rand = new Random();            while (wallList.Count > 0)            {                //picks a random wall that is not destroyed, and has not already been checked                int index = rand.Next(wallList.Count - 1);                if (!wallList[index].roomsAlreadyConnected())                {                    //if the rooms next to the wall are not already connected destroys the wall                    wallList[index].destroyWall();                }                //removes wall so it is not checked again                wallList.RemoveAt(index);            }        }        private static void drawMaze(Room[,] rooms)        {            //draws the top of the maze            Console.Write(" ");            for (int width = 0; width < rooms.GetLength(1) - 1; width++)                Console.Write("__");            Console.WriteLine("_");            //draws the main part of the maze            for (int height = 0; height < rooms.GetLength(0); height++)            {                //left wall                Console.Write("|");                for (int width = 0; width < rooms.GetLength(1); width++)                {                    //if room has wall down, draws it                    //also draws wall down if edge of maze                    if (rooms[height, width].hasWallDown() || height == rooms.GetLength(0) - 1)                        Console.Write("_");                    else                        Console.Write(" ");                    //if room has wall right, draws it                    //also draws wall right if edge of maze                    if (rooms[height, width].hasWallRight() || width == rooms.GetLength(1) - 1)                        Console.Write("|");                    else                        Console.Write("_");                }                Console.WriteLine();            }        }        private static bool queryContinue()        {            //checks if the user wants to continue            Console.WriteLine("Maze Completed! Would you like to create another? ([Y]es, [N]o):");            while (true)            {                String temp = Console.ReadLine();                if (temp.ToLower().Equals("yes") || temp.ToLower().Equals("y"))                    return true;                else if (temp.ToLower().Equals("no") || temp.ToLower().Equals("n"))                    return false;                else                    Console.WriteLine("Invalid entry, please enter one of the choices ([Y]es, [N]o)");            }        }    }}


Room.cs
using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{    class Room    {        public int roomnum;        //walls of the room        public Wall down, right, up, left;        //list of connected rooms        private List<Room> connected;        public Room(int num)        {            roomnum = num;            //makes new list of connected rooms, and adds this room (its connected to itself)            connected = new List<Room>();            connected.Add(this);        }        public void removeWall(Wall wall)        {            //removes a specified wall (from any direction) if present in this room            if(up == wall)                up = null;            if(right == wall)                right = null;            if(down == wall)                down = null;            if(left == wall)                left = null;        }        public bool hasWallDown()        {            //checks if the down wall is a null reference (I.E. there is no wall) and returns false if it is            return (down != null);        }        public bool hasWallRight()        {            //checks if the right wall is a null reference (I.E. there is no wall) and returns false if it is            return (right != null);        }        public void mergeWith(Room room)        {            //adds list of connected rooms from passed room and this together            connected.AddRange(room.connected);            //loop ensures that every connected room's list is updated to reflect merge            foreach (Room r in connected)                r.connected = connected;        }        public bool isConnectedTo(Room room)        {            //checks if this room is connected to the passed room            return connected.Contains(room);        }    }}


Wall.cs
using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{    class Wall    {        public Room room1, room2;        public Wall(Room room1, Room room2)        {            this.room1 = room1;            this.room2 = room2;        }        public void destroyWall()        {            //destroys this wall, then updates each room's list of connected rooms to reflect the newly destroyed wall            room1.removeWall(this);            room2.removeWall(this);            room1.mergeWith(room2);        }        public bool roomsAlreadyConnected()        {            //checks if rooms are already connected            return room1.isConnectedTo(room2);        }    }}

Telastyn
Telastyn
[WARNING]
I am a cheater. I went through the project so I could better answer questions, so I focused on the bits that would help me most.

I used stuff that's not yet been covered in the workshop. I also circumvented the requirements, skipping the user input stuff. I also used an arguably different algorithm to generate the maze (slight modifications to a pathfinding algorithm I once implemented).

Oh, and I did some naughty habit things (fixed indexes in TileSet, bad variable naming in places, leaving things (maze wrapping, 3d bits, specifying the size via cli) undone, nesting method calls in places, lack of refactoring...).

All in all it works, and well; but it is very thrown together. Review at your own peril!

[/warning]


That out of the way, my maze gen was split into two projects. One for the infrastructure and the generations, the other for the 'front end' which would eventually take parameters and the such.

The part that took the longest was easily Map.ToAscii. Map.Generate took about 20 mins.

First, the front-end:
using System;using System.Collections.Generic;using System.Text;namespace GDnet_csWorkshop_proj1 {    class Program {        static void Main(string[] args) {                      Console.SetWindowSize(80, 80);            foreach (string line in GDnet_csWorkshop_mazelib.Map.Generate(20,20,1,false,false,false,42).ToAscii()) {                Console.WriteLine(line);            }        }    }}


Yeah.

Saw a nifty maze and promptly stopped. I'm not exactly a front-end kinda guy...

using System;using System.Collections.Generic;using System.Text;namespace GDnet_csWorkshop_mazelib {    // stolen from moe.    public class CoordinateLookupTable {        private Dictionary<int, Dictionary<int, Dictionary<int, Tile>>> Table = new Dictionary<int, Dictionary<int, Dictionary<int, Tile>>>();        public void Add(Tile tile) {            if (!Table.ContainsKey(tile.X)) {                Table.Add(tile.X, new Dictionary<int, Dictionary<int, Tile>>());            }            if (!Table[tile.X].ContainsKey(tile.Y)) {                Table[tile.X].Add(tile.Y, new Dictionary<int, Tile>());            }            if (!Table[tile.X][tile.Y].ContainsKey(tile.Z)) {                Table[tile.X][tile.Y].Add(tile.Z, tile);            } else {                Table[tile.X][tile.Y][tile.Z] = tile;            }        }                public void Add(Tile tile, int[] from, int[] to) { Add(tile); }                public Tile Fetch(int x, int y, int z) {            if (!Table.ContainsKey(x)) {                return (null);            }            if (!Table[x].ContainsKey(y)) {                return (null);            }            if (!Table[x][y].ContainsKey(z)) {                return (null);            }            return (Table[x][y][z]);        }        public void Clear() {            Table = new Dictionary<int, Dictionary<int, Dictionary<int, Tile>>>();        }             public void Remove(Tile tile) {            if (Fetch(tile.X, tile.Y, tile.Z) == tile) {                Table[tile.X][tile.Y].Remove(tile.Z);            }        }    }    public class Map {        protected List<Tile> Tiles = new List<Tile>();        protected CoordinateLookupTable TileTable = new CoordinateLookupTable();        public readonly bool WrapX;        public readonly bool WrapY;        public readonly bool WrapZ;        internal int minX = int.MaxValue;        internal int maxX = int.MinValue;        internal int minY = int.MaxValue;        internal int maxY = int.MinValue;        internal int minZ = int.MaxValue;        internal int maxZ = int.MinValue;        public enum Direction {            North,            East,            South,            West        }        public static Direction OppositeOf(Direction direction) {            Direction toDir = Direction.North;            switch (direction) {                case Direction.East:                    toDir = Direction.West;                    break;                case Direction.North:                    toDir = Direction.South;                    break;                case Direction.South:                    toDir = Direction.North;                    break;                case Direction.West:                    toDir = Direction.East;                    break;            }            return (toDir);        }        public void Add(Tile what) {            Tiles.Add(what);            TileTable.Add(what);            if (what.X < minX) { minX = what.X; }            if (what.X > maxX) { maxX = what.X; }            if (what.Y < minY) { minY = what.Y; }            if (what.Y > maxY) { maxY = what.Y; }            if (what.Z < minZ) { minZ = what.Z; }            if (what.Z > maxZ) { maxZ = what.Z; }        }        internal static void SetPath(Tile from, Direction direction, Tile to, Path value) {            Direction fromDir = direction;            from.Add(fromDir, value);            if (value.State != Path.Type.Solid && to != null) {                to.Add(OppositeOf(fromDir), value);            }        }        protected Map(bool wrapX, bool wrapY, bool wrapZ) { }        protected Map() : this(false, false, false) { }        protected Tile[] TileSet(int x, int y, int z) {            Tile[] rtn = new Tile[10];            rtn[1] = TileTable.Fetch(x - 1, y + 1, z);            rtn[2] = TileTable.Fetch(x, y + 1, z);            rtn[3] = TileTable.Fetch(x + 1, y + 1, z);            rtn[4] = TileTable.Fetch(x - 1, y, z);            rtn[5] = TileTable.Fetch(x, y, z);            rtn[6] = TileTable.Fetch(x + 1, y, z);            rtn[7] = TileTable.Fetch(x - 1, y - 1, z);            rtn[8] = TileTable.Fetch(x, y - 1, z);            rtn[9] = TileTable.Fetch(x + 1, y - 1, z);            return (rtn);        }        protected Tile[] TileSet(Tile what) { return (TileSet(what.X, what.Y, what.Z)); }                protected char AsciiFor(float x, float y, float z) {            if (z % 1 != 0) {                throw new NotImplementedException();            }            if (x % 1 == 0) {                if (y % 1 == 0) {                    return (Path.AsciiRepresentation[Path.Type.Clear]);                } else {                    Tile high = TileTable.Fetch((int)Math.Floor(x), (int)Math.Floor(y), (int)Math.Floor(z));                    Tile low = TileTable.Fetch((int)Math.Floor(x), (int)Math.Ceiling(y), (int)Math.Floor(z));                    if (high == null && low == null) {                        return (' ');                    }                    if (high != null) {                        return (Path.AsciiRepresentation[high.PathTo(Direction.South).State]);                    } else {                        return (Path.AsciiRepresentation[low.PathTo(Direction.North).State]);                    }                }            } else {                if (y % 1 == 0) {                    Tile right = TileTable.Fetch((int)Math.Ceiling(x), (int)Math.Floor(y), (int)Math.Floor(z));                    Tile left = TileTable.Fetch((int)Math.Floor(x), (int)Math.Floor(y), (int)Math.Floor(z));                    if (right == null && left == null) {                        return (' ');                    }                    if (left != null) {                        return (Path.AsciiRepresentation[left.PathTo(Direction.East).State]);                    } else {                        return (Path.AsciiRepresentation[right.PathTo(Direction.West).State]);                    }                } else {                    Tile nw = TileTable.Fetch((int)Math.Floor(x), (int)Math.Floor(y), (int)Math.Floor(z));                    Tile ne = TileTable.Fetch((int)Math.Ceiling(x), (int)Math.Floor(y), (int)Math.Floor(z));                    Tile se = TileTable.Fetch((int)Math.Ceiling(x), (int)Math.Ceiling(y), (int)Math.Floor(z));                    Tile sw = TileTable.Fetch((int)Math.Floor(x), (int)Math.Ceiling(y), (int)Math.Floor(z));                    if (nw != null || ne != null || se != null || sw != null) {                        return (Path.AsciiRepresentation[Path.Type.Solid]);                    } else {                        return (' ');                    }                }            }        }        private enum GenState {            Closed,            Used,            Open        }        public static Map Generate(int xSize, int ySize, int zSize, bool xWrap, bool yWrap, bool zWrap, int seed) {            if (xSize < 1 || ySize < 1 || zSize < 1) {                return (null);            }            Map rtn = new Map(xWrap, yWrap, zWrap);            for (int x = 0; x < xSize; ++x) {                for (int y = 0; y < ySize; ++y) {                    for (int z = 0; z < zSize; ++z) {                        Tile newbie = new Tile(x, y, z);                        if (y == 0) {                            newbie.Add(Direction.North, new Path(Path.Type.Solid));                        } else {                            newbie.Add(Direction.North, new Path(Path.Type.Wall));                        }                        if (y == ySize - 1) {                            newbie.Add(Direction.South, new Path(Path.Type.Solid));                        } else {                            newbie.Add(Direction.South, new Path(Path.Type.Wall));                        }                        if (x == 0) {                            newbie.Add(Direction.West, new Path(Path.Type.Solid));                        } else {                            newbie.Add(Direction.West, new Path(Path.Type.Wall));                        }                        if (x == xSize - 1) {                            newbie.Add(Direction.East, new Path(Path.Type.Solid));                        } else {                            newbie.Add(Direction.East, new Path(Path.Type.Wall));                        }                        rtn.Add(newbie);                    }                }            }            Random rng = new Random(seed);            Dictionary<Tile, GenState> GenStatus = new Dictionary<Tile, GenState>();            List<Tile> OpenPath = new List<Tile>();            foreach (Tile t in rtn.Tiles) {                GenStatus.Add(t, GenState.Closed);            }            int startX;            int startY;            int startZ;            startX = rng.Next(rtn.minX, rtn.maxX + 1);            startY = rng.Next(rtn.minY, rtn.maxY + 1);            startZ = rng.Next(rtn.minZ, rtn.maxZ + 1);            Tile CurrentTile = rtn.TileTable.Fetch(startX, startY, startZ);            OpenPath.Add(CurrentTile);            GenStatus[CurrentTile] = GenState.Open;            Tile[] SurroundingTiles;            while (OpenPath.Count > 0) {                CurrentTile = OpenPath[OpenPath.Count - 1];                SurroundingTiles = rtn.TileSet(CurrentTile);                if (SurroundingTiles[2] != null && GenStatus[SurroundingTiles[2]] == GenState.Closed ||                    SurroundingTiles[4] != null && GenStatus[SurroundingTiles[4]] == GenState.Closed ||                    SurroundingTiles[6] != null && GenStatus[SurroundingTiles[6]] == GenState.Closed ||                    SurroundingTiles[8] != null && GenStatus[SurroundingTiles[8]] == GenState.Closed) {                    int Target;                    do {                        Target = rng.Next(1, 5) * 2;                    } while (SurroundingTiles[Target] == null || GenStatus[SurroundingTiles[Target]] != GenState.Closed);                    Direction TargetDirection = Direction.South;                    switch(Target){                        case 4:                            TargetDirection=Direction.West;                            break;                        case 6:                            TargetDirection=Direction.East;                            break;                        case 8:                            TargetDirection=Direction.North;                            break;                    }                    OpenPath.Add(SurroundingTiles[Target]);                    GenStatus[SurroundingTiles[Target]] = GenState.Open;                    SetPath(CurrentTile, TargetDirection, SurroundingTiles[Target], new Path(Path.Type.Clear));                } else {                    GenStatus[CurrentTile] = GenState.Used;                    OpenPath.Remove(CurrentTile);                }            }            return (rtn);        }        public static Map TestCreate() {            Map rtn = new Map();            Tile[] Tiles = new Tile[10];            int a = 1;            for (int y = 2; y >= 0; --y) {                for (int x = 0; x <= 2; ++x) {                    Tiles[a] = new Tile(x, y, 0);                    ++a;                }            }            Map.SetPath(Tiles[5], Direction.East, Tiles[6], new Path(Path.Type.Clear));            Map.SetPath(Tiles[5], Direction.South, Tiles[2], new Path(Path.Type.Wall));            Map.SetPath(Tiles[5], Direction.West, Tiles[4], new Path(Path.Type.Wall));            Map.SetPath(Tiles[5], Direction.North, Tiles[8], new Path(Path.Type.Wall));            Map.SetPath(Tiles[6], Direction.North, Tiles[9], new Path(Path.Type.Clear));            Map.SetPath(Tiles[6], Direction.East, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[6],Direction.South,Tiles[3],new Path(Path.Type.Wall));            Map.SetPath(Tiles[9], Direction.West, Tiles[8], new Path(Path.Type.Clear));            Map.SetPath(Tiles[9], Direction.North, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[9], Direction.East, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[8], Direction.West, Tiles[7], new Path(Path.Type.Clear));            Map.SetPath(Tiles[8], Direction.North, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[7], Direction.South, Tiles[4], new Path(Path.Type.Clear));            Map.SetPath(Tiles[7], Direction.North, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[7], Direction.West, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[4], Direction.South, Tiles[1], new Path(Path.Type.Clear));            Map.SetPath(Tiles[4], Direction.West, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[1], Direction.East, Tiles[2], new Path(Path.Type.Clear));            Map.SetPath(Tiles[1], Direction.South, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[1], Direction.West, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[2], Direction.East, Tiles[3], new Path(Path.Type.Clear));            Map.SetPath(Tiles[2], Direction.South, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[3], Direction.South, null, new Path(Path.Type.Solid));            Map.SetPath(Tiles[3], Direction.East, null, new Path(Path.Type.Solid));            for (int x = 1; x < 10; ++x) {                rtn.Add(Tiles[x]);            }            return (rtn);        }        public List<string> ToAscii() {            List<string> rtn = new List<string>();            string currentLine;            float curX;            float curY;            for (curY = (float)(minY - .5); curY <= maxY + .5; curY += (float).5) {                currentLine = "";                for (curX = (float)(minX - .5); curX <= maxX + .5; curX += (float).5) {                    currentLine += AsciiFor(curX, curY, minZ);                }                rtn.Add(currentLine);            }            return (rtn);        }    }    public class Tile {        public int X;        public int Y;        public int Z;        protected Dictionary<Map.Direction,Path> paths=new Dictionary<Map.Direction,Path>();        public Path PathTo(Map.Direction Direction) {            if (paths.ContainsKey(Direction)) {                return (paths[Direction]);            } else {                return (null);            }        }        internal void Add(Map.Direction Direction, Path path) {            paths[Direction] = path;        }        internal Tile(int inX, int inY, int inZ) {            X = inX;            Y = inY;            Z=inZ;        }    }    public class Path {        public static Dictionary<Type, char> AsciiRepresentation = new Dictionary<Type, char>();                public enum Type {            Unknown,            Solid,            Clear,            Wall,            OpenDoor,            ClosedDoor        }                        protected Type state;        public Type State{            get{                return(state);            }            internal set{                state=value;            }        }        internal Path(Type inState) { state = inState; }        static Path(){            AsciiRepresentation[Type.Unknown] = '?';            AsciiRepresentation[Type.Solid] = '#';            AsciiRepresentation[Type.Clear] = '.';            AsciiRepresentation[Type.Wall] = '#';                }    }}
Emmanuel Deloget
Emmanuel Deloget
Time to give you my own solution. I tried to stick to the requirements, and hopefully I succeeded (well, I throw an exception; that's not that good). The design of this solution is not that bad, although it could be better (if we were allowed to use more bits of the language). I believe that the whole project will serve as a base for the forthcoming projects, so I should be able to refactor it a bit.

Take care, this is a bit long...
using System;using System.Collections.Generic;using System.Text;namespace MazeGen{  class Program  {    static int GetIntegerFromConsole(string message, int min, int max, string onError)    {      int value = 0;      bool isValid = false;      do      {        try        {          Console.Write(message + " ");          string userInput = Console.ReadLine();          if (userInput.Length > 0)          {            value = Convert.ToInt32(userInput);            if (value > min && value < max)            {              isValid = true;            }            else            {              throw new OverflowException();            }          }        }        catch (FormatException)        {          Console.WriteLine(onError);        }        catch (OverflowException)        {          Console.WriteLine(onError);        }      }      while (!isValid);      return value;    }    static void UpdateConsole(int columns, int lines)    {      if (Console.WindowWidth < columns + 10)      {        Console.WindowWidth = columns + 10;      }      if (Console.WindowHeight < lines + 10)      {        Console.WindowHeight = lines + 10;      }    }    static void GenerateAndPrintMaze(int columns, int lines)    {      Model.MazeGenerator generator = new Model.MazeGenerator(columns, lines);      generator.MakeMaze();      generator.PrintMaze(new Model.MazePrinter());    }    static void Main(string[] args)    {      Console.WriteLine("Thy be Cee Pound MazeGen!");      Console.WriteLine("");      int columns = GetIntegerFromConsole("Gimme thy number of columns!", 2, 51,          "Nay. Thy number be greater than 2 or weaker than 50");      int lines = GetIntegerFromConsole("Gimme thy number of lines!", 2, 51,          "Nay. Thy number be greater than 2 or weaker than 50");      Console.WriteLine("");      UpdateConsole(columns, lines);      GenerateAndPrintMaze(columns, lines);      Console.WriteLine("");    }  }}namespace MazeGen.Model{  public class MazeGenerator  {    internal int columns;    internal int lines;    internal RoomSet roomSet = null;    internal WallSet wallSet = null;    public MazeGenerator(int cols, int lines)    {      this.columns = cols;      this.lines = lines;      wallSet = new WallSet(this.columns, this.lines);      roomSet = new RoomSet(this.columns, this.lines);    }    public void MakeMaze()    {      wallSet.Begin();      do      {        int room1;        int room2;        bool lr;        int wall = wallSet.CurrentWall;        wallSet.GetAttachedRoom(wall, out room1, out room2, out lr);        if (roomSet.Join(room1, room2))        {          wallSet.RemoveWall();        }      }      while (roomSet.Count > 1 && wallSet.Advance());      wallSet.End();    }    public void PrintMaze(MazePrinter printer)    {      int[] upWallSet = wallSet.UpWallSet;      if (upWallSet != null)      {        printer.Print(upWallSet, this.columns, this.lines);      }    }  }  class WallSet  {    internal int columns;    internal int lines;    internal int[] walls = null;    internal int[] removedWalls = null;    internal int currentWallIndex = 0;    internal int endWallIndex = 0;    public WallSet(int columns, int lines)    {      this.columns = columns;      this.lines = lines;      int wallCount = 2 * columns * lines - columns - lines;      this.walls = new int[wallCount];      this.removedWalls = new int[wallCount];      for (int i = 0; i < wallCount; ++i)      {        this.walls = i;        this.removedWalls = -1;      }      RandomizeWallSet();    }    private void RandomizeWallSet()    {      Random rndGenerator = new Random();      int iterCount = 2 * this.walls.Length;      for (int i = 0; i < iterCount; ++i)      {        // swap two datas at random        int index1 = rndGenerator.Next() % this.walls.Length;        int index2 = rndGenerator.Next() % this.walls.Length;        int temp = this.walls[index1];        this.walls[index1] = this.walls[index2];        this.walls[index2] = temp;      }    }    public int CurrentWall { get { return this.walls[this.currentWallIndex]; } }    public bool Advance()    {      if (this.currentWallIndex < this.walls.Length - 1)      {        this.currentWallIndex++;        return true;      }      return false;    }    public void GetAttachedRoom(int wall, out int room1, out int room2, out bool lrDirection)    {      int lineToConsider = wall / (2 * this.columns - 1);      int positionInLine = wall % (2 * this.columns - 1);      if (positionInLine >= this.columns - 1)      {        room1 = lineToConsider * this.columns + positionInLine - (this.columns - 1);        room2 = room1 + this.columns;        lrDirection = false;      }      else      {        room1 = lineToConsider * this.columns + positionInLine;        room2 = room1 + 1;        lrDirection = true;      }    }    public void Begin()    {      this.currentWallIndex = 0;      this.endWallIndex = 0;    }    public void End() { }    public void RemoveWall()    {      this.removedWalls[this.endWallIndex] = this.walls[this.currentWallIndex];      this.endWallIndex++;    }    public int[] UpWallSet    {      get      {        if (this.endWallIndex > 0)        {          int[] upWallSet = new int[this.walls.Length];          for (int i = 0; i < upWallSet.Length; ++i)          {            upWallSet = i;          }          for (int i = 0; i < this.endWallIndex; ++i)          {            upWallSet[this.removedWalls] = -1;          }          return upWallSet;        }        else        {          return null;        }      }    }  }  class RoomSet  {    internal int columns;    internal int lines;    internal int roomSetCount;    // this array contains the roomset to which the room belongs    internal int[] rooms;    public RoomSet(int columns, int lines)    {      this.columns = columns;      this.lines = lines;      this.roomSetCount = this.columns * this.lines;      this.rooms = new int[this.roomSetCount];      for (int i = 0; i < this.rooms.Length; ++i)      {        // each room is in its own room set        this.rooms = i;      }    }    public bool Join(int room1, int room2)    {      if (this.rooms[room1] != this.rooms[room2])      {        // put everything from this.rooms[room2] into this.rooms[room1]        int fromSet = this.rooms[room2];        int toSet = this.rooms[room1];        for (int i = 0; i < this.rooms.Length; ++i)        {          if (this.rooms == fromSet)          {            this.rooms = toSet;          }        }        --roomSetCount;        return true;      }      return false;    }    public int Count { get { return roomSetCount; } }  }  public class MazePrinter  {    internal void WriteHeaderMazeLine(int lineSize)    {      Console.Write(" ");      for (int i = 0; i < lineSize - 1; ++i)      {        Console.Write("__");      }      Console.WriteLine("_");    }    internal void WriteFooterMazeLine(int[] upWalls, int fromIndex, int lineSize)    {      Console.Write("|");      int index = fromIndex;      int lineSizeVert = lineSize - 1;      for (int c = 0; c < lineSize; ++c)      {        bool endLine = (c == lineSizeVert);        string wallRep = "__";        if (endLine || upWalls[index] >= 0)        {          wallRep = "_|";        }        if (endLine)        {          Console.WriteLine(wallRep);        }        else        {          Console.Write(wallRep);        }        ++index;      }    }    internal void WriteMazeLine(int[] upWalls, int fromIndex, int lineSize)    {      Console.Write("|");      int index = fromIndex;      int lineSizeVert = lineSize - 1;      for (int c = 0; c < lineSize; ++c)      {        string wallRep = "";        bool endLine = (c == lineSizeVert);        bool lrWall = upWalls[index] >= 0 || endLine;        bool udWall = upWalls[index + lineSizeVert] >= 0;        if (udWall) wallRep += "_";        else wallRep += " ";        if (lrWall) wallRep += "|";        else wallRep += wallRep;        if (endLine)        {          Console.WriteLine(wallRep);        }        else        {          Console.Write(wallRep);        }        ++index;      }    }    public void Print(int[] upWalls, int columns, int lines)    {      int index = 0;      WriteHeaderMazeLine(columns);      for (int l = 0; l < lines; ++l)      {        if (l == lines - 1)        {          WriteFooterMazeLine(upWalls, index, columns);        }        else        {          WriteMazeLine(upWalls, index, columns);          index += 2 * columns - 1;        }      }    }  }}

I'm afraid I forgot to comment most things. Sorry for the inconvenience... [smile] I'm going to comment everything and put that into a ZIP later.
Two
Two
Here is my implementation. This is my first program written in C#, so I'm not familiar with the standard formatting, apologies if it insults someone's sensibilities.

One thing I'd like to point out is I used a formula to find what two rooms surround a wall. Took me a while to convert that to code from the idea I had in my head, so it is an achievement in my opinion. It only works with the "left-right top-bottom" numbering scheme, the one JWalsh described in the original post.


The MazeMaker class:
using System;public class MazeMaker{    #region local variables    public int height, width, numOfWalls;    private int[] walls;    private bool[] wallsUp;    private int[] roomSets;    #endregion    #region constructors    //default constructor of a 5X5 maze    public MazeMaker()    {        height = 5;        width = 5;        numOfWalls = (width * (height - 1)) + (height * (width - 1));        initArrays();    }    //constuctor which sets a variable height with a constant width of 10    public MazeMaker(int y)    {        width = 10;        height = y;        numOfWalls = (width * (height - 1)) + (height * (width - 1));        initArrays();    }    //constructor which sets both the width and the height    public MazeMaker(int x, int y)    {        width = x;        height = y;        numOfWalls = (width * (height - 1)) + (height * (width - 1));        initArrays();    }    #endregion    #region mazemaking methods    //initializes the arrays    public void initArrays()    {        walls = new int[numOfWalls];                for (int i = 0; i < walls.Length; i++)            walls = i;        //randomization starts here        Random randGenerator = new Random();        double rand;        for (int i = 0; i < walls.Length; i++)        {            rand = randGenerator.NextDouble();            swap(i, (int)(rand * walls.Length));        }        //initializes all walls as up        wallsUp = new bool[numOfWalls];        for (int i = 0; i < wallsUp.Length; i++)            wallsUp = true;        //initializes all rooms in their own set        roomSets = new int[height * width];        for (int i = 0; i < roomSets.Length; i++)            roomSets = i;    }    //helper method for randomizing the walls array    public void swap(int index1, int index2)    {        int tmp = walls[index1];        walls[index1] = walls[index2];        walls[index2] = tmp;    }    //given the wall number, returns the two rooms touching the wall    public void findRoomsFromWall(int wallNum, out int r1, out int r2)    {        int magicNumber = 2 * width - 1;        int reducedWallNum = wallNum % magicNumber;        int rowNumber = wallNum / magicNumber;        if (reducedWallNum < width - 1)        {            r1 = reducedWallNum + magicNumber * rowNumber - (width - 1) * rowNumber;            r2 = r1 + 1;        }        else        {            r1 = wallNum - (width - 1) * (rowNumber + 1);            r2 = r1 + width;        }    }    //checks to see if two rooms occupy the same set    public bool isRoomInSameSet(int r1, int r2)    {        return roomSets[r1] == roomSets[r2];    }    //checks to see if the wall is up    //if it is, checks if the two rooms are in the same set    //if they are, removes the wall and combines the two sets    public void knockdownWall(int wallNum)    {        int room1, room2;        findRoomsFromWall(wallNum, out room1, out room2);        if (!isRoomInSameSet(room1, room2))        {            wallsUp[wallNum] = false;            int r2OldSet = roomSets[room2];            for (int i = 0; i < roomSets.Length; i++)            {                if (roomSets == r2OldSet)                    roomSets = roomSets[room1];            }        }    }    //a check method to see if there are multiple room sets    //returns false when all rooms are in the same set    public bool isMultipleSets()    {        bool answer = false;        int baseSet = roomSets[0];        for(int i = 1; i<roomSets.Length; i++)        {            if (roomSets != baseSet)                answer = true;        }        return answer;    }    //maze generation method    public void generateMaze()    {        int num = 0;        while(isMultipleSets())        {            knockdownWall(walls[num]);            num++;        }    }    #endregion    //method to print the maze    //its convoluted and confusing, but it works well with the implementation I've used    //kudos to you if you can decipher it    public void printMaze()    {        int verticalWallIndex = 0;        int horizontalWallIndex = width - 1;        int rowIndex = 0;        int endPoint;        //draws the roof of the maze        Console.WriteLine(" " + new string('_', width * 2 - 1) + " ");        //this while loop draws each row one at a time by checking to see if the walls are up or not        while (rowIndex < (height - 1))         {            //draws the left side wall            Console.Write("|");            endPoint = horizontalWallIndex + width;            //checks if the first horizontal wall is up or not            if (wallsUp[horizontalWallIndex] == true)                Console.Write("_");            else                Console.Write(" ");            horizontalWallIndex++;            //enters a loop to draw the rest of the row            while (horizontalWallIndex < endPoint)            {                if (wallsUp[verticalWallIndex] == true)                    Console.Write("|");                else                    Console.Write("_");                verticalWallIndex++;                if (wallsUp[horizontalWallIndex] == true)                    Console.Write("_");                else                    Console.Write(" ");                horizontalWallIndex++;            }            //draws the right side wall            Console.WriteLine("|");                          horizontalWallIndex = horizontalWallIndex + width - 1;            verticalWallIndex = verticalWallIndex + width;            rowIndex++;        }        //since the bottom row is different from the others, it is outside the loop        //draws the bottom left corner        Console.Write("|_");        //draws the bottom row, but instead of checking if the horizontal rows are up,        //it just prints an underscore        while (verticalWallIndex < walls.Length)        {            if (wallsUp[verticalWallIndex] == true)                Console.Write("|");            else                Console.Write("_");            verticalWallIndex++;            Console.Write("_");        }        Console.Write("|");    }}



The client program:
using System;class ClientProgram{    public static void Main()    {        Console.Title = "Maze Generator";        Console.WriteLine("Welcome to the Maze Generator.");        Console.WriteLine();        bool loop = true, loop2;         string answer;        int width, height;        Console.WriteLine(Console.WindowHeight);        Console.WriteLine(Console.WindowWidth);        //loop for user input        while (loop)        {            do            {                Console.Write("How many columns? (2-50): ");                Int32.TryParse(Console.ReadLine(), out width);                if (width < 2 || width > 50) Console.Write("Invalid input, try again:");            } while (width < 2 || width > 50);            do            {                Console.Write("How many rows? (2-50): ");                Int32.TryParse(Console.ReadLine(), out height);                if (height < 2 || height > 50) Console.Write("Invalid input, try again: ");            } while (height < 2 || height > 50);            Console.SetWindowSize(width < 40 ? 80 : width * 2 + 2, height > 30 ? height + 5 : 30);            Console.WriteLine();            MazeMaker test = new MazeMaker(width, height);            test.generateMaze();            test.printMaze();            Console.WriteLine();            loop2 = true;            do            {                Console.Write("Create another? (Y)es or (N)o ");                answer = Console.ReadLine();                if (answer[0] == 'n' || answer[0] == 'N')                {                    loop = !loop;                    loop2 = !loop2;                }                else if (answer[0] == 'y' || answer[0] == 'Y')                    loop2 = !loop2;                else                    Console.WriteLine("Invalid answer, try again.");            } while (loop2);        }    }}


Please point out anything you see wrong. Hope this helps someone.
mozie
mozie
First of all, thank you Jeromy for the challenge. It was a good way to get me back in to coding again after such a long long break.

Second thing I would like to mention, is that I did make use of List<> but I treated it like an array at times, so I think I should have either not used it or should have used it properly. (edit:) I read in a post above that we should not use parts of the language that have not been covered, I can go back and fit it to an array if needed.

Last of all I didn't follow the first chapters, I have been coding in C# for a while but I didn't start following this Workshop until I saw the post for the challenge in the 'most recent threads' list. To add to that, I have started to read the chapters from Week-1 just to get a better handle on where everyone else is currently, and to pickup anything that I didn't know from my previous learning of C#.

Here is my code, ~370 lines with 3 classes.

using System;using System.Collections.Generic;using System.Text;namespace mazeGame{    class MazeWall    {        public bool isDown;        public int wallNumber;        public int roomOne;        public int roomTwo;                public MazeWall()        {            isDown = false;            wallNumber = 0;            roomOne = 0;            roomTwo = 0;        }    };    class Maze    {        int mazeWidth;        int mazeHeight;        int totalWalls;        List<int> wallOrder;        List<MazeWall> wallList;        List<List<int>> roomSets;        void generateWallOrder()        {            Random r = new Random();            int tempInt;            while (wallOrder.Count != wallList.Count)            {                tempInt = r.Next(wallList.Count);                if (!wallOrder.Contains(tempInt))                {                    wallOrder.Add(tempInt);                }            }        }        void combineRoomSets(int setOne, int setTwo)        {                        if (setTwo < setOne) // move in to lower set numbers set.            {                int tempI = setOne;                setOne = setTwo;                setTwo = tempI;            }            for(int i=0;i<roomSets[setTwo].Count;++i)            {                roomSets[setOne].Add(roomSets[setTwo]);            }            roomSets[setTwo].Clear();            roomSets[setOne].Sort();        }        void generateMazeFromData()        {            int i = 0;            int x = 0;            int r1set, r2set;            do            {                x = wallOrder;                r1set = getSetIndexFromRoom(wallList[x].roomOne);                r2set = getSetIndexFromRoom(wallList[x].roomTwo);                if (r1set != r2set)                {                    wallList[x].isDown = true;                    combineRoomSets(r1set, r2set);                }                ++i;            } while (i < wallOrder.Count);        }        int getSetIndexFromRoom(int room)        {            int retVal = -1;            for (int i = 0; i < roomSets.Count; ++i)            {                if (roomSets.Contains(room))                {                    retVal = i;                    break;                }            }            return retVal;        }        void generateWallList()        {            int i = 0;            MazeWall aWall;            // each room            for (i = 0; i < (mazeWidth * mazeHeight); ++i)            {                // room to left?                int tempInt = (i + 1);                tempInt = tempInt % mazeWidth;                if (tempInt > 0) // true if we are not in last column in row                {                    // make wall                    aWall = new MazeWall();                    aWall.wallNumber = totalWalls++;                    aWall.roomOne = i;                    aWall.roomTwo = i + 1;                    wallList.Add(aWall);                }                // room to bottom?                tempInt = 1 + (i / mazeWidth); // in last row?                if (tempInt < mazeHeight)                {                    // make wall                    aWall = new MazeWall();                    aWall.wallNumber = totalWalls++;                    aWall.roomOne = i;                    aWall.roomTwo = i + mazeWidth;                    wallList.Add(aWall);                }            }            // loop - next room        }        void generateRoomSets()        {            roomSets.Clear();            int rooms = mazeWidth * mazeHeight;            for (int i = 0; i < rooms; ++i)            {                List<int> newInt = new List<int>();                newInt.Add(i);                roomSets.Add(newInt);            }        }        void getWallsForRoom(int room, out MazeWall wallOne, out MazeWall wallTwo)        {            MazeWall firstWall = null;            MazeWall secondWall = null;            wallOne = firstWall;            wallTwo = secondWall;            foreach (MazeWall m in wallList)            {                if (m.roomOne == room) // roomOne is the origin room for walls                {                    if (firstWall == null)                        firstWall = m;                    else                        secondWall = m;                }            }            wallOne = firstWall;            wallTwo = secondWall;        }        string getViewOfRoom(int room)        {            string retVal = "  ";            MazeWall wallOne, wallTwo;            getWallsForRoom(room, out wallOne, out wallTwo);            bool rightWall = false;            bool bottomWall = false;            int roomDistance;            if(wallOne != null) // the last room has no walls                if (wallOne.isDown == false)                {                    roomDistance = wallOne.roomTwo - wallOne.roomOne;                    if (roomDistance == 1)                        rightWall = true;                    if (roomDistance == mazeWidth)                        bottomWall = true;                }            if(wallTwo != null) // not all rooms have two walls                if (wallTwo.isDown == false)                {                    roomDistance = wallTwo.roomTwo - wallTwo.roomOne;                    if (roomDistance == 1)                        rightWall = true;                    if (roomDistance == mazeWidth)                        bottomWall = true;                }            if ((room / mazeWidth) + 1 == mazeHeight) // always draw floor in last row                bottomWall = true;            if ((1 + room) % mazeWidth == 0) // in last column of row, draw right wall                rightWall = true;            if (rightWall && !bottomWall)                retVal = " |";            if (!rightWall && bottomWall)                retVal = "__";            if (rightWall && bottomWall)                retVal = "_|";            return retVal;        }        public void outputMazeToConsole()        {            int consoleWidth = Console.WindowWidth;            int consoleHeight = Console.WindowHeight;            int targetWidth = (2 * mazeWidth) + 2;            int targetHeight = (2 * mazeHeight) + 2;            if (consoleWidth < targetWidth || consoleHeight < targetHeight)            {                Console.SetWindowSize(targetWidth,targetHeight);            }            int i;            Console.Write(" ");            for (i = 0; i < ((mazeWidth*2) - 1); ++i)                Console.Write("_");            Console.WriteLine("");            i = 0;            for(i=0;i<mazeHeight;++i)            {                Console.Write("|");                for (int j = 0; j < mazeWidth; ++j)                {                    Console.Write(getViewOfRoom((i*mazeWidth) + j));                }                Console.WriteLine("");            }            Console.WriteLine("");        }        public Maze(int width, int height)        {            mazeWidth = width;            mazeHeight = height;            roomSets = new List<List<int>>();            wallList = new List<MazeWall>();            wallOrder = new List<int>();            generateRoomSets();            generateWallList();            totalWalls = wallList.Count;            generateWallOrder();            generateMazeFromData();        }    };    class Program    {        static void displayIntro()        {            string buff = "mazeGame C# challenge, gamedev.net";            Console.WriteLine(buff);            Console.Title = buff;        }        static void displayWRequest()        {            Console.WriteLine("How wide of a maze to make? (Please enter a number from 2-50)");        }        static void displayHRequest()        {            Console.WriteLine("How tall of a maze to make? (Please enter a number from 2-50)");        }        static int inputNumber()        {            int retVal = -1;            string buff = Console.ReadLine();            if(int.TryParse(buff, out retVal))                return retVal;            return -1;        }        static int getInputRange(int minRange, int maxRange)        {            int inputResult;            int userInput = -1;            do            {                inputResult = inputNumber();                if (inputResult == -1)                {                    Console.WriteLine("Please try again. Enter a number from {0} through {1}.", minRange, maxRange);                    userInput = -1;                }                else if (inputResult >= minRange && inputResult <= maxRange)                    userInput = inputResult;                else                {                    Console.WriteLine("Please try again. Enter a number from {0} through {1}.", minRange, maxRange);                    inputResult = -1;                    userInput = -1;                }            } while (userInput == -1);            return userInput;        }        static int getWidthInput()        {            // get width imput            int userWidth = -1;            displayWRequest();            userWidth = getInputRange(2, 50);            return userWidth;        }        static int getHeightInput()        {            // get width imput            int userHeight = -1;            displayHRequest();            userHeight = getInputRange(2, 50);                   return userHeight;        }        static bool inputContinue()        {            bool doContinue = false;            int userInput = -1;            string buff;            do            {                Console.WriteLine("Would you like to do another maze? ('Y'es or 'N'o)");                buff = Console.ReadLine();                buff = buff.ToUpper();                if (buff == "Y" || buff == "YES")                {                    doContinue = true;                    userInput = 1;                }                else if (buff == "N" || buff == "NO")                {                    doContinue = false;                    userInput = 0;                }                else                {                    userInput = -1;                    continue;                }            } while (userInput == -1);            return doContinue;        }        static void Main(string[] args)        {            displayIntro();            bool playing = true;            int userWidth;            int userHeight;            while (playing)            {                userWidth = getWidthInput();                userHeight = getHeightInput();                Console.WriteLine("Generating maze, width {0} x height {1}.", userWidth, userHeight);                Maze maze = new Maze(userWidth, userHeight);                maze.outputMazeToConsole();                 playing = inputContinue();            }            Console.WriteLine("Thanks for playing!\r\n");        }    }}


I'm not really happy with the way that everything looks, but I am happy that everything does actually work (as best as I can tell). My approach to the challenge was to first make all the room's (roomSets), then for each room find if there is room to the right or room to the bottom, and making a wall (in wallList) for each that exists. After the rooms and walls are setup it is the usual permutate the wall indices, cycle through them and combine any roomSets that are not already together.

I thought it was going to be difficult to display the maze, but I found it to be rather simple once I implimented the getWallsForRoom() function (which made it easy to find which walls were still up).

One example of something I don't like about my code (but couldnt come up with a different solution) are the few lines like this: 1 + (index / mazeWidth) which I use to find if it is in the last row of the maze. I think it looks cheap, and isn't exactly clear (so I comment what it does), but it works just fine so I am keeping them.

Thanks for reading!

EDIT: Fixed a small display issue in the source. Added comment about making my lists an array if needed. Removed some text from the end of my post.

[Edited by - mozie on August 7, 2007 6:39:49 PM]
alvarofrank
alvarofrank
Hi all, i have been having problems getting inside this section, i see no direct link to project 1!! :( maybe i am missing other projects too...
i think i am done with my project, but my maze doenst look random at all! its just plane boring, what am i doing wrong? heres the code, there is no need to analize it too much maybe looking at a maze example can help someone tell me whats wrong.
[source lang=c#]using System;using System.Collections.Generic;using System.Text;namespace maze{        class Program    {        public class Settings        {            //gets and sets rows, columns and verifys user input            private int Rows;            private int Colmns;            private int Temp;            public void RowSettings()            {                Console.Write("Please enter the number of rows between 2-50: ");                if (int.TryParse(Console.ReadLine(), out Temp) && Temp >= 2 && Temp <= 50)                    Rows = Temp;                else                    RowSettings();            }            public void Columns()            {                Console.Write("Please enter the number of columns between 2-37: ");                if (int.TryParse(Console.ReadLine(), out Temp) && Temp >= 2 && Temp <= 37)                    Colmns = Temp;                else                    Columns();            }            public int GetRows            {                get { return Rows; }            }            public int GetColmns            {                get { return Colmns; }            }        }        public class MazeGenerator        {            //generates the necesary arrays to work with            private int [] RoomArray;            private int [,] WallsUpArray;            private int [] RoomSetsArray;            private bool[] WallsBoolArray;            private int Walls;            private int Rooms;            public void SetArrays(int a, int b)            {                Rooms = a * b;                Walls = ((2 * a * b) - a - b);                RoomArray = new int[Rooms];                for (int i = 0; i < Rooms; i++)                        RoomArray = i;                                                RoomSetsArray = new int [Rooms];                for (int i = 0; i < Rooms; i++)                    RoomSetsArray = i;                WallsBoolArray = new bool[Walls];                for (int i = 0; i < Walls; i++)                        WallsBoolArray = true;                WallsUpArray = new int [Walls, 2];                int x = 0;                int t = 0;                int c = 0;                int n = (a - 1);                int y = (2 * b - 1);                for (int i = 0; i < y; i++)                {                    for (int e = 0; e < n; e++)                    {                                                WallsUpArray[x, 0] = (x - (t * n));                        WallsUpArray[x, 1] = (x - (c * n) + 1);                        //Console.Write("{0} ", WallsUpArray[x, 0]);                        //Console.Write("{0} ", WallsUpArray[x, 1]);                        x++;                    }                    t++;                    i++;                    if (i == y)                        break;                    for (int g = 0; g < a; g++)                    {                                                WallsUpArray[x, 0] = (x - (t * n));                        WallsUpArray[x, 1] = (x - (c * n) + 1);                        //Console.Write("{0} ", WallsUpArray[x, 0]);                        //Console.Write("{0} ", WallsUpArray[x, 1]);                        x++;                    }                    c++;                }                //Console.WriteLine("");            }            //a random number generator for the knockdown algorithm            private int RandomNumber(int min, int max)            {                Random random = new Random();                //Console.WriteLine("{0}", random.Next(min, max));                return random.Next(min, max);            }            //i am stuck here            public void KnockDown()            {                int StartPoint = RandomNumber(0, (Walls - 1));                Console.Write("{0} out of ", StartPoint);                //for (int i = 0; i < Walls; i++)                    //Console.Write(" {0}", i);                //Console.WriteLine("");                for (int g = 0; g < (Walls - 1); g++)                {                    int Room1 = WallsUpArray[StartPoint, 0];                    int Room2 = WallsUpArray[StartPoint, 1];                    if (!(RoomSetsArray[Room1] == RoomSetsArray[Room2]))                    {                        WallsBoolArray[StartPoint] = false;                        //Console.Write(" {0} ", StartPoint);                        int check = RoomSetsArray[Room1];                        RoomSetsArray[Room1] = RoomSetsArray[Room2];                        for (int d = 0; d < Rooms; d++)                        {                            if (RoomSetsArray[d] == check)                                RoomSetsArray[d] = RoomSetsArray[Room2];                        }                    }                    if (StartPoint == (Walls -1))                        StartPoint = 0;                    else                        StartPoint++;                }            }            public void DrawMaze(int a, int b)            {                int n = (a - 1);                int y = (2 * b - 1);                int x = 0;                Console.WriteLine("");                Console.Write(" ");//used for upper boundry                for (int i = 0; i < a; i++) //used for upper boundry                    Console.Write(" _"); //used for upper boundry                Console.WriteLine(""); //used for upper boundry                for (int i = 0; i < (b - 1); i++)                {                    Console.Write(" |");//border                    if (WallsBoolArray[(x + ((i + 1) * n))])//first wall                        Console.Write("_");                    else                        Console.Write(" ");                    for (int e = 0; e < n; e++)//walls iteration                    {                        if (WallsBoolArray[(x + (i * n))])                            Console.Write("|");                        else                            Console.Write(" ");                        x++;                        if (WallsBoolArray[(x + ((i + 1)* n))])                            Console.Write("_");                        else                            Console.Write(" ");                    }                    Console.Write("|");//border                    Console.WriteLine("");                    x++;                }                Console.Write(" |_");//border                for (int i = 0; i < n; i++)                {                    if (WallsBoolArray[(x + ((b - 1) * n))])//final floor                        Console.Write("|_");                    else                        Console.Write(" _");                    x++;                }                Console.Write("|");//border            }        }                public static void Main(string[] args)        {                        Console.WriteLine("Random Maze Generator by Yolda!");            Settings Setts = new Settings();            Setts.RowSettings();            Setts.Columns();            MazeGenerator MazeGen = new MazeGenerator();            MazeGen.SetArrays(Setts.GetColmns, Setts.GetRows);            MazeGen.KnockDown();            MazeGen.DrawMaze(Setts.GetColmns, Setts.GetRows);            Console.WriteLine("");        }    }}

GameDev Doctor
GameDev Doctor
alvarofrank, It looks like you're just picking a single random number as the start point and going through the maze randomly from there, which means that there are only numberofwalls variations. You need to find a way to randomize the entire order in which you access walls.
I mean, why would you get your medical advice anywhere else?
alvarofrank
alvarofrank
thnks i did as soon is i found out that was my mistale, now my maze looks likes taking WAY too long to load if its a bog one. i used this code:
public void KnockDown()            {                bool[] StartpointList = new bool[Walls];                int StartPoint = RandomNumber(0, (Walls - 1));                int StartPoint2;                StartpointList[StartPoint] = true;                //Console.Write("{0} out of ", StartPoint);                //for (int i = 0; i < Walls; i++)                    //Console.Write(" {0}", i);                //Console.WriteLine("");                for (int g = 0; g < (Walls - 1); g++)                {                    int Room1 = WallsUpArray[StartPoint, 0];                    int Room2 = WallsUpArray[StartPoint, 1];                    if (!(RoomSetsArray[Room1] == RoomSetsArray[Room2]))                    {                        WallsBoolArray[StartPoint] = false;                        //Console.Write(" {0} ", StartPoint);                        int check = RoomSetsArray[Room1];                        RoomSetsArray[Room1] = RoomSetsArray[Room2];                        for (int d = 0; d < Rooms; d++)                        {                            if (RoomSetsArray[d] == check)                                RoomSetsArray[d] = RoomSetsArray[Room2];                        }                    }                        do                        {                            StartPoint2 = RandomNumber(0, (Walls - 1));                        }                        while (StartPoint2 == StartPoint || StartpointList[StartPoint2]);                        StartPoint = StartPoint2;                }            }            public void DrawMaze(int a, int b)            {                int n = (a - 1);                int y = (2 * b - 1);                int x = 0;                Console.WriteLine("");                Console.Write(" ");//used for upper boundry                for (int i = 0; i < a; i++) //used for upper boundry                    Console.Write(" _"); //used for upper boundry                Console.WriteLine(""); //used for upper boundry                for (int i = 0; i < (b - 1); i++)                {                    Console.Write(" |");//border                    if (WallsBoolArray[(x + ((i + 1) * n))])//first wall                        Console.Write("_");                    else                        Console.Write(" ");                    for (int e = 0; e < n; e++)//walls iteration                    {                        if (WallsBoolArray[(x + (i * n))])                            Console.Write("|");                        else                            Console.Write(" ");                        x++;                        if (WallsBoolArray[(x + ((i + 1)* n))])                            Console.Write("_");                        else                            Console.Write(" ");                    }                    Console.Write("|");//border                    Console.WriteLine("");                    x++;                }                Console.Write(" |_");//border                for (int i = 0; i < n; i++)                {                    if (WallsBoolArray[(x + ((b - 1) * n))])//final floor                        Console.Write("|_");                    else                        Console.Write(" _");                    x++;                }                Console.Write("|");//border            }

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.