You may now post code

Started by
40 comments, last by Washu 14 years, 8 months ago
With the project half way over, feel free to begin uploading source examples or links to zip files. For people still trying to work this out, feel free to look over other people's code, that's a natural part of learning correct design and programming. But be aware, not everyone does things "correctly" and there is, strictly speaking, no "right" or "wrong" way to implement something. You may find you were doing something completely different than someone else. Don't feel the need to scratch your work and start over simply because someone else took a different approach. Perhaps your approach is just as valid. Evaluate the differences critically and then decide if you made a mistake, or simply did something differently. Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Advertisement
Hey! I think I took a bit of a different route in the way the map is stored.

I have it like this:

11111
10101
11111

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

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

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

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


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

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


Again, feel free to add critique / comments!

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

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

void bla::hello() {
}

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

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

111
101
111

Two cells:

11111
10101
11111

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


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


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


I like this line
int wallindex = (cols - 1) * rows + r * cols + c; //EWW
I mean, why would you get your medical advice anywhere else?
Quote:Original post by Telastyn
Quote:
One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside?


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


I like to put sections of each class into #region's in order to make it more readable and navigable. Usually, I have the regions broken down into variables, properties, events, constructor(s), methods, event handlers, and private helper methods.
Mike Popoloski | Journal | SlimDX
Quote:Original post by Mike.Popoloski
Quote:Original post by Telastyn
Quote:
One question I came across while writing this: Is there any way to declare the class methods inside the actual class definition, but define the method outside?


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


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


That's a good plan. You might also want to further group things by functionality - one region for maze-building functions, one region for maze-drawing functions, etcetera.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

I haven't gotten anywhere near finished. But since I am now stuck I will post what I have to see if what I've got so far is at least a decent start.
I can not figure out how I'm going to keep the drawing of the border of the maze separate and yet somehow control the difference between whether I am working with a border wall or one of the inner walls. This is more complicated than I thought at first.

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

The class that contains Main:

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


The class that will be used to create maze objects:

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


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

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

Now on to the maze code...

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

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

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


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

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

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


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

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

EDIT: Added comments to my code

[Edited by - cNoob on August 6, 2007 1:06:07 AM]

This topic is closed to new replies.

Advertisement