이전에 만든 미로만들기 클래스에 3D로 그리는 함수를 추가했다.

아직 소스 정리를 더 해야하지만 만드는 과정도 알며 좋을것 같다.

※ 미로 클래스 소스

using System.Drawing;

namespace maze
{
    class Maze
    {
        public int Size { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public bool[,] Well { get; private set; }
        public int MaxX { get; private set; }
        public int MaxY { get; private set; }
        private Random rnd = new Random(DateTime.Now.Millisecond);
        private SolidBrush wBrush = new SolidBrush(Color.White);
        private SolidBrush rBrush = new SolidBrush(Color.Red);
        private List<int[]> dd = new List<int[]> {
            new int[2]{1, 0},
            new int[2]{0, 1},
            new int[2]{-1, 0},
            new int[2]{0, -1}
        };

        public Maze(int x, int y)
        {
            MaxX = x * 2 + 1;
            MaxY = y * 2 + 1;
            Well = new bool[MaxX, MaxY];
            initMaze();
            makeWell(1, 1);
            Well[0, 1] = false; // 시작점
            Well[MaxX - 1, MaxY - 2] = false; // 종료점
        }
        private void initMaze()
        {
            for (int x = 0; x < MaxX; x++)
                for (int y = 0; y < MaxY; y++)
                    Well[x, y] = true;
        }


        private void makeWell(int x, int y)
        {
            Stack<Point> loc = new Stack<Point>();
            Point[] di = new Point[4];
            while (true)
            {
                int dn = 0;
                Well[x, y] = false;
                if ((x > 1) && Well[x - 2, y]) di[dn++] = new Point(-1, 0);
                if ((y > 1) && Well[x, y - 2]) di[dn++] = new Point(0, -1);
                if ((x < MaxX - 2) && Well[x + 2, y]) di[dn++] = new Point(1, 0);
                if ((y < MaxY - 2) && Well[x, y + 2]) di[dn++] = new Point(0, 1);
                if (dn == 0)
                {
                    if (loc.Count > 0)
                    {
                        Point p = loc.Pop();
                        x = p.X;
                        y = p.Y;
                        continue;
                    }
                    else return;
                }

                int dd = rnd.Next(dn);
                int dx = di[dd].X, dy = di[dd].Y;
                x += dx;
                y += dy;
                Well[x, y] = false;
                x += dx;
                y += dy;
                loc.Push(new Point(x, y));
            }
        }
        public void Size3d(int width, int height, int size)
        {
            this.Width = width;
            this.Height = height;
            this.Size = size;
        }

        public void Draw(Graphics g, int x, int y)
        {
            Draw(g);
            g.FillRectangle(rBrush, x * Size + 6, y * Size + 6, Size * 2, Size * 2);
        }
        public void Draw(Graphics g)
        {
            g.FillRectangle(wBrush, 10, 10, MaxX * Size, MaxY * Size);
            for (int x = 0, x1 = 10; x < MaxX; x++, x1 += Size)
            {
                for (int y = 0, y1 = 10; y < MaxY; y++, y1 += Size)
                {
                    if (Well[x, y])
                    {
                        if (x < MaxX - 1 && Well[x + 1, y]) // 가로선
                            g.DrawLine(Pens.Black, x1, y1, x1 + Size, y1);
                        if (y < MaxY - 1 && Well[x, y + 1]) // 세로선
                            g.DrawLine(Pens.Black, x1, y1, x1, y1 + Size);
                    }
                }
            }
        }
        public void Draw3d(Graphics gr, int x, int y, int p)
        {
            int cx = x, cy = y;
            int wellW = 0;
            int wellD = 50;

            gr.Clear(Color.White);
            while (!Well[x, y])
            {
                int x1 = wellW, x2 = x1 + wellD;
                int y1 = wellW, y2 = y1 + wellD;
                if (Well[x + dd[p][1], y - dd[p][0]])
                {
                    gr.DrawLine(Pens.Black, x1, y1, x2, y2);
                    gr.DrawLine(Pens.Black, x1, Height - y1, x2, Height - y2);
                }
                else
                {
                    gr.DrawLine(Pens.Black, x1, y1, x1, Height - y1);
                    gr.DrawLine(Pens.Black, x2, y2, x2, Height - y2);
                    gr.DrawLine(Pens.Black, x1, y2, x2, y2);
                    gr.DrawLine(Pens.Black, x1, Height - y2, x2, Height - y2);
                }
                x1 = Width - wellW;
                x2 = x1 - wellD;
                y1 = wellW;
                y2 = y1 + wellD;
                if (Well[x - dd[p][1], y + dd[p][0]])
                {
                    gr.DrawLine(Pens.Black, x1, y1, x2, y2);
                    gr.DrawLine(Pens.Black, x1, Height - y1, x2, Height - y2);
                }
                else
                {
                    gr.DrawLine(Pens.Black, x1, y1, x1, Height - y1);
                    gr.DrawLine(Pens.Black, x2, y2, x2, Height - y2);
                    gr.DrawLine(Pens.Black, x1, y2, x2, y2);
                    gr.DrawLine(Pens.Black, x1, Height - y2, x2, Height - y2);
                }
                x += dd[p][0];
                y += dd[p][1];
                wellW += wellD;
                wellD--;
                if (x + dd[p][0] < 0) break;
                if (x + dd[p][0] >= MaxX - 1) break;
                if ((Height - wellW * 2 < wellD) || (Width - wellW * 2 < wellD)) break;
            }

            {
                int x1 = wellW, x2 = Width - x1;
                int y1 = wellW, y2 = Height - y1;
                gr.DrawRectangle(Pens.Black, x1, y1, x2 - x1, y2 - y1);
            }

            Draw(gr, cx, cy);
        }

    }
}

 

※ 화면소스

namespace maze
{
    public partial class FrmMain3 : Form
    {
        private Maze maze;
        private int CurX = 1;
        private int CurY = 1;
        private int CurP = 0;
        private Bitmap bmp;
        Graphics gr;
        public FrmMain3()
        {
            InitializeComponent();
        }
        private void btnMake_Click(Object sender, EventArgs e)
        {
            CurP = 0;
            CurX = 1;
            CurY = 1;
            int width = this.ClientSize.Width - 200;
            int height = this.ClientSize.Height;
            bmp = new Bitmap(width, height);
            gr = Graphics.FromImage(bmp);

            maze = new Maze((int)numX.Value, (int)numY.Value);
            maze.Size3d(width, height, 4);

            maze.Draw3d(gr, CurX, CurY, CurP);

            this.BackgroundImage = null;
            this.BackgroundImage = bmp;
        }
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                    move(1);
                    break;
                case Keys.Down:
                    move(2);
                    break;
                case Keys.Left:
                    move(3);
                    break;
                case Keys.Right:
                    move(4);
                    break;
            }
        }
        private void move(int n)
        {
            switch (n)
            {
                case 1: // 앞으로 이동
                    if (CurX + dd[CurP][0] == 0 || CurX + dd[CurP][0] == maze.MaxX - 1) return;
                    if (!maze.Well[CurX + dd[CurP][0], CurY + dd[CurP][1]])
                    {
                        CurX += dd[CurP][0];
                        CurY += dd[CurP][1];
                    }
                    break;
                case 2: // 뒤으로 이동
                    if (CurX - dd[CurP][0] == 0 || CurX - dd[CurP][0] == maze.MaxX - 1) return;
                    if (!maze.Well[CurX - dd[CurP][0], CurY - dd[CurP][1]])
                    {
                        CurX -= dd[CurP][0];
                        CurY -= dd[CurP][1];
                    }
                    break;
                case 3: // 왼쪽으로 회전
                    CurP--;
                    if (CurP < 0) CurP = 3;
                    break;
                case 4: // 오른쪽으로 회전
                    CurP++;
                    if (CurP > 3) CurP = 0;
                    break;
            }
            if (CurX == maze.MaxX - 2 && CurY == maze.MaxY - 2)
            {
                MessageBox.Show("미로 탈출 성공");
            }
            maze.Draw3d(gr, CurX, CurY, CurP);
            this.BackgroundImage = null;
            this.BackgroundImage = bmp;

        }
        private List<int[]> dd = new List<int[]> {
                new int[2]{1, 0},
                new int[2]{0, 1},
                new int[2]{-1, 0},
                new int[2]{0, -1}
             };

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.DoubleBuffered = true;
            //this.BackgroundImageLayout = ImageLayout.Zoom;
            this.BackgroundImageLayout = ImageLayout.None;
            this.Width = 900;
            this.Height = 800;
            this.FormBorderStyle = FormBorderStyle.Fixed3D;
            this.MaximizeBox = false;
            this.KeyPreview = true;
            panel1 = new Panel();

