728x90
이전에 만든 미로만들기 클래스에 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
반응형
'Software > C#' 카테고리의 다른 글
VSCode에서 C# 시작하기 - MySQL 연결하기 (0) | 2024.05.24 |
---|---|
VSCode에서 C#개발 시작하기 - SQLite 소개 (0) | 2023.12.19 |
C# 시작하기 - Winform 바둑판 그리기(2) (1) | 2023.12.06 |
C# 시작하기 - Winform 바둑판 그리기(1) (1) | 2023.12.06 |
C# 시작하기 - 미로 만들기 함수(스택) (1) | 2023.12.05 |