🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

You may now post code

Started by
40 comments, last by Washu 14 years, 10 months ago
Got a small glitch in my code and could use another set of eyes....

Basically it's a problem with the GeneratePath method and the KnockDownWalls method. I used the DFS algorithm and a two dimensional array of UInt16 setting the bits for WSEN walls etc..

The Init appears to be fine but the code I've written seems to be resetting some walls.

Thanks for any help....

Here's Main.cs

using System;using System.Text.RegularExpressions;namespace Game{	/// <summary>	/// Main Application Class for Game.	/// </summary>	class SimpleMazeApp	{		/// <summary>		/// The main entry point for the application.		/// </summary>		[STAThread]		static int Main(string[] args)		{			int ret_val = 0;			sbyte rowSize = 0;			sbyte colSize = 0;            const string AppName = "JWWicks Maze Factory";            const string Version = "0.99.00";			Maze MyMaze;			Console.Title =  AppName + " - " + Version;			do			{				ShowAppInfo( AppName, Version);				GetMazeDimension( ref rowSize, "Rows (height)", 2, 50 );				GetMazeDimension( ref colSize, "Columns (width)", 2, 50 );				MyMaze = CreateMaze( (uint)rowSize, (uint)colSize );                MyMaze.GeneratePath();				MyMaze.Draw();			}while( !IsAppDone() );			return ret_val;		}		static void ShowAppInfo( string AppName, string Version )		{			Console.WriteLine("{0} - {1}\n\n", AppName, Version);		}		static bool IsAppDone()		{			bool ret_val = false;			string answer = null;					do			{				Console.Write("Would you like to display another Maze: ");				try				{					answer = Console.ReadLine();				}				catch				{					Console.WriteLine("Error: Getting the answer, please try again...");				}			}while( !IsValidAnswer( answer ) );            if (Regex.IsMatch(answer, @"^[Nn]$|^[Nn][Oo]$"))                ret_val = true;            else                Console.Clear();			return ret_val;		}		static void GetMazeDimension( ref sbyte Size, string Dim, sbyte Min, sbyte Max )		{			do			{				Console.Write("Number of {0} in Maze ( {1} to {2} ): ", Dim, Min, Max);				try				{					Size = SByte.Parse(Console.ReadLine());				}				catch				{					Console.WriteLine("Error: Please enter a number from {0} to {1} !", Min, Max);				}			}while( !IsValidSize( Size, Min, Max ) );		}		static bool IsValidAnswer( string s )		{			bool ret_val = false;			ret_val = Regex.IsMatch( s , @"^[Nn]$|^[Nn][Oo]$|^[Yy]$|^[Yy][Ee][Ss]$");			if (!ret_val)				Console.WriteLine("Please enter either y[es] or n[o]...");			return ret_val;		}		static bool IsValidSize( sbyte Val, sbyte Min, sbyte Max )		{			bool ret_val = false;			if( Val < Min | Val > Max )				Console.WriteLine("Error: Value must be from {0} to {1}.", Min, Max);			else				ret_val = true;						return ret_val;		}		static Maze CreateMaze( uint r, uint c )		{			Maze maze = new Maze(r, c);			return maze;		}	}}


And here's the Maze.cs file...
using System;using System.Collections;using System.Threading;namespace Game{	public class Maze	{ 		public Maze()		{            this.m_columns = 3;            this.m_rows = 3;            Initialize();		}        public Maze(uint rows, uint columns)		{			if( rows > 0 && columns > 0 )			{                this.m_rows = rows;                this.m_columns = columns;                Initialize();			}			else				throw( new InvalidMazeDimensionException() );		}        public void GeneratePath()        {            Stack cellStack = new Stack();            Random randCell = new Random();            uint cellsVisited = 0;            UInt16 curCellRow = 0, curCellCol = 0, nextCellRow = 0, nextCellCol = 0;            UInt16 curCellNo = (UInt16)randCell.Next((int)m_totalRooms);            uint nextCellNo = 0;            //If this isn't true something terribly wrong has happened            if (FindRoomPos(curCellNo, ref curCellRow, ref curCellCol))            {                this.m_startRoom = curCellNo;                while (cellsVisited < m_totalRooms)                {                    if (FindNeighborWithWallsUp(curCellNo, ref nextCellNo))                    {                        FindRoomPos(nextCellNo, ref nextCellRow, ref nextCellCol);                        KnockDownWall(curCellRow, curCellCol, nextCellRow, nextCellCol);                        cellStack.Push(curCellNo);                        curCellNo = (UInt16)nextCellNo;                        cellsVisited++;                     }                    else                    {                        curCellNo = (UInt16)cellStack.Pop();                    }                }            }            else                throw ( new InvalidRoomNoException());        }        public bool HasWallsUp(UInt16 cRow, UInt16 cCol)        {            bool ret_val = false;            if((m_rooms[cRow, cCol] & ANY_WALLS_UP) > 0)                ret_val = true;            return ret_val;        }        public void Draw()        {            int roomSet = 1;            for (int r = 0; r < this.m_rows; r++)            {                for (int c = 0; c < this.m_columns; c++)                {                    //Console.WriteLine("No: {0} Val: {1} or {1,9:X8}", roomSet - 1, this.m_rooms[r, c]);                    roomSet++;                    if ((this.m_rooms[r, c] & S_WALL_UP) != 0 || (r == this.m_rows - 1))                        Console.Write("_");                    else                        Console.Write(" ");                    if ((this.m_rooms[r, c] & E_WALL_UP) != 0 || (c == this.m_columns - 1))                        Console.Write("|");                    else                        Console.Write(" ");                }                Console.Write("\n");            }        }        public uint Rooms        {            get { return m_totalRooms; }        }        public uint Walls        {            get { return m_totalWalls; }        }        protected void Initialize()        {            this.m_totalRooms = this.m_rows * this.m_columns;             this.m_totalWalls = this.m_totalRooms + ((this.m_rows - 1) * (this.m_columns - 1) - 1);            this.m_rooms = new UInt16[this.m_rows, this.m_columns];            this.m_roomSet = new uint[this.m_totalRooms];            uint roomSet = 1;            uint mask = 0;            for (int r = 0; r < this.m_rows; r++)                for (int c = 0; c < this.m_columns; c++)                {                    mask = ALL_WALLS_UP;                    if (r == 0)                        mask ^= N_BORDER_UP | N_WALL_UP;                    if (c == 0)                        mask ^= W_BORDER_UP | W_WALL_UP;                    if (r == this.m_rows - 1)                        mask ^= S_BORDER_UP | S_WALL_UP;                    if (c == this.m_columns - 1)                        mask ^= E_BORDER_UP | E_WALL_UP;                    this.m_rooms[r,c] = (ushort)(mask);                    this.m_roomSet[roomSet -1] = roomSet++;                 }        }        protected void KnockDownWall(UInt16 cRow, UInt16 cCol, UInt16 nRow, UInt16 nCol)        {            switch (cRow == nRow)            {                case true:                    if (cCol > nCol)                    {                        this.m_rooms[cRow, cCol] ^= W_WALL_UP;                        this.m_rooms[nRow, nCol] ^= E_WALL_UP;                    }                    else                    {                        this.m_rooms[cRow, cCol] ^= E_WALL_UP;                        this.m_rooms[nRow, nCol] ^= W_WALL_UP;                    }                    break;                default:                    switch (cCol == nCol)                    {                        case true: if (cRow > nRow)                            {                                this.m_rooms[cRow, cCol] ^= N_WALL_UP;                                this.m_rooms[nRow, nCol] ^= S_WALL_UP;                            }                            else                            {                                this.m_rooms[cRow, cCol] ^= S_WALL_UP;                                this.m_rooms[nRow, nCol] ^= N_WALL_UP;                            } break;                        default: break;                    }                    break;            }        }        protected bool FindRoomNo(UInt16 cRow, UInt16 cCol, ref uint cRoomNo)        {            bool ret_val = false;            cRoomNo = 0;            if ((cRow >= 0 && cRow < this.m_rows) && (cCol >= 0 && cCol < this.m_columns))            {                cRoomNo = (cRow * this.m_columns) + cCol;                ret_val = true;            }            return ret_val;        }        protected bool FindRoomPos(uint roomNo, ref UInt16 row, ref UInt16 column)        {            bool ret_val = false;            if (roomNo >= 0 && roomNo < this.m_totalRooms)            {                row = (UInt16)(roomNo / this.m_columns);                column = (UInt16)(roomNo % this.m_columns);                ret_val = true;            }            return ret_val;        }        protected bool FindNeighborWithWallsUp(uint cCellNo, ref uint nCellNo)        {            bool ret_val = false;            uint rTemp = 0;            UInt16 curCellRow = 0, curCellCol = 0, nextCellRow = 0, nextCellCol = 0;            uint[] neighbors = new uint[4];            int x;            if (cCellNo < this.m_totalRooms)            {                FindRoomPos(cCellNo, ref curCellRow, ref curCellCol);                switch (rTemp = NumberOfNeighbors(curCellRow, curCellCol, ref neighbors))                {                    case 2:                    case 3:                    case 4: Random rand = new Random();                        int i = (int)rand.Next((int)(rTemp - 1));                        for (x = i; x < rTemp && !ret_val; x++)                            if (FindRoomPos(neighbors[x], ref nextCellRow, ref nextCellCol) && HasWallsUp(nextCellRow, nextCellCol))                            {                                FindRoomNo(nextCellRow, nextCellCol, ref nCellNo);                                if (this.m_roomSet[nCellNo] != 0)                                {                                    this.m_roomSet[nCellNo] = 0;                                    ret_val = true;                                }                            }                        for (x = i - 1; x > -1 && !ret_val; x--)                            if (FindRoomPos(neighbors[x], ref nextCellRow, ref nextCellCol) && HasWallsUp(nextCellRow, nextCellCol))                            {                                FindRoomNo(nextCellRow, nextCellCol, ref nCellNo);                                if (this.m_roomSet[nCellNo] != 0)                                {                                    this.m_roomSet[nCellNo] = 0;                                    ret_val = true;                                }                            }                        break;                    default: break;                }            }            return ret_val;        }        protected uint NumberOfNeighbors(uint cRow, uint cCol, ref uint[] nArray)        {            uint ret_val = 0;            uint c = 0;            uint curRoomNo = 0;            // Either top row or bottom row corners            if (((cRow % (m_rows - 1)) == 0) && ((cCol % (m_columns - 1)) == 0))                ret_val = 2;            // Outer edge middle cells            else if (((cRow % (m_rows - 1)) == 0) || ((cCol % (m_columns - 1)) == 0))                ret_val = 3;            else // Somewhere in the middle                ret_val = 4;            if (FindRoomNo((UInt16)(cRow - 1), (UInt16)cCol, ref curRoomNo))                nArray[c++] = curRoomNo;            if (FindRoomNo((UInt16)(cRow + 1), (UInt16)cCol, ref curRoomNo))                nArray[c++] = curRoomNo;            if (FindRoomNo((UInt16)cRow, (UInt16)(cCol - 1), ref curRoomNo))                nArray[c++] = curRoomNo;            if (FindRoomNo((UInt16)cRow, (UInt16)(cCol + 1), ref curRoomNo))                nArray[c++] = curRoomNo;            return ret_val;        }		protected uint m_totalRooms;		protected uint m_totalWalls;		protected uint m_rows;		protected uint m_columns;		protected UInt16[,] m_rooms;        protected uint[] m_roomSet;        protected uint m_startRoom, m_finishRoom;        protected const UInt16 N_WALL_UP = 0x01;        protected const UInt16 E_WALL_UP = N_WALL_UP << 1;        protected const UInt16 S_WALL_UP = E_WALL_UP << 1;        protected const UInt16 W_WALL_UP = S_WALL_UP << 1;        protected const UInt16 ALL_WALLS_UP = N_WALL_UP | E_WALL_UP | S_WALL_UP | W_WALL_UP;        protected const UInt16 ANY_WALLS_UP = ALL_WALLS_UP;        protected const UInt16 N_BORDER_UP = N_WALL_UP << 4;        protected const UInt16 E_BORDER_UP = N_BORDER_UP << 1;        protected const UInt16 S_BORDER_UP = E_BORDER_UP << 1;        protected const UInt16 W_BORDER_UP = S_BORDER_UP << 1;        protected const UInt16 ANY_BORDERS_UP = N_BORDER_UP | E_BORDER_UP | S_BORDER_UP | W_BORDER_UP;    }	class InvalidMazeDimensionException : Exception	{		public InvalidMazeDimensionException(){}		public InvalidMazeDimensionException( string msg ) : base( msg ){}		public InvalidMazeDimensionException( string msg, Exception e ): base( msg, e ){}	}    class InvalidRoomNoException : Exception    {        public InvalidRoomNoException() { }        public InvalidRoomNoException(string msg) : base(msg) { }        public InvalidRoomNoException(string msg, Exception e) : base(msg, e) { }    } }
Computers are useless, they can only give you answers. - Pablo Picasso
Advertisement
Quote: Original post by Emmanuel Deloget
I tried to implement this as well;


You might want to consider a different color scheme; I'm RG color blind and it took me a while to realize that the visited background color and the non-visited background color were different.
I was going to do a bit of refactoring before I posted this but I don't really have the time at the moment and I'm falling behind in the workshop so since the deadline is almost up here's my source code:

using System;using System.Collections.Generic;using System.Text;namespace ConsoleMazeGenerator{    class Program    {        static void GetNumber(string question, int min, int max, ref int num)        {            bool incomplete = true;            Console.Write(question);                        while (incomplete)            {                if (!int.TryParse(Console.ReadLine(), out num))                    Console.WriteLine("You did not enter a number");                if(num < min || num > max)                {                    Console.Write("Please enter a number between " + min + " and " + max + ": ");                }                else                {                    incomplete = false;                }            }               }        static bool Repeat()        {            bool cont = true;            bool answered = false;            while (!answered)            {                string question = "Create another maze ([y]es | [n]o): ";                Console.Write(question);                string response = Console.ReadLine();                response = response.ToLower();                switch (response)                {                    case "yes":                        cont = true;                        answered = true;                        break;                    case "y":                        cont = true;                        answered = true;                        break;                    case "no":                        cont = false;                        answered = true;                        break;                    case "n":                        cont = false;                        answered = true;                        break;                    default:                        Console.WriteLine("Invalid input");                        answered = false;                        break;                }            }            return cont;        }        static void Main(string[] args)        {            string title = "Welcome to the C# Random Maze Generator";            Console.Title = title;            Console.WriteLine(title);            Console.WriteLine();                                    do            {                const int minValue = 2;                const int maxValue = 50;                int rows = 0;                int columns = 0;                string rQuestion = "Enter the number of rows" + "(" + minValue + "-" + maxValue.ToString() + "): ";                GetNumber(rQuestion, minValue, maxValue, ref rows);                string cQuestion = "Enter the number of columns" + "(" + minValue + "-" + maxValue.ToString() + "): ";                GetNumber(cQuestion, minValue, maxValue, ref columns);                int numRooms = rows * columns;                int numWalls = ((columns - 1) * rows) + ((rows - 1) * columns);                int[] roomArray = new int[numRooms];                for (int i = 0; i < numRooms; i++)                {                    roomArray = i;                }                Wall[] wallArray = new Wall[numWalls];                for (int i = 0; i < wallArray.Length; i++)                {                    wallArray = new Wall();                }                               //assign two rooms to each wall                int rowWall = columns - 1;                int columnWall = columns;                int room = 0;                int walls = 0;                while (true)                {                    //the vertical walls                    for (int i = 0; i < rowWall; i++)                    {                        wallArray[walls].room1 = room;                        if (room != numRooms)                            wallArray[walls].room2 = room + 1;                        else                            wallArray[walls].room2 = room;                        if (room < numRooms)                            room++;                        walls++;                    }                    //break out of loop if we have gone through all the walls                         if (walls >= numWalls - 1)                        break;                    //horizontal walls                    for (int j = 0; j < columnWall; j++)                    {                        if (room < numRooms)                            room++;                        wallArray[walls].room1 = room - columns;                        wallArray[walls].room2 = room;                        walls++;                    }                    room = room - (columns - 1);//adjust the room number for the vertical walls                }                //add each room to a default set                int[][] roomSets = new int[numRooms][];                for (int i = 0; i < numRooms; i++)                {                    roomSets = new int[1];                }                //assign a default room to each set                for (int i = 0; i < numRooms; i++)                {                    for (int j = 0; j < roomSets.Length; j++)                    {                        roomSets[j] = i;                    }                }                                //produces the indexes that are used to access wallArray                int[] wallSeq = new int[numWalls];                                //default numbers for the wallSeq array                for (int i = 0; i < numWalls; i++)                {                    wallSeq = i;                }                //randomize the sequence                int temp = 0;                Random rGen = new Random();//outside for loop for extra randomness                for (int i = 0; i < numWalls; i++)                {                    int rNum = rGen.Next(numWalls);                    temp = wallSeq;                    wallSeq = wallSeq[rNum];                    wallSeq[rNum] = temp;                }                /*                for (int i = 0; i < wallSeq.Length; i++)                    Console.Write(wallSeq + " ");                */                /*Console.WriteLine();                foreach(int i in wallSeq)                    Console.Write(i + " ");*/                //knock down the walls                for (int i = 0; i < numWalls; i++)                {                    int setNumber1 = roomArray[wallArray[wallSeq].room1];                    int setNumber2 = roomArray[wallArray[wallSeq].room2];                                        if (setNumber1 != setNumber2)                    {                        wallArray[wallSeq].isWallUp = false;                        //create a temporary array to store all the rooms that each room set contains                        int[] tempArray = new int[roomSets[setNumber1].Length + roomSets[setNumber2].Length];                                                //copy all rooms to the tempArray                        Array.Copy(roomSets[setNumber1], tempArray, roomSets[setNumber1].Length);                        Array.ConstrainedCopy(roomSets[setNumber2], 0, tempArray, roomSets[setNumber1].Length, roomSets[setNumber2].Length);                                                roomSets[setNumber1] = tempArray;                        //roomSet[setNumber1] now holds all the rooms that are connected                        //set all elements in roomArray to equal setNumber1                        for(int j = 0; j < roomSets[setNumber1].Length; j++)                        {                            roomArray[roomSets[setNumber1][j]] = setNumber1;                        }                    }                }                /*                int c = 0;                foreach (Wall i in wallArray)                {                    Console.WriteLine();                    Console.WriteLine("wall up down: {0}", c);                    Console.WriteLine();                    Console.WriteLine("isUp: {0}", i.isWallUp);                    Console.WriteLine("room1: {0}", i.room1);                    Console.WriteLine("room2: {0}", i.room2);                    c++;                }*/                                //draw the maze                int r = 0;//room we're in                int row = 0;                                //the top of the maze                string top = new string('_', columns + (columns - 1));                top = " " + top;                Console.WriteLine(top);                while (r < numRooms - 1)                {                    Console.Write("|");//draw the first piece of each row                    for (int i = 0; i < columns; i++)                    {                        //only draw the 'south' wall on the last column                        if (i == columns - 1 && r < numRooms -1)                        {                            //Console.WriteLine("d");                            int sWall = r + (columns - 1) * (row + 1);                            if (wallArray[sWall].isWallUp)                                Console.Write("_");                            else                                Console.Write(" ");                            //always draw the last vertical line                            Console.Write("|");                            r++;                            row++;                        }                        //if we are at the last room all walls have been accounted for                        //draw the final piece                        else if (r == numRooms - 1)                        {                            Console.Write("_|");                        }                        //if we are on the last row only draw the 'east' wall                        else if (row == rows - 1 && r < numRooms - 1)                        {                            Console.Write("_");                            int eWall = r + (columns - 1) * row;                            if (wallArray[eWall].isWallUp)                                Console.Write("|");                            else                                Console.Write("_");                            r++;                        }                        else//draw a 'south' and 'east' wall                        {                            int sWall = r + (columns - 1) * (row + 1);                            int eWall = r + (columns - 1) * row;                            if (wallArray[sWall].isWallUp)                                Console.Write("_");                            else                                Console.Write(" ");                            if (wallArray[eWall].isWallUp)                                Console.Write("|");                            else                                Console.Write("_");                            r++;                        }                    }                    Console.WriteLine();                }                                        } while (Repeat());        }    }    class Wall    {        public bool isWallUp;        public int room1;        public int room2;        public Wall()        {            isWallUp = true;            room1 = 0;            room2 = 0;        }    }}//Console.WriteLine("Height: {0}", Console.BufferHeight);//Console.WriteLine("Width: {0}", Console.BufferWidth);


There is one thing which I have not achieved from the project requirements and that is making sure the console buffer is big enough to display large mazes, 40 * 40 and 50 * 50 mazes come out looking a mess, theres some code commented out at the bottom which is needed to help complete this aspect of the project but I would also need to look out the methods required to set the buffer on msdn.

I am aware my implementation is not the best but critiques and comments would be welcome.
How about them apples?
I finally finished up the project this evening, I got most of it working over the weekend, and I got the buffer resizing stuff working tonight.

Thanks JWalsh for devising an interesting and challenging (but very possible) project!

I think the main problem with my code is that it isn't very object-oriented and I mainly just use static methods :/

Also my method of creating a random permutation of walls seems like an ugly hack - I just keep generating random numbers until I get one that hasn't been assigned already!

Now that I have finished it for myself, I'll look at everyone else's code and identify any ways that I can improve my design. I would also be very grateful for any criticism or advice! On to project 2 :D

[source lang=c#]using System;using System.Collections;class MazeGenerator{    const int MINIMUM = 2;    const int MAXIMUM = 50;    public static void Main()    {        Console.WriteLine("\nWelcome to The C# Maze Generator Program!\n\n");        Console.Title = "Welcome to The C# Maze Generator Program!";        bool quit = false;        int defaultBufferWidth = Console.BufferWidth;        int defaultBufferHeight = Console.BufferHeight;        int defaultWindowWidth = Console.WindowWidth;        int defaultWindowHeight = Console.WindowHeight;        while (!quit)        {            Console.WindowWidth = defaultWindowWidth;            Console.BufferWidth = defaultBufferWidth;            Console.WindowHeight = defaultWindowHeight;            Console.BufferHeight = defaultBufferHeight;            Console.Write("Enter number of rows ({0}-{1}):", MINIMUM, MAXIMUM);            int rows = GetDimension();            Console.Write("Enter number of columns ({0}-{1}):", MINIMUM, MAXIMUM);            int columns = GetDimension();            Console.Title = "Random Maze Generation (" + columns + "x" + rows + ")";            //Resize console buffer according to input            int targetWidth = (columns * 2) + 2;            if (targetWidth > Console.LargestWindowWidth)                targetWidth = Console.LargestWindowWidth;                        int targetHeight = (rows * 2) + 2;            if (targetHeight > Console.LargestWindowHeight)                targetHeight = Console.LargestWindowHeight;            if (targetWidth < defaultWindowWidth)            {                Console.WindowWidth = defaultWindowWidth;                Console.BufferWidth = defaultBufferWidth;            }            else            {                Console.WindowWidth = targetWidth;                Console.BufferWidth = targetWidth;            }            if (targetHeight < defaultWindowHeight)            {                Console.WindowHeight = defaultWindowHeight;                Console.BufferHeight = defaultBufferHeight;            }            else            {                Console.WindowHeight = targetHeight;                Console.BufferHeight = targetHeight;            }            int numberOfRooms = rows * columns;            int numberOfWalls = (columns * (rows - 1)) + (rows * (columns - 1));            Wall[] wallList = new Wall[numberOfWalls];            for (int i = 0; i < numberOfWalls; ++i)            {                wallList = new Wall();            }            AssignRooms(wallList, numberOfRooms, rows, columns);            int[] wallsUp = new int[wallList.Length];            RandomizeWalls(wallsUp);            KnockDownWalls(wallList, wallsUp, numberOfRooms);            DrawMaze(wallList, rows, columns);            Console.WriteLine("Nice maze! Would you like to create another? ([y]es|[n]o):");            string response = Console.ReadLine();            response = response.ToLower();            while ((response != "y") && (response != "yes") && (response != "n") && (response != "no"))            {                Console.WriteLine("Invalid response. Please type y/yes if you want another maze, or n/no to quit.");                response = Console.ReadLine();                response = response.ToLower();            }            if ((response == "n") || (response == "no"))            {                quit = true;            }            else            {                Console.Clear();            }        }    }    static int GetDimension()    {        int input = 0;        bool isInputValid = false;        while (!isInputValid)        {            if (!Int32.TryParse(Console.ReadLine(), out input))            {                Console.WriteLine("Please enter a number between {0} and {1} (inclusive)", MINIMUM, MAXIMUM);            }            else if (input < MINIMUM || input > MAXIMUM)            {                Console.WriteLine("Sorry, that's an invalid number. Please try a number between {0} and {1}.", MINIMUM, MAXIMUM);            }            else            {                isInputValid = true;            }        }        return input;    }    static void AssignRooms(Wall[] walls, int numberOfRooms, int rows, int columns)    {        int horizontalRoomCounter = 0; //used to keep track of rooms being assigned to vertical walls        int verticalRoomCounter = 0; //used to keep track of rooms being assigned to horizontal walls        int verticalWalls = columns - 1;         int verticalWallCounter = 0; //used to determine when the end of a row of vertical walls is reached        int horizontalWalls = columns;        int horizontalWallCounter = 0; //used to determine when the end of a row of horizontal walls is reached        bool isVerticalWallBeingAssigned = true;        for (int i = 0; i < walls.Length; ++i)        {            if (isVerticalWallBeingAssigned) //assign the two rooms being divided to a vertical wall            {                walls.room1 = horizontalRoomCounter;                walls.room2 = horizontalRoomCounter + 1;                ++horizontalRoomCounter;                ++verticalWallCounter;                if (verticalWallCounter == verticalWalls) //finished assigning rooms to a row of vertical walls                {                    verticalWallCounter = 0;                    ++horizontalRoomCounter; //skip the second "edge" wall                    isVerticalWallBeingAssigned = false;                }            }            else //assign the two rooms being divided to a horizontal wall            {                walls.room1 = verticalRoomCounter;                walls.room2 = verticalRoomCounter + columns; //add the number of walls to determine the index of the room directly below                ++verticalRoomCounter;                ++horizontalWallCounter;                if (horizontalWallCounter == horizontalWalls) //finished assigning rooms to a row of horizontal walls                {                    horizontalWallCounter = 0;                    isVerticalWallBeingAssigned = true;                }            }        }    }    static void RandomizeWalls(int[] wallsUp)    {        int[] allNumbers = new int[wallsUp.Length];                for (int i = 0; i < wallsUp.Length; ++i)        {            allNumbers = i;        }        Random myRandom = new System.Random();        for (int i = 0; i < wallsUp.Length; ++i)        {            int randomIndex = 0;            do            {                randomIndex = myRandom.Next(0, wallsUp.Length);            }            while (allNumbers[randomIndex] == -1);            wallsUp = allNumbers[randomIndex];            allNumbers[randomIndex] = -1;        }            }    static void KnockDownWalls(Wall[] walls, int[] wallsUp, int numberOfRooms)    {        int[] roomSets = new int[numberOfRooms]; //each index represents a room, a number is stored at a room's index to specify what set the room belongs to        for (int i = 0; i < numberOfRooms; ++i) //set each room to be alone in their own set        {            roomSets = i;        }        for (int i = 0; i < walls.Length; ++i) //for each wall, knock it down if the 2 rooms being divided are in different sets        {            int set1 = roomSets[walls[wallsUp].room1]; //find what room set the first room of the wall referred to by wallsUp belongs to            int set2 = roomSets[walls[wallsUp].room2]; //find what room set the second room of the wall referred to by wallsUp belongs to            if (set1 != set2) //if the two rooms are in different sets            {                walls[wallsUp].isUp = false; //knock down the wall                for (int j = 0; j < roomSets.Length; ++j) //go through each room set and assign all the rooms in the second set to the first set                {                    if (roomSets[j] == set2)                    {                        roomSets[j] = set1;                    }                }            }        }    }    static void DrawMaze(Wall[] walls, int rows, int columns)    {        //draw top edge        Console.WriteLine(new string('_', columns * 2));        int verticalWallCounter = 0;        int horizontalWallCounter = columns - 1;        for (int i = 0; i < (rows - 1); ++i)        {            Console.Write("|");            for (int j = 0; j < columns; ++j)            {                if (walls[horizontalWallCounter].isUp)                {                    Console.Write("_");                }                else                {                    Console.Write(" ");                }                ++horizontalWallCounter;                if (j < (columns - 1)) //one less vertical wall than horizontal wall                {                    if (walls[verticalWallCounter].isUp)                    {                        Console.Write("|");                    }                    else                    {                        Console.Write("_");                    }                    ++verticalWallCounter;                }                else                {                    Console.WriteLine("|"); //draw the right edge of the maze and progress to the next line                }            }            horizontalWallCounter += (columns - 1);            verticalWallCounter += columns;        }        //draw the bottom row of the maze        Console.Write("|_");        for (int i = 0; i < (columns - 1); ++i)        {            if (walls[verticalWallCounter].isUp)            {                Console.Write("|");            }            else            {                Console.Write("_");            }            ++verticalWallCounter;            Console.Write("_");        }        Console.WriteLine("|");    }}class Wall{    public bool isUp;    public int room1;    public int room2;    public Wall()    {        isUp = true;    }}
OK, finally completed the Project 1 Maze Generator. I'm doing the 1 year late C++ Workshop and C# Workshop in batches where I at times focus more on the other et cetera and I wanted to complete the C++ Project 1 before I threw my hands on the C# one.

So although a little late, here is my sourcecode. My first try at it came out as a mess and I scratched it since debugging got hard. My second try, was IMO quite easy to read, but not that flexible. My last and final try is probably something in the middle of those two.

Instead of single dimension arrays, I'm cheating a bit with List.

using System;using System.Collections.Generic;using System.Text;namespace Maze{    class Program    {        static void Main(string[] args)        {            int width = 0;            int height = 0;            const string DEFAULT_TITLE = "Random Maze Generator";            if (args.GetLength(0) > 1)            {                width = Convert.ToInt16(args[0]);                height = Convert.ToInt16(args[1]);            }            Console.Write("Welcome to Random C# Maze Generator!\n\n\n");            Console.Title = DEFAULT_TITLE;            while(true)            {                // For simplicity, these contain crude error checking.                if (width == 0)                {                    Console.Write("Enter the width of the maze <2-50>: ");                    width = Convert.ToInt16(Console.ReadLine());                }                if (CheckInput(width))                {                    // Bad input, start over.                    Console.Write("You need to type a number between 2 and 50.\n");                    width = 0;                    continue;                }                if (height == 0)                {                    Console.Write("Enter the height of the maze <2-50>: ");                    height = Convert.ToInt16(Console.ReadLine());                }                if (CheckInput(height))                {                    // Bad input, start over.                    Console.Write("You need to type a number between 2 and 50.\n");                    height = 0;                    continue;                }                Console.Title = "Random Maze Generator (" + width + "x" + height + ")";                Console.SetBufferSize(200,200);                Maze Maze = new Maze(width, height);                Maze.View();                Console.Write("\n");                Console.Write("Would you like to create another? <[y]es|[n]o>: ");                string answer = Console.ReadLine();                answer.Trim().ToLower();                if (answer == "y" || answer == "yes")                {                    width = 0;                    height = 0;                    Console.Title = DEFAULT_TITLE;                    continue;                }                else                {                    break;                }            }        }        static bool CheckInput(int num)        {            if (num > 1 && num <= 50)            {                return false;            }            return true;        }    }}

using System;using System.Collections.Generic;using System.Text;namespace Maze{    enum WallType { SouthWall, EastWall };    class Maze    {        int m_width;        int m_height;        int m_area;        int numWalls;        int numCells;        List<Cell> Cells;        List<Wall> Walls;        Cell[][] ConnectedCells;                public Maze(int width, int height)        {            m_width = width;            m_height = height;            m_area = m_width * m_height;            Cells = new List<Cell>();            Walls = new List<Wall>();            Initialize();            KnockdownWalls();        }        void Initialize()        {            numCells = m_area;            numWalls = (numCells * 2) - m_width - m_height;            /* Repeats a cycle of adding m_width -1 x EastWalls and then m_width x Southwalls             * until numWalls is done looping.             */            int wallsPerRow = (m_width * 2) - 1;            int rowNumber = 0;            int cell1 = 0;            int cell2 = 0;            int counter = 0;            for (int i = 0; i < numWalls; i++)            {                // Calculate the current row the wall is on.                for (int j = 1; j <= m_height; j++)                {                    if ((i) < (j * wallsPerRow))                    {                        rowNumber = j;                        break;                    }                }                if (counter < (m_width - 1))                {                    // Foreach row, the cell1 index is wallIndex - ( += m_width-1), starting at 0. (0, m_width -1, etc)                    cell1 = i - ((rowNumber - 1) * (m_width - 1));                    cell2 = cell1 + 1;                    Walls.Add(new Wall(WallType.EastWall, i, cell1, cell2));                    counter++;                }                else                {                    // Foreach row, the cell2 index is wallIndex + (+= m_width-1), starting at +1. (1, 1 - (m_width-1), etc)                    cell2 = i + (1 - ((rowNumber - 1) * (m_width - 1)));                    cell1 = cell2 - m_width;                    Walls.Add(new Wall(WallType.SouthWall, i, cell1, cell2));                    counter++;                }                if (counter >= ((m_width * 2) - 1))                {                    counter = 0;                }            }            /* Setup cells. */            ConnectedCells = new Cell[numCells][];            for (int i = 0; i < numCells; i++)            {                Cells.Add(new Cell(i));                ConnectedCells = new Cell[numCells];                ConnectedCells[0] = Cells;            }            AddCellReferencesToWalls();            // Permute walls.            Shuffle.List(Walls);        }        void AddCellReferencesToWalls()        {            foreach (Wall Wall in Walls)            {                // Adds the correct cell index to be referenced from each of the walls.                int cell1 = Wall.Cell1;                Cells[cell1].SetWall(Wall);            }        }        void KnockdownWalls()        {            for(int i = 0; i < Walls.Count; i++)            {                if(CheckPath(i))                {                    // Skip knockdown, move along.                    continue;                }                // Knock down wall, add and clean up.                Walls.IsUp = false;                int cell1 = Walls.Cell1;                int cell2 = Walls.Cell2;                int cellSetNum1 = Cells[cell1].BelongsToCellSet;                int cellSetNum2 = Cells[cell2].BelongsToCellSet;                MoveCellToAnotherSet(cell2, Cells[cell1].BelongsToCellSet);            }        }        void MoveCellToAnotherSet(int cellIndex, int targetSet)        {            int oldSetMember = Cells[cellIndex].BelongsToCellSet;            //Find a new space for it in the target set.            for (int i = 0; i < ConnectedCells[targetSet].GetLength(0); i++)            {                if (ConnectedCells[targetSet] == null) // empty space, insert                {                    for (int j = 0; j < ConnectedCells[oldSetMember].GetLength(0); j++)                    {                        if (ConnectedCells[oldSetMember][j] != null)                        {                            ConnectedCells[targetSet] = ConnectedCells[oldSetMember][j]; <span class="cpp-comment">// Add the reference</span><br>                            ConnectedCells[targetSet].BelongsToCellSet = targetSet;      <span class="cpp-comment">// Update information</span><br>                            ConnectedCells[oldSetMember][j] = null;                             <span class="cpp-comment">// Delete old reference in old set</span><br>                        }<br>                    }<br>                    <span class="cpp-keyword">break</span>;<br>                }<br>            }<br>        }<br><br>        <span class="cpp-keyword">bool</span> CheckPath(<span class="cpp-keyword">int</span> wallIndex)<br>        {<br>            <span class="cpp-keyword">int</span> cell1 = Walls[wallIndex].Cell1;<br>            <span class="cpp-keyword">int</span> cell2 = Walls[wallIndex].Cell2;<br>            <span class="cpp-keyword">int</span> cellSetNum1 = Cells[cell1].BelongsToCellSet;<br>            <span class="cpp-keyword">int</span> cellSetNum2 = Cells[cell2].BelongsToCellSet;<br><br>            <span class="cpp-keyword">if</span> (Cells[cell1].BelongsToCellSet == Cells[cell2].BelongsToCellSet)<br>            {<br>                <span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;<br>            }<br>            <span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;<br>        }<br><br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">void</span> View()<br>        {<br>            Console.Write(<span class="cpp-literal">"\n"</span>);<br>            <span class="cpp-keyword">int</span> newLineCounter = <span class="cpp-number">1</span>;<br>            string topBorder = <span class="cpp-keyword">new</span> System.String('_', m_width * <span class="cpp-number">2</span>);<br>            Console.Write(topBorder + <span class="cpp-literal">"\n"</span>);<br>            <span class="cpp-keyword">for</span>(<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i &lt; Cells.Count; i++)<br>            {<br>                <span class="cpp-comment">// Takes care of left border.</span><br>                <span class="cpp-keyword">if</span> (newLineCounter == <span class="cpp-number">1</span>)<br>                {<br>                    Console.Write(<span class="cpp-literal">"|"</span>);<br>                }<br>                <span class="cpp-keyword">if</span> (i &gt; (m_area - (m_width +<span class="cpp-number">1</span>)))<br>                {<br>                    Console.Write(<span class="cpp-literal">"_"</span>);<br>                }<br>                <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> (Cells<span style="font-weight:bold;">.SouthWall.IsUp)<br>                    Console.Write(<span class="cpp-literal">"_"</span>);<br>                <span class="cpp-keyword">else</span><br>                {<br>                    Console.Write(<span class="cpp-literal">" "</span>);<br>                }<br>                <span class="cpp-keyword">if</span> (newLineCounter == (m_width))<br>                {<br>                    Console.Write(<span class="cpp-literal">"|\n"</span>);<br>                    newLineCounter = <span class="cpp-number">0</span>;<br>                }<br>                <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> (Cells<span style="font-weight:bold;">.EastWall.IsUp)<br>                    Console.Write(<span class="cpp-literal">"|"</span>);<br>                <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> (i &gt; (m_area - (m_width + <span class="cpp-number">1</span>)))<br>                    Console.Write(<span class="cpp-literal">"_"</span>);<br>                <span class="cpp-keyword">else</span><br>                    Console.Write(<span class="cpp-literal">"_"</span>);<br><br>                newLineCounter++;<br>            }<br>            Console.Write(<span class="cpp-literal">"\n"</span>);<br>        }<br><br>    }<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre><br><span class="cpp-keyword">using</span> System;<br><span class="cpp-keyword">using</span> System.Collections.Generic;<br><span class="cpp-keyword">using</span> System.Text;<br><br><span class="cpp-keyword">namespace</span> Maze<br>{<br>    <span class="cpp-keyword">class</span> Cell<br>    {<br>        Wall m_EastWall;<br>        Wall m_SouthWall;<br>        <span class="cpp-keyword">int</span> m_index;                <span class="cpp-comment">// The unique index for the room.</span><br>        <span class="cpp-keyword">int</span> m_belongsToCellSet;     <span class="cpp-comment">// Starts in set equal to it's unique index, but might get changed during knockdown of walls.</span><br><br>        <span class="cpp-keyword">public</span> Cell(<span class="cpp-keyword">int</span> index)<br>        {<br>            m_index = index;<br>            m_belongsToCellSet = index;<br>        }<br><br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">int</span> Index<br>        {<br>            get { <span class="cpp-keyword">return</span> m_index; }<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">int</span> BelongsToCellSet<br>        {<br>            get { <span class="cpp-keyword">return</span> m_belongsToCellSet; }<br>            set { m_belongsToCellSet = value; }<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">void</span> SetWall(Wall Wall)<br>        {<br>            <span class="cpp-keyword">if</span> (Wall.WallType == WallType.EastWall)<br>            {<br>                m_EastWall = Wall;<br>            }<br>            <span class="cpp-keyword">else</span><br>            {<br>                m_SouthWall = Wall;<br>            }<br>        }<br><br>        <span class="cpp-keyword">public</span> Wall EastWall<br>        {<br>            get { <span class="cpp-keyword">return</span> m_EastWall; }<br>        }<br>        <span class="cpp-keyword">public</span> Wall SouthWall<br>        {<br>            get { <span class="cpp-keyword">return</span> m_SouthWall; }<br>        }<br>    }<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre><br><span class="cpp-keyword">using</span> System;<br><span class="cpp-keyword">using</span> System.Collections.Generic;<br><span class="cpp-keyword">using</span> System.Text;<br><br><span class="cpp-keyword">namespace</span> Maze<br>{<br>    <span class="cpp-keyword">class</span> Wall<br>    {<br>        <span class="cpp-keyword">bool</span> m_isUp;<br>        WallType m_wallType;    <span class="cpp-comment">// Makes it a little easier to keep track of what type of wall it is.</span><br>        <span class="cpp-keyword">int</span> m_wallIndex;<br>        <span class="cpp-keyword">int</span> m_cell1;            <span class="cpp-comment">// If the wall is a SouthWall, Cell1 references the index of the upper cell. If EastWall, it references the left wall.</span><br>        <span class="cpp-keyword">int</span> m_cell2;<br><br>        <span class="cpp-keyword">public</span> Wall(WallType type, <span class="cpp-keyword">int</span> wallIndex, <span class="cpp-keyword">int</span> c1, <span class="cpp-keyword">int</span> c2)<br>        {<br>            m_isUp = <span class="cpp-keyword">true</span>;<br>            m_wallType = type;<br>            m_wallIndex = wallIndex;<br>            m_cell1 = c1;<br>            m_cell2 = c2;<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">bool</span> IsUp<br>        {<br>            get { <span class="cpp-keyword">return</span> m_isUp; }<br>            set { m_isUp = value; }<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">int</span> Index<br>        {<br>            get { <span class="cpp-keyword">return</span> m_wallIndex; }<br>        }<br>        <span class="cpp-keyword">public</span> WallType WallType<br>        {<br>            get { <span class="cpp-keyword">return</span> m_wallType; }<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">int</span> Cell1<br>        {<br>            get { <span class="cpp-keyword">return</span> m_cell1; }<br>        }<br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">int</span> Cell2<br>        {<br>            get { <span class="cpp-keyword">return</span> m_cell2; }<br>        }<br>    }<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre><br><span class="cpp-keyword">using</span> System;<br><span class="cpp-keyword">using</span> System.Collections.Generic;<br><span class="cpp-keyword">using</span> System.Text;<br><br><span class="cpp-keyword">namespace</span> Maze<br>{<br>    <span class="cpp-keyword">class</span> Shuffle<br>    {<br>        <span class="cpp-comment">// Probably quite ugly way of handling shuffles, haven't improved it since first make.</span><br>        <span class="cpp-comment">// Looking at the code, I see &lt;Wall&gt; is used instead of &lt;Object&gt;, defeating the purpose of making it an independant class for future use, duh.</span><br>        <span class="cpp-keyword">public</span> <span class="cpp-keyword">static</span> <span class="cpp-keyword">void</span> List(List&lt;Wall&gt; unshuffledList)<br>        {<br>            Random Rand = <span class="cpp-keyword">new</span> Random();<br>            List&lt;Wall&gt; shuffledList = <span class="cpp-keyword">new</span> List&lt;Wall&gt;();<br>            <span class="cpp-keyword">int</span> rndNum = <span class="cpp-number">0</span>;<br>            <span class="cpp-keyword">int</span> numList = unshuffledList.Count;<br>            <span class="cpp-keyword">for</span>(<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i &lt; numList; i++)<br>            {<br>                rndNum = Rand.Next(<span class="cpp-number">0</span>, (unshuffledList.Count -<span class="cpp-number">1</span>));<br>                shuffledList.Add(unshuffledList[rndNum]);<br>                unshuffledList.RemoveAt(rndNum);<br>            }<br>            unshuffledList.Clear();<br>            foreach (Wall obj in shuffledList)<br>            {<br>                unshuffledList.Add(obj);<br>            }<br>        }<br><br>    }<br>}<br><br><br></pre></div><!–ENDSCRIPT–><br><br>I would love for some suggestions and/or advice!
using System;using System.Collections.Generic;using System.Text;namespace mgen{   class Direction   {      public const int North = 0;      public const int East = 1;      public const int South = 2;      public const int West = 3;      public const int Count = 4;      public const int First = North;      public const int Last = West;   }   class Threshhold   {      public bool Passable;      public Threshhold()      {         Passable = false;      }   }   class Area   {      private Threshhold[] threshholds;      private Area[] neighbors;      public uint Zone;      public Threshhold[] Threshholds      {         get         {            return (threshholds);         }      }      public Area[] Neighbors      {         get         {            return (neighbors);         }      }      public void Fill()      {         for (uint index = Direction.First; index <= Direction.Last; ++index)         {            if ((Threshholds[index] != null) && (Neighbors[index] != null) && (Threshholds[index].Passable) && (Neighbors[index].Zone != Zone))            {               Neighbors[index].Zone = Zone;               Neighbors[index].Fill();            }         }      }      public Area(uint theZone)      {         threshholds = new Threshhold[Direction.Count];         neighbors = new Area[Direction.Count];         for (uint index = Direction.First; index <= Direction.Last; ++index)         {            threshholds[index] = null;            neighbors[index] = null;         }         Zone = theZone;      }   }   class Map   {      private Area[] areas;      private uint width;      private uint height;      public uint Width      {         get         {            return (width);         }      }      public uint Height      {         get         {            return (height);         }      }      public Area GetArea(uint column, uint row)      {         return(((column<Width)&&(row<Height))?(areas[row*Width+column]):(null));      }      public void SetSize(uint newWidth,uint newHeight)      {         width = newWidth;         height = newHeight;         areas = (width*height>0)?(new Area[width*height]):(null);         if (areas != null)         {            uint row;            uint column;            uint currentZone = 0;            for (row = 0; row < Height; ++row)            {               for (column = 0; column < Width; ++column)               {                  areas[currentZone] = new Area(currentZone);                  if (column > 0)                  {                     areas[currentZone].Threshholds[Direction.West] = new Threshhold();                     areas[currentZone].Neighbors[Direction.West] = areas[currentZone - 1];                     areas[currentZone - 1].Threshholds[Direction.East] = areas[currentZone].Threshholds[Direction.West];                     areas[currentZone - 1].Neighbors[Direction.East] = areas[currentZone];                  }                  if (row > 0)                  {                     areas[currentZone].Threshholds[Direction.North] = new Threshhold();                     areas[currentZone].Neighbors[Direction.North] = areas[currentZone - Width];                     areas[currentZone - Width].Threshholds[Direction.South] = areas[currentZone].Threshholds[Direction.North];                     areas[currentZone - Width].Neighbors[Direction.South] = areas[currentZone];                  }                  ++currentZone;               }            }         }      }      private bool HasMultipleZones()      {         if (areas == null) return (false);         uint theZone = areas[0].Zone;         for (uint index = 1; index < areas.Length; ++index)         {            if (areas[index].Zone != theZone)            {               return (true);            }         }         return (false);      }      public void Generate(uint newWidth, uint newHeight)      {         SetSize(newWidth, newHeight);         Random rng = new Random();         while (HasMultipleZones())         {            Area theArea = areas[rng.Next(areas.Length)];            uint suitability = 0;            bool[] suitableWalls = new bool[Direction.Count];            uint direction;            for (direction = Direction.First; direction <= Direction.Last; ++direction)            {               if (suitableWalls[direction] = (theArea.Threshholds[direction] != null) && (!theArea.Threshholds[direction].Passable) && (theArea.Neighbors[direction] != null) && (theArea.Neighbors[direction].Zone != theArea.Zone))               {                  suitability++;               }            }            if (suitability > 0)            {               do               {                  direction = (uint)rng.Next(Direction.Count);               }               while (!suitableWalls[direction]);               theArea.Threshholds[direction].Passable = true;               theArea.Fill();            }         }      }      public Map()      {      }   }   class Program   {      static void Main(string[] args)      {         Map map = new Map();         map.Generate(16,16);         string[] lines = new string[2];         for (uint row = 0; row < map.Height; ++row)         {            lines[0] = "";            lines[1] = "";            for (uint column = 0; column < map.Width; ++column)            {               Area theArea = map.GetArea(column, row);               lines[0] += "#" + (((theArea.Threshholds[Direction.North] == null) || (!theArea.Threshholds[Direction.North].Passable)) ? ("#") : (" "));               lines[1] += (((theArea.Threshholds[Direction.West] == null) || (!theArea.Threshholds[Direction.West].Passable)) ? ("#") : (" ")) + " ";            }            lines[0] += "#";            lines[1] += "#";            Console.WriteLine(lines[0]);            Console.WriteLine(lines[1]);         }         for (uint column = 0; column < map.Width; ++column) Console.Write("##");         Console.WriteLine("#");         Console.ReadKey();      }   }}

Get off my lawn!

Ok, so it's late :( I wrote the algo three times and I had the same problem just not quite all the rooms got visited. I wracked my brains and it was a simple mistake. I set both rooms to the same set!!! Oh well, better late then never....

My apologies to those that completed on time....

Main.cs
using System;using System.Text.RegularExpressions;namespace Game{	/// <summary>	/// Main Application Class for Game.	/// </summary>	class SimpleMazeApp	{		/// <summary>		/// The main entry point for the application.		/// </summary>		[STAThread]		static int Main(string[] args)		{			int ret_val = 0;			sbyte rowSize = 0;			sbyte colSize = 0;            const string AppName = "JWWicks Maze Factory";            const string Version = "0.99.00";			Maze MyMaze;			Console.Title =  AppName + " - " + Version;			do			{				ShowAppInfo( AppName, Version);				GetMazeDimension( ref rowSize, "Rows (height)", 2, 50 );				GetMazeDimension( ref colSize, "Columns (width)", 2, 50 );				MyMaze = CreateMaze( (uint)rowSize, (uint)colSize );                MyMaze.GeneratePath();                SetConsoleSize((uint)rowSize, (uint)colSize);				MyMaze.Draw();			}while( !IsAppDone() );			return ret_val;		}		static void ShowAppInfo( string AppName, string Version )		{			Console.WriteLine("{0} - {1}\n\n", AppName, Version);		}		static bool IsAppDone()		{			bool ret_val = false;			string answer = null;					do			{				Console.Write("\n\nWould you like to display another Maze: ");				try				{					answer = Console.ReadLine();				}				catch				{					Console.WriteLine("Error: Getting the answer, please try again...");				}			}while( !IsValidAnswer( answer ) );            if (Regex.IsMatch(answer, @"^[Nn]$|^[Nn][Oo]$"))                ret_val = true;            else                Console.Clear();			return ret_val;		}		static void GetMazeDimension( ref sbyte Size, string Dim, sbyte Min, sbyte Max )		{			do			{				Console.Write("Number of {0} in Maze ( {1} to {2} ): ", Dim, Min, Max);				try				{					Size = SByte.Parse(Console.ReadLine());				}				catch				{					Console.WriteLine("Error: Please enter a number from {0} to {1} !", Min, Max);				}			}while( !IsValidSize( Size, Min, Max ) );		}		static bool IsValidAnswer( string s )		{			bool ret_val = false;			ret_val = Regex.IsMatch( s , @"^[Nn]$|^[Nn][Oo]$|^[Yy]$|^[Yy][Ee][Ss]$");			if (!ret_val)				Console.WriteLine("Please enter either y[es] or n[o]...");			return ret_val;		}		static bool IsValidSize( sbyte Val, sbyte Min, sbyte Max )		{			bool ret_val = false;			if( Val < Min | Val > Max )				Console.WriteLine("Error: Value must be from {0} to {1}.", Min, Max);			else				ret_val = true;						return ret_val;		}		static Maze CreateMaze( uint r, uint c )		{            Maze maze = new Maze(r, c);            return maze;		}        static void SetConsoleSize(uint r, uint c)        {            try            {                if (r * 2 < Console.LargestWindowHeight && c * 2 < Console.LargestWindowWidth)                    Console.SetWindowSize((int)c * 2, (int)r * 2);                else                    Console.SetWindowSize((Console.LargestWindowWidth - 20), (Console.LargestWindowHeight - 5));                if (Console.BufferHeight < 2 * r) Console.BufferHeight = (int)r * 2;                if (Console.BufferWidth < 2 * c) Console.BufferWidth = (int)c * 2;            }            catch            {            }        }	}}


Maze.cs
using System;using System.Collections;using System.Threading;namespace Game{	public class Maze	{ 		public Maze()		{            this.m_columns = 3;            this.m_rows = 3;            Initialize();		}        public Maze(uint rows, uint columns)		{            if (rows > uint.MinValue && rows < uint.MaxValue && columns > uint.MinValue && columns < uint.MaxValue)			{                this.m_rows = rows;                this.m_columns = columns;                Initialize();			}			else				throw( new InvalidMazeDimensionException() );		}        public void Reset(uint rows, uint columns)        {            if (rows > uint.MinValue && rows < uint.MaxValue && columns > uint.MinValue && columns < uint.MaxValue)            {                this.m_rows = rows;                this.m_columns = columns;                Initialize();            }            else                throw (new InvalidMazeDimensionException());        }         public void Draw()        {            string sTemp = new string('_', (int)(2*this.m_columns));            sTemp = sTemp.Replace("__", " _");            Console.Write("\n {0}", sTemp);            for (int r = 0; r < this.m_rows; r++)            {                Console.Write("\n |");                for (int c = 0; c < this.m_columns; c++)                {                    if (this.m_rooms[r, c].IsWallStanding((uint)Direction.South) || (r == this.m_rows - 1))                        Console.Write("_");                    else                        Console.Write(" ");                    if (this.m_rooms[r, c].IsWallStanding((uint)Direction.East) || (c == this.m_columns - 1))                        Console.Write("|");                    else                        Console.Write(" ");                }            }        }        public void GeneratePath()        {            UInt16 r1 = 0, c1 = 0;            UInt16 r2 = 0, c2 = 0;            foreach (Room r in this.m_rooms)                foreach (Wall w in r.Walls())                    this.m_walls[w.m_number] = w;            PermutateWalls( ref m_walls );            foreach (Wall w in m_walls)            {                FindRoomPos(w.m_room1, ref r1, ref c1);                FindRoomPos(w.m_room2, ref r2, ref c2);                if (this.m_rooms[r1, c1].Set != 0 )                {                    switch ((int)w.m_orientation)                    {                        case 0: this.m_rooms[r1, c1].RemoveWall(0); this.m_rooms[r2, c2].RemoveWall(2); break;                        case 1: this.m_rooms[r1, c1].RemoveWall(1); this.m_rooms[r2, c2].RemoveWall(3); break;                        case 2: this.m_rooms[r1, c1].RemoveWall(2); this.m_rooms[r2, c2].RemoveWall(0); break;                        case 3: this.m_rooms[r1, c1].RemoveWall(3); this.m_rooms[r2, c2].RemoveWall(1); break;                        default: break;                    }                    this.m_rooms[r1, c1].Set = 0;                }            }        }        protected void Initialize()        {            this.m_totalRooms = this.m_rows * this.m_columns;             this.m_totalWalls = this.m_totalRooms + ((this.m_rows - 1) * (this.m_columns - 1) - 1);            this.m_rooms = new Room[this.m_rows, this.m_columns];            this.m_roomSet = new uint[this.m_totalRooms];            this.m_walls = new Wall[this.m_totalWalls];            Random rnd = new Random(unchecked((int)DateTime.Now.Ticks));            this.m_startRoom = (uint)rnd.Next(0, (int)this.m_totalRooms);            this.m_finishRoom = (uint)rnd.Next(0, (int)this.m_totalRooms);            uint count = 0, roomSet = 0;            for (int r = 0; r < this.m_rows; r++)                for (int c = 0; c < this.m_columns; c++)                {                   this.m_rooms[r,c] = new Room();                   m_rooms[r, c].Number = count++;                   m_roomSet[roomSet++] = count;                   m_rooms[r, c].Set = count;                }                        AddWallsToRooms();        }        protected void AddWallsToRooms()        {            uint w = this.m_totalWalls;            int r, c;            for (r = 0; r < this.m_rows; r++)                for (c = 0; c < this.m_columns; c++)                {                    if (c + 1 <= this.m_columns - 1)                    {                        this.m_rooms[r, c + 1].AddWall(this.m_totalWalls - w, Direction.West, this.m_rooms[r, c + 1].Number, this.m_rooms[r, c].Number);                        this.m_rooms[r, c].AddWall(this.m_totalWalls - w--, Direction.East, this.m_rooms[r, c].Number, this.m_rooms[r, c + 1].Number);                    }                    if (r + 1 <= this.m_rows - 1)                    {                        this.m_rooms[r + 1, c].AddWall(this.m_totalWalls - w, Direction.North, this.m_rooms[r + 1, c].Number, this.m_rooms[r, c].Number);                        this.m_rooms[r, c].AddWall(this.m_totalWalls - w--, Direction.South, this.m_rooms[r, c].Number, this.m_rooms[r + 1, c].Number);                    }                                    }        }        protected bool FindRoomNo(UInt16 cRow, UInt16 cCol, ref uint cRoomNo)        {            bool ret_val = false;            cRoomNo = 0;            if ((cRow >= 0 && cRow < this.m_rows) && (cCol >= 0 && cCol < this.m_columns))            {                cRoomNo = (cRow * this.m_columns) + cCol;                ret_val = true;            }            return ret_val;        }        protected bool FindRoomPos(uint roomNo, ref UInt16 row, ref UInt16 column)        {            bool ret_val = false;            if (roomNo >= 0 && roomNo < this.m_totalRooms)            {                row = (UInt16)(roomNo / this.m_columns);                column = (UInt16)(roomNo % this.m_columns);                ret_val = true;            }            return ret_val;        }        protected bool FindNeighborWithWallsUp(uint cCellNo, ref uint nCellNo)        {            bool ret_val = false;            return ret_val;               }        protected uint NumberOfNeighbors(uint cRow, uint cCol, ref uint[] nArray)        {            uint ret_val = 0;              return ret_val;        }        private void PermutateWalls(ref Wall[] w)        {            Random rnd = new Random(unchecked((int)DateTime.Now.Ticks));            uint curIndex, lastIndex = 0;            Wall temp;                        for (int i = 0; i < this.m_totalWalls; i++)            {                curIndex = (uint)rnd.Next(0, (int)this.m_totalWalls);                temp = w[lastIndex];                w[lastIndex] = w[curIndex];                w[curIndex] = temp;                lastIndex = curIndex;            }        }		protected uint m_totalRooms;		protected uint m_totalWalls;		protected uint m_rows;		protected uint m_columns;		protected Room[,] m_rooms;        protected Wall[] m_walls;        protected uint[] m_roomSet;        protected uint[] m_wallNo;        protected uint m_startRoom, m_finishRoom;    }	class InvalidMazeDimensionException : Exception	{		public InvalidMazeDimensionException(){}		public InvalidMazeDimensionException( string msg ) : base( msg ){}		public InvalidMazeDimensionException( string msg, Exception e ): base( msg, e ){}	}    class InvalidRoomNoException : Exception    {        public InvalidRoomNoException() { }        public InvalidRoomNoException(string msg) : base(msg) { }        public InvalidRoomNoException(string msg, Exception e) : base(msg, e) { }    } 	class TestMazeApp	{		public static int Main( string[] args )		{			int ret_val = 0;            Maze maze = new Maze(9, 9);                        maze.GeneratePath();            maze.Draw();			            return ret_val;		}	}}


Room.cs
using System;namespace Game{	public class Room	{        public Room()        {            this.m_roomNo = 0;            InitializeWalls();                   }        public Room(uint n)		{            if (n >= uint.MinValue && n <= uint.MaxValue)            {                this.m_roomNo = n;                InitializeWalls();            }		}		public uint Number		{			get { return this.m_roomNo; }			set 			{                if (value >= uint.MinValue && value <= uint.MaxValue)                    this.m_roomNo = value;			}		}        public uint Set        {            get { return this.m_roomSet; }            set            {                if (value >= uint.MinValue && value <= uint.MaxValue)                    this.m_roomSet = value;            }        }        public Wall[] Walls()        {            Wall[] w = null;            int i = 0;            foreach (Wall j in this.m_walls)            {                if (j.m_status == true)                {                    Array.Resize<Wall>(ref w, i + 1);                    w = j;                    i++;                }            }            return w;        }        public bool IsWallStanding(uint w)        {            bool ret_val = false;            if (this.m_walls[w].m_status == true) ret_val = true;            return ret_val;        }        public bool IsWallNo(uint n, ref Wall w)        {            bool ret_val = false;            for (int i = 0; i < this.m_walls.Length; i++)            {                if (this.m_walls.m_number == n && this.m_walls.m_status == true)                {                    w = this.m_walls;                    ret_val = true;                    break;                }            }            return ret_val;        }        public bool AddWall( uint n, Direction d , uint room1, uint room2)        {            bool ret_val = false;            uint i = (uint)d;            if (i >= 0 && i < m_maxWalls)            {                switch (i)                {                    case 0:                    case 1:                    case 2:                    case 3:                        {                            this.m_walls.m_number = n;                            this.m_walls.m_status = true;                            this.m_walls.m_room1 = room1;                            this.m_walls.m_room2 = room2;                            ret_val = true;                            break;                        }                    default: break;                }            }            return ret_val;        }        public bool RemoveWall( uint n )        {            bool ret_val = false;            switch (n)            {                case 0:                 case 1:                 case 2:                case 3: this.m_walls[n].m_status = false; ret_val = true; break;                default: break;            }            return ret_val;        }        protected void InitializeWalls()        {            for (this.m_wallCount = 0; this.m_wallCount < m_maxWalls; m_wallCount++)            {                this.m_walls[this.m_wallCount].m_number = 0;                this.m_walls[this.m_wallCount].m_status = false;                this.m_walls[this.m_wallCount].m_border = false;                this.m_walls[this.m_wallCount].m_room1 = this.m_roomNo;                this.m_walls[this.m_wallCount].m_room2 = this.m_roomNo;                switch( this.m_wallCount ){                    case 0: this.m_walls[this.m_wallCount].m_orientation = Direction.North; break;                    case 1: this.m_walls[this.m_wallCount].m_orientation = Direction.East; break;                    case 2: this.m_walls[this.m_wallCount].m_orientation = Direction.South; break;                    case 3: this.m_walls[this.m_wallCount].m_orientation = Direction.West; break;                    default: break;                }                            }        }		protected uint m_roomNo;        protected uint m_roomSet;        protected const uint m_maxWalls = 4;        private uint m_wallCount = 0;		private Wall[] m_walls = new Wall[m_maxWalls];	}}


Wall.cs
using System;namespace Game{	public struct Wall	{        public uint m_number;        public bool m_status;        public bool m_border;		public uint m_room1;		public uint m_room2;        public Direction m_orientation;	}}


Direction.cs
using System;namespace Game{	public enum Direction {		North = 0,		East = 1,		South = 2,		West = 3	} 	public class InvalidDirectionException : Exception	{		public InvalidDirectionException(){}		public InvalidDirectionException( string msg ) : base( msg ){}		public InvalidDirectionException( string msg, Exception e ) : base( msg, e ){}	}	public class TestDirectionApp	{		public static int Main( string[] args )		{			int ret_val = 0;			Type MyDirection = typeof(Direction);			Console.WriteLine("The Directions and their Values are:");			foreach( string s in Enum.GetNames(MyDirection) )				Console.WriteLine("{0,-5} = {1}", s, Enum.Format(MyDirection, Enum.Parse(MyDirection,s), "d"));			return ret_val;		}	}}


JWWicks

Computers are useless, they can only give you answers. - Pablo Picasso
Damn, that was an interesting first project. I couldn't wrap my head around the logic behind the walls and whatnot, had to re-read the description a half-dozen times.

Boy I'm rusty.
using System;using System.Globalization;using System.Windows.Forms;class MazeWall{    public int room1=0, room2=0;    public bool isfloor = false;}class MazeSpace{    public bool floor = true, rwall = true;}class MazeGenerator{    public static void Main()    {        Console.WriteLine(Console.Title = "Welcome to Decel's Maze Generator!");        string myanswer;        do        {            GenerateMaze();            Console.WriteLine();            Console.WriteLine("Maze is done!  Do you want to create another one? ([y]es:[n]o)");            myanswer = (Console.ReadLine()).ToLower();            myanswer.TrimEnd('\r', '\n');            if (myanswer == "n" || myanswer == "no" || myanswer == "y" || myanswer == "yes")                continue;            else            {                Console.WriteLine("Invalid answer, please use an available command ([y]es:[n]o)");                myanswer = (Console.ReadLine()).ToLower();                myanswer.TrimEnd('\r', '\n');            }        }while (myanswer == "y" || myanswer == "yes");    }    static void GenerateMaze()    {        Int32 irow = GetNumberInfo("rows");        Int32 icol = GetNumberInfo("columns");        //Set the console display buffer        if (Console.BufferHeight < irow)            Console.BufferHeight = irow;        if (Console.BufferWidth < icol * 2)            Console.BufferWidth = 110;        //Create and initialize room sets        Int32[][] iroomset = new Int32[irow * icol][];        MazeSpace[] msMaze = new MazeSpace[irow * icol];        for (Int32 i = 0; i < msMaze.Length; i++)            msMaze = new MazeSpace();        for (Int32 i = 0; i < iroomset.Length; i++)        {            iroomset = new Int32[1] { i };        }        //Create and initialize maze walls        MazeWall[] mwset = new MazeWall[irow * (icol - 1) + icol * (irow - 1)];        Int32 index = 0;        for (Int32 myrow = 0; myrow < irow; myrow++)        {            //Assign rooms to walls            for (Int32 iwall = 0; iwall < icol - 1; iwall++)            {                mwset[index] = new MazeWall();                mwset[index].room1 = (myrow * icol) + iwall;                mwset[index].room2 = mwset[index].room1 + 1;                //msMaze[mwset[index].room1 - 1].rwall = true;                index++;            }            //The last row doesn't have floors            if (myrow < irow - 1)            {                //Assign rooms to floors (horizontal walls)                for (Int32 ifloor = 0; ifloor < icol; ifloor++)                {                    mwset[index] = new MazeWall();                    mwset[index].room1 = (myrow * icol) + ifloor;                    mwset[index].room2 = mwset[index].room1 + icol;                    mwset[index].isfloor = true;                    //msMaze[mwset[index].room1 - 1].floor = true;                    index++;                }            }        }        //Randomize wall sequence        Random rand = new Random();        for (Int32 irand = 0; irand < mwset.Length; irand++)        {            SwapWall(ref mwset[rand.Next(mwset.Length - 1)], ref mwset[rand.Next(mwset.Length - 1)]);        }        //Wall Knockdown Algorithm        for (Int32 i = 0; i < mwset.Length; i++)        {            Int32 roomind1 = -1, roomind2 = -1;            for (Int32 j = 0; j < irow * icol; j++)            {                if (iroomset[j] == null)                    continue;                Int32[] jarray = iroomset[j];                foreach (Int32 k in jarray)                {                    if (k == mwset.room1)                        roomind1 = j;                    else if (k == mwset.room2)                        roomind2 = j;                    else if (roomind1 != -1 && roomind2 != -1)                        break;  //Avoid unnecessary searching                }                if (roomind1 != -1 && roomind2 != -1)                    break;  //Avoid unnecessary searching            }            //If the rooms are not in the same set            if (roomind1 != roomind2)            {                Int32[] iarray = iroomset[roomind1];                iroomset[roomind1] = new Int32[iarray.Length + iroomset[roomind2].Length];                for (Int32 x = 0; x < iarray.Length; x++)                    iroomset[roomind1][x] = iarray[x];                for (Int32 y = 0; y < iroomset[roomind2].Length; y++)                    iroomset[roomind1][iarray.Length + y] = iroomset[roomind2][y];                iroomset[roomind2] = null;                //Remove the wall from the msMaze set                if (mwset.isfloor)                    msMaze[mwset.room1].floor = false;                else                    msMaze[mwset.room1].rwall = false;            }        }        //Display Maze        Console.WriteLine();        string curstr = " ";        //Top floor (roof)        for (Int32 i = 0; i < icol - 1; i++)            curstr += "__";        Console.Write(curstr + "_");        for (Int32 i = 0; i < msMaze.Length; i++)        {            if (i % icol == 0)                Console.Write("\r\n|");            if (msMaze.floor == true)                Console.Write("_");            else                Console.Write(" ");            if (msMaze.rwall == true)                Console.Write("|");            else                Console.Write("_");        }    }    static Int32 GetNumberInfo(string info)    {        do        {            Console.Write("Enter the number of " + info + " [2-50]: ");            Int32 inum = Int32.Parse(Console.ReadLine());            if (inum >= 2 && inum <= 50)                return inum;            Console.WriteLine("Sorry, the number of " + info + " entered was not between 2 and 50!");        } while (true);    }    static void SwapWall(ref MazeWall mw1, ref MazeWall mw2)    {        MazeWall mwtemp = mw1;        mw1 = mw2;        mw2 = mwtemp;    }}


Thanks for the lessons btw. Greatly appreciated.

Edit: Bah, didn't notice that constructors were part of the scope of this project :(
Hey I know the workshop is over, but maybe there are still people hanging out here and we can get some work done together.

I started learning programming about 4 weeks ago and this is my FIRST SELF WRITTEN CODE so please be as harsh as you like, but keep in mind I'm a complete "newb". This is my first shot at the maze, it assigns the rooms to the walls properly, but I'm not sure if it tears down walls correctly and I know for sure it doesn't draw right.

My next step is going to use my text-testing thinger at the bottom to make sure it's tearing down walls correctly and work on that. After that is working I'll tinker with the drawing function and see what I can learn.

EDIT2: Hot diggity I JUST DREW A BOX!! Finally figured out what was wrong.. so simple (writeline vs. write...). Now either my writing function is screwing or my wall tearing function is ripping down every wall (most likely). Updated the code box below.

EDIT3: It mostly works now!!! But there is still some sort of issue with a) the randomizer or b) the way it tears down walls; because I'm not getting "perfect" mazes.

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Maze0{    struct Wall /*This is the wall variable, it is up or down and inbetween two rooms*/    {        public bool up; //Wall exists or doesn't        public int leftOrTop, rightOrBottom; //This should be the number of the room to the left (or top) and right (or bottom) of the wall    }    struct Room /*This is the room variable, it is in a set and the right or bottom wall is true or false*/    {        public int set;        public bool right, bottom;    }    class Program    {        /*This method is called to get the height of the maze*/        static System.Int32 GetHeight()        {            System.Int32 height = 0;            do            {                try                {                    System.Console.WriteLine("How tall do you want your maze to be? (1-52):");                    height = Convert.ToInt32(Console.ReadLine());                    if (height < 1 || height > 52)                        System.Console.WriteLine("That is not a number between 1 and 52.  Please try again.\n");                }                catch                {                    System.Console.WriteLine("Invalid entry.\n");                }                       } while (height < 1 || height > 52);            return height;        }        /*This method is called to get the width of the maze*/        static System.Int32 GetWidth()        {            System.Int32 width = 0;            do            {                try                {                    System.Console.WriteLine("How wide do you want your maze to be? (1-52):");                    width = Convert.ToInt32(Console.ReadLine());                    if (width < 1 || width > 52)                        System.Console.WriteLine("That is not a number between 1 and 52.  Please try again.\n");                }                catch                {                    System.Console.WriteLine("Invalid entry.\n");                }            } while (width < 1 || width > 52);            return width;        }        static void Draw(Room[] RoomArray, int rows, int columns) //The drawing function.        {            System.Console.Write("\n ");            for (int r = 0; r < columns; r++)            {                Console.Write("__");            }            for (int i = 0; i < rows; i++)            {                Console.Write("\n|");                for (int j = 0; j < columns; j++)                {                    int thisRoom = (i * columns + j);                    /*WORK IN PROGRESS*/                    //if (RoomArray[thisRoom].right == RoomArray[thisRoom].bottom)                    //    switch RoomArray[thisRoom].right                    //        case true:                    //            System.Console.Write                    //switch (RoomArray[thisRoom].right                    if (RoomArray[thisRoom].right == false && RoomArray[thisRoom].bottom == false)                        Console.Write("  ");                    else if (RoomArray[thisRoom].right == true && RoomArray[thisRoom].bottom == true)                        Console.Write("_|");                    else if (RoomArray[thisRoom].bottom == true)                        Console.Write("__");                    else if (RoomArray[thisRoom].right == true)                        Console.Write(" |");                    else System.Console.WriteLine("CRYYYYYYYYYY");                }             }          }        static char StartOver()        {                       string ans = ("");            char shortans = ('0');            do            {                try                {                    System.Console.WriteLine("\nWould you like to make another maze?");                    ans = System.Console.ReadLine();                    ans = ans.ToLower();                    ans = ans.Trim();                    shortans = ans[1];                }                catch                {                    System.Console.WriteLine("Invalid entry.\n");                }            } while (shortans == ('0'));            return shortans;        }        static void Main(string[] args)            {            start:                System.Int32 rows = GetHeight();                     //Number of rows in maze                System.Int32 columns = GetWidth();                   //Number of columns in maze                System.Int32 rooms = rows * columns;                 //Number of rooms                System.Int32 walls = ((columns - 1) * rows) + ((rows - 1) * columns);         //Number of walls                Room[] RoomArray = new Room[rooms];                Wall[] WallArray = new Wall[walls];                for (int i = 0; i < RoomArray.Length; i++)                {                    RoomArray.set = i;                    RoomArray.right = true;                    RoomArray.bottom = true;                }            // This part builds the wall array and assigns the adjoining rooms.#region Build Wall Array                for (int i = 0; i < WallArray.Length; )                {                    if (i < (columns - 1) * rows)                    {                        for (int h = 0; h < columns; h++)                        {                            for (int w = 0; w < (rows - 1); w++, i++)                            {                                WallArray.up = true;                                WallArray.leftOrTop = (h * rows) + w;                                WallArray.rightOrBottom = WallArray.leftOrTop + 1;                            }                        }                    }                    else                    {                        for (int h = 0; h < columns - 1; h++)                        {                            for (int w = 0; w < rows; w++, i++)                            {                                WallArray.up = true;                                WallArray.leftOrTop = (h * rows) + w;                                WallArray.rightOrBottom = WallArray.leftOrTop + columns;                            }                        }                    }                }#endregion            // This part itterates through the walls and tears them down if necessary.#region Tear down walls            //To make numbers random we make a random array.  Work in progress.            int[] WallArrayRandomizer = new int[WallArray.Length];            for (int i = 0; i < WallArray.Length; i++)            {                WallArrayRandomizer = i;            }            Random randomizer = new Random();            for (int i = 0; i < WallArray.Length; i++)            {                int storage, rand;                rand = randomizer.Next(i);                storage = WallArrayRandomizer[rand];                WallArrayRandomizer[rand] = WallArrayRandomizer;                WallArrayRandomizer = storage;                //tmp1 = randomizer.Next(WallArray.Length);                //tmp2 = WallArrayRandomizer;                //WallArrayRandomizer = WallArrayRandomizer[tmp1];                //WallArrayRandomizer[tmp1] = tmp2;                Console.Write("{0}, ", rand);            }              //This is the current wall tearing down function.            int j = 0;                for (int i = 0; i < WallArray.Length; i++)                {                    j = WallArrayRandomizer;                    if (RoomArray[WallArray[j].leftOrTop].set == RoomArray[WallArray[j].rightOrBottom].set)                    {                        continue;                    }                    else if (j < (columns - 1) * rows)                    {                        RoomArray[WallArray[j].rightOrBottom].set = RoomArray[WallArray[0].leftOrTop].set;                        WallArray[j].up = false;                        RoomArray[WallArray[j].leftOrTop].right = false;                    }                    else                    {                        RoomArray[WallArray[j].rightOrBottom].set = RoomArray[WallArray[0].leftOrTop].set;                        WallArray[j].up = false;                        RoomArray[WallArray[j].leftOrTop].bottom = false;                    }                }            Draw(RoomArray, rows, columns);            /* This thing doesn't work, and I'm not really sure how to make it more elegant.             * Optimally I could put everything above in method calls and do the entire Main() in a do{}while loop             * and just quit it when they want to.  Or I could learn how to take input and quit a program >.< */            //char shortans = StartOver();                           //if (shortans == 'y')            //{            Console.WriteLine("\n\n");            goto start;            //}            //else            //{            //}            System.Console.ReadKey();#endregion     //This part I built for testing purposes.          //here://                Console.WriteLine("Please enter a wall number or room number:");//                int wallnumber = Convert.ToInt32(Console.ReadLine());//                Console.WriteLine("Wall number {0} is between rooms {1} and {2} and is {3}", wallnumber, WallArray[wallnumber].leftOrTop, WallArray[wallnumber].rightOrBottom, WallArray[wallnumber].up);//                Console.WriteLine("Room number {0} is in set {1}; Right is {2} and Left is {3}\n\n",  wallnumber, RoomArray[wallnumber].set, RoomArray[wallnumber].right, RoomArray[wallnumber].bottom);//goto here;                       }    }}


I could really use some more elegant solutions to some problems in here but my toolset is limited and I'm still trying to perfect single dimensional arrays etc. etc. so my code is going to be pretty "linear" if that's a good descriptive term. I'll try to get more into class management in the later projects once I can code the basics properly.

Edit: Also it appears that some of my code didn't go in right. The < or other weird errors look like most < or > signs. Probably because I'm using a japanese keyboard to type this. Just moved to Japan 2 months ago and my computer committed hari-kari last week so I'm using a company laptop right now. Anybody know where to buy an english computer in Japan????

[Edited by - welldone101 on October 21, 2007 9:24:51 AM]
I'm going through the workshop late at my own pace, as I didn't feel I had the time or the energy to do it when it was actually going.

Here's my implementation of the first project. I actually managed to simplify the algorithm, while still keeping the requirements implemented. Starting at the top left, the cursor moves in a random direction (if it encounters a maze boundary, it simply stays there until the dice roller gives a valid direction). If and only if the source square is marked as reachable AND the destination square is NOT marked as reachable, it knocks down the wall between them and sets the destination square as reachable, and moves to the destination. I get around the problem of running into a dead end by not limiting movement. For example, if the source square and the destination square are both set as reachable, I move there, I simply don't knock down the wall between them. Same if they're both not reachable. In this fashion, if a dead end is found, it'll simply wander around the maze until it finds a valid place to start again.

This might not sound very efficient, but on my Athlon 64 3200, it generates a 50x50 maze almost instantly. Good enough for me.

Finally, I overrode the ToString() function for the display code. This allows me to do
Console.WriteLine(somemaze);
but is generally flexible and not tied to the console at all.

Program.cs
using System;using Maze;namespace Maze_Gen{    class Alpha    {        static void Main()        {            Console.Title = "Maze Generator";            Console.WindowWidth = 110;            Console.WindowHeight = 50;            Console.BufferWidth = 110;            Console.BufferHeight = 400;            Console.WriteLine("Welcome to the maze generator.\n");            bool Done = false;            string strChoice = new string(string.Empty.ToCharArray());            byte width = 0, height = 0;            while(!Done)            {                bool Valid = false;                do                {                    try                    {                        Console.WriteLine("Please input how wide and how tall you'd like your maze to be (must be >= 2 and <= 50).");                        Console.Write("Width: ");                        width = byte.Parse(Console.ReadLine());                        Console.Write("Height: ");                        height = byte.Parse(Console.ReadLine());                        if(width > 50 || width < 2 || height > 50 || height < 2)                            Console.WriteLine("Please enter numbers greater than or equal to 2 and less than or equal to 50.");                        else                            Valid = true;                    }                    catch(OverflowException)                    {                        Console.WriteLine("Please enter numbers greater than 2 and less than 50.");                    }                    catch(FormatException)                    {                        Console.WriteLine("\nYou must input a valid number");                    }                }                while(!Valid);                RandomMaze mTest = new RandomMaze(width, height);                Console.WriteLine();                Console.WriteLine(mTest + "\n");                Console.Write("Would you like to make another? ([Y]es|[N]o): ");                strChoice = Console.ReadLine().ToLower();                if(strChoice != "y" && strChoice != "yes")                    Done = true;            }        }    }}


RandomMaze.cs
using System;using System.Text;namespace Maze{    class RandomMaze    {        Cell[] Rooms;        byte Width, Height;        // Sole constructor.  Generates a random maze of the specified number of cells.        public RandomMaze(byte InputWidth, byte InputHeight)        {            // Prepare the random direction generator            Random Direction = new Random();            this.Width = InputWidth;            this.Height = InputHeight;            // Create and initialize the cells needed for the maze            Rooms = new Cell[Width * Height];            for(uint i = 0; i < Rooms.Length; i++)                Rooms.EastDoorOpen = Rooms.SouthDoorOpen = true;            // Begin the pathing process.  Start at the top left cell and set it as reachable, and            // note that one room is open.  Position is used to keep track of the current cell.            ushort RoomCount = 1;            ushort Position = 0;            Rooms[Position].Reachable = true;            // For each loop interation, move one cell in a random direction (up, down, left, or right).            // Do not move through the maze boundries.  If the current cell is reachable, and the destination            // cell is not, knock down the wall between them, set the destination as reachable, and move to            // the new cell.  Otherwise (move reachable, or both not reachable), just move to the new cell.            while(RoomCount < (Width * Height))            {                switch(Direction.Next(4))                {                    case 0:                        if(((Position + 1) % Width) != 0)                        {                            if(Rooms[Position].Reachable == true && Rooms[Position + 1].Reachable == false)                            {                                Rooms[Position].EastDoorOpen = false;                                Rooms[Position + 1].Reachable = true;                                RoomCount++;                            }                            Position++;                        }                        break;                    case 1:                        if((Position + Width) < Width * Height)                        {                            if(Rooms[Position].Reachable == true && Rooms[Position + Width].Reachable == false)                            {                                Rooms[Position].SouthDoorOpen = false;                                Rooms[Position + Width].Reachable = true;                                RoomCount++;                            }                            Position += Width;                        }                        break;                    case 2:                        if(Position % Width != 0)                        {                            if(Rooms[Position].Reachable == true && Rooms[Position - 1].Reachable == false)                            {                                Rooms[Position - 1].EastDoorOpen = false;                                Rooms[Position - 1].Reachable = true;                                RoomCount++;                            }                            Position--;                        }                        break;                    case 3:                        if(Position >= Width)                        {                            if(Rooms[Position].Reachable == true && Rooms[Position - Width].Reachable == false)                            {                                Rooms[Position - Width].SouthDoorOpen = false;                                Rooms[Position - Width].Reachable = true;                                RoomCount++;                            }                            Position -= Width;                        }                        break;                    default:                        break;                }                          }        }        // Overridden ToString() function.  Returns a formatted string representing the maze        public override string ToString()        {            // Prepare the top row with the proper amount and placment of _s            string strTemp = " ";            for(byte i = 0; i <= Width * 2 - 2; i++)                strTemp += "_";            strTemp += " " + Environment.NewLine;            // Check each cell.  First, check if it's at the beginning of the row, and if so add a            // preceeding |.  Then, check which walls are up, and place a | or _ (or both) as needed            for(uint i = 0; i < Rooms.Length; i++)            {                if(i % Width == 0) strTemp += "|";                if(Rooms.SouthDoorOpen == true) strTemp += "_";                else strTemp += " ";                if(Rooms.EastDoorOpen == true) strTemp += "|";                else strTemp += "_";                if((i + 1) % Width == 0) strTemp += Environment.NewLine;            }                        return strTemp;        }        // Basic object describing the current state of a given cell        struct Cell        {            public bool EastDoorOpen, SouthDoorOpen, Reachable;        }    }}

This topic is closed to new replies.

Advertisement