            numX = new NumericUpDown() { Name = "numX", Value = 10, Top = 10, Left = 100, Width = 90, Minimum = 3, Maximum = 40 };
            numY = new NumericUpDown() { Name = "numY", Value = 10, Top = 40, Left = 100, Width = 90, Minimum = 3, Maximum = 20 };
            //numSize = new NumericUpDown() { Name = "numSize", Value = 10, Top = 70, Left = 100, Width = 90, Minimum = 10, Maximum = 100 };

            btnMake = new Button() { Name = "btnMake", Text = "Make", Top = 100, Left = 10, Width = 180, Height = 28 };

            panel1.Width = 200;
            panel1.BorderStyle = BorderStyle.FixedSingle;
            panel1.Dock = System.Windows.Forms.DockStyle.Right;

            panel1.Controls.Add(new Label() { Name = "lnlX", Text = "X", Top = 10, Left = 10, Width = 90 });
            panel1.Controls.Add(new Label() { Name = "lblY", Text = "Y", Top = 40, Left = 10, Width = 90 });
            //panel1.Controls.Add(new Label() { Name = "lblSize", Text = "Size", Top = 70, Left = 10, Width = 90 });
            panel1.Controls.Add(btnMake);
            panel1.Controls.Add(numSize);
            panel1.Controls.Add(numY);
            panel1.Controls.Add(numX);

            this.Controls.Add(panel1);
            this.ResumeLayout(false);

            btnMake.Click += btnMake_Click;
            this.KeyDown += this.Form1_KeyDown;
        }

        private Panel panel1;
        private NumericUpDown numX;
        private NumericUpDown numY;
        private NumericUpDown numSize;

        private Button btnMake;
    }
}

 

※ 실행화면

728x90

+ Recent posts