Пример #1
0
        public static void Save(Maze maze)
        {
            using (FileStream fs = new FileStream("maze.mzl", FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

                sw.WriteLine(maze.GetSize().r + " " + maze.GetSize().c);

                foreach (List <bool> i in maze.HolWalls)
                {
                    foreach (bool j in i)
                    {
                        sw.Write((j ? 1 : 0) + " ");
                    }
                    sw.WriteLine();
                }

                foreach (List <bool> i in maze.VerWalls)
                {
                    foreach (bool j in i)
                    {
                        sw.Write((j ? 1 : 0) + " ");
                    }
                    sw.WriteLine();
                }

                sw.Flush();
            }
        }
Пример #2
0
        // Recursive Backtracker 방식의 미로 생성
        // maze: 완전 미로를 생성할 변수
        // action: 벽을 제거할 때마다 실행되기를 원하는 함수
        public static void RecursiveBacktracker(Maze maze, Action action)
        {
            #region INITIALIZE
            ArrayPoint2D        size       = maze.GetSize();
            List <List <bool> > hasVisited = new List <List <bool> >();

            for (int i = 0; i < size.r; i++)
            {
                hasVisited.Add(new List <bool>(size.c));
                for (int j = 0; j < size.c; j++)
                {
                    hasVisited[i].Add(false);
                }
            }
            #endregion

            using (FileStream fs = new FileStream("test.log", FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

                #region ALGORITHM
                // CODE STARTS HERE //
                ArrayPoint2D current = maze.StartPoint;
                hasVisited[current.r][current.c] = true;
                sw.WriteLine("Recursive Backtracker 생성입니다. 현재 위치는 " + current + " 입니다."); // LOG

                Stack <ArrayPoint2D> PointStack = new Stack <ArrayPoint2D>();

                while (!HasVisitedAll(hasVisited))
                {
                    List <ArrayPoint2D> avail = new List <ArrayPoint2D>();
                    AddNeighbor(avail, current, size);
                    avail.RemoveAll(_ => hasVisited[_.r][_.c]);
                    if (avail.Count() != 0)
                    {
                        ArrayPoint2D target = avail[random.Next(avail.Count())];
                        PointStack.Push(current);
                        sw.WriteLine("스택에 " + current + " 가 푸시되었습니다.");             // LOG
                        maze.RemoveWallBetween(current, target, action);
                        sw.WriteLine(current + " 와 " + target + " 사이 벽이 제거되었습니다."); // LOG
                        action();                                                   // GRAPHIC
                        hasVisited[target.r][target.c] = true;
                        current = target;
                        sw.WriteLine("현재 위치는 이제 " + current + " 입니다."); // LOG
                    }
                    else
                    {
                        current = PointStack.Pop();
                        sw.WriteLine("현재 위치를 스택에서 팝된 데이터로 설정합니다. " + current + " 가 팝되었습니다."); // LOG
                    }
                }
                #endregion

                sw.Flush();
            }
        }
Пример #3
0
        public static bool MovePlayer(Maze maze, Key dir)
        {
            maze.Cells[playerPos.r][playerPos.c] = 0;

            switch (dir)
            {
            case Key.W:
                if (playerPos.r > 0 && maze.HolWalls[playerPos.r - 1][playerPos.c] == false)
                {
                    playerPos.r--;
                }
                break;

            case Key.S:
                if (playerPos.r < maze.GetSize().r - 1 && maze.HolWalls[playerPos.r][playerPos.c] == false)
                {
                    playerPos.r++;
                }
                break;

            case Key.A:
                if (playerPos.c > 0 && maze.VerWalls[playerPos.r][playerPos.c - 1] == false)
                {
                    playerPos.c--;
                }
                break;

            case Key.D:
                if (playerPos.c < maze.GetSize().c - 1 && maze.VerWalls[playerPos.r][playerPos.c] == false)
                {
                    playerPos.c++;
                }
                break;

            default:
                maze.Cells[playerPos.r][playerPos.c] = 4;
                return(false);
            }

            maze.Cells[playerPos.r][playerPos.c] = 4;
            return(true);
        }
Пример #4
0
        // HuntAndKill 방식의 미로 생성
        // maze: 완전 미로를 생성할 변수
        // action: 벽을 제거할 때마다 실행되기를 원하는 함수
        public static void HuntAndKill(Maze maze, Action action)
        {
            #region INITIALIZE
            ArrayPoint2D        size       = maze.GetSize();
            List <List <bool> > hasVisited = new List <List <bool> >();

            for (int i = 0; i < size.r; i++)
            {
                hasVisited.Add(new List <bool>(size.c));
                for (int j = 0; j < size.c; j++)
                {
                    hasVisited[i].Add(false);
                }
            }
            #endregion

            using (FileStream fs = new FileStream("test.log", FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

                #region ALGORITHM
                // CODE STARTS HERE //
                ArrayPoint2D current = new ArrayPoint2D(random.Next(size.r), random.Next(size.c));
                hasVisited[current.r][current.c] = true;
                sw.WriteLine("Hunt-And-Kill 생성입니다. 현재 위치는 " + current + " 입니다."); // LOG

                while (!HasVisitedAll(hasVisited))
                {
                    List <ArrayPoint2D> avail = new List <ArrayPoint2D>();
                    AddNeighbor(avail, current, size);
                    avail.RemoveAll(_ => hasVisited[_.r][_.c]);
                    while (avail.Count() != 0)
                    {
                        ArrayPoint2D target = avail[random.Next(avail.Count())];
                        maze.RemoveWallBetween(current, target, action);
                        sw.WriteLine("미로를 생성 중입니다. " + current + " 와 " + target + " 사이 벽이 제거되었습니다.");
                        hasVisited[target.r][target.c] = true;
                        current = target;
                        avail.Clear();
                        AddNeighbor(avail, current, size);
                        avail.RemoveAll(_ => hasVisited[_.r][_.c]);
                    }

                    bool         restart = false; // 이중 반복문 탈출을 위해
                    ArrayPoint2D loop;
                    for (int i = 0; i < size.r; i++)
                    {
                        for (int j = 0; j < size.c; j++)
                        {
                            loop = new ArrayPoint2D(i, j);
                            if (!hasVisited[loop.r][loop.c])
                            {
                                List <ArrayPoint2D> related = new List <ArrayPoint2D>();
                                AddNeighbor(related, loop, size);
                                related.RemoveAll(_ => !hasVisited[_.r][_.c]);

                                if (related.Count == 0)
                                {
                                    continue;
                                }

                                ArrayPoint2D target = related[random.Next(related.Count())];
                                maze.RemoveWallBetween(loop, target, action);
                                sw.WriteLine("새로운 지역을 탐색합니다. " + loop + ", " + target + " 사이 벽이 제거되었습니다.");
                                hasVisited[loop.r][loop.c] = true;
                                current = loop;
                                restart = true;
                                sw.WriteLine("새로운 현재 위치는 " + current + " 입니다."); // LOG
                                break;
                            }
                        }
                        if (restart)
                        {
                            break;
                        }
                    }
                }

                // CODE ENDS HERE //
                #endregion

                sw.Flush();
            }
        }
Пример #5
0
        // Kruskal 방식의 미로 생성
        // maze: 완전 미로를 생성할 변수
        // action: 벽을 제거할 때마다 실행되기를 원하는 함수
        public static void Kruskal(Maze maze, Action action)
        {
            #region INITIALIZE

            ArrayPoint2D size = maze.GetSize();

            DisjointSet <ArrayPoint2D> disjointSet = new DisjointSet <ArrayPoint2D>();

            List <WallWithDirection> WallList  = new List <WallWithDirection>();
            List <List <int> >       CellIndex = new List <List <int> >();

            int removedCount       = 0;
            int removedCountTarget = (size.r * size.c) - 1;

            for (int i = 0; i < size.r - 1; i++)
            {
                for (int j = 0; j < size.c; j++)
                {
                    WallList.Add(new WallWithDirection(false, new ArrayPoint2D(i, j)));
                }
            }
            for (int i = 0; i < size.r; i++)
            {
                for (int j = 0; j < size.c - 1; j++)
                {
                    WallList.Add(new WallWithDirection(true, new ArrayPoint2D(i, j)));
                }
            }
            for (int i = 0; i < size.r; i++)
            {
                CellIndex.Add(new List <int>());
                for (int j = 0; j < size.c; j++)
                {
                    CellIndex[i].Add(-1);
                }
            }

            #endregion

            using (FileStream fs = new FileStream("test.log", FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

                #region ALGORITHM
                // CODE STARTS HERE //
                //WallList.Count != 0 ||
                while (removedCount != removedCountTarget)
                {
                    sw.WriteLine("Recursive Backtracker 생성입니다."); // LOG
                    int rand = random.Next(WallList.Count);
                    WallWithDirection target = WallList[rand];
                    ArrayPoint2D      ULPos  = target.Wall;
                    ArrayPoint2D      DRPos  = target.Wall + (target.IsVerWall ? new ArrayPoint2D(0, 1) : new ArrayPoint2D(1, 0));
                    sw.WriteLine("현재 대상 벽은 " + ULPos + " 와 " + DRPos + " 사이의 벽입니다."); // LOG

                    ArrayPoint2D[] targetCells = { ULPos, DRPos };
                    foreach (var item in targetCells)
                    {
                        if (CellIndex[item.r][item.c] == -1)
                        {
                            CellIndex[item.r][item.c] = disjointSet.GetTreeCount();
                            disjointSet.MakeSet(item);
                            sw.WriteLine("Disjoint Set에 " + item + "을 추가합니다."); // LOG
                        }
                    }

                    if (disjointSet.Find(CellIndex[ULPos.r][ULPos.c]) != disjointSet.Find(CellIndex[DRPos.r][DRPos.c]))
                    {
                        disjointSet.Union(CellIndex[ULPos.r][ULPos.c], CellIndex[DRPos.r][DRPos.c]);
                        maze.RemoveWallBetween(ULPos, DRPos, action);
                        sw.WriteLine(ULPos + " 와 " + DRPos + " 사이 벽이 제거되었습니다."); // LOG
                        removedCount++;
                    }

                    WallList.RemoveAt(rand);
                }

                // CODE ENDS HERE //
                #endregion

                sw.Flush();
            }
        }
Пример #6
0
        public static void BFS(Maze maze, Action action)
        {
            #region INITIALIZE
            ArrayPoint2D        size       = maze.GetSize();
            Queue <PathNode>    que        = new Queue <PathNode>();
            List <List <bool> > hasVisited = new List <List <bool> >();
            ArrayPoint2D[]      dirs       = { new ArrayPoint2D(-1, 0), new ArrayPoint2D(1, 0), new ArrayPoint2D(0, -1), new ArrayPoint2D(0, 1) };
            PathNode            answer     = new PathNode();

            for (int i = 0; i < size.r; i++)
            {
                hasVisited.Add(new List <bool>(size.c));
                for (int j = 0; j < size.c; j++)
                {
                    hasVisited[i].Add(false);
                }
            }
            #endregion

            que.Enqueue(new PathNode(maze.StartPoint));
            hasVisited[maze.StartPoint.r][maze.StartPoint.c] = true;

            while (que.Count != 0)
            {
                PathNode target = que.Dequeue();
                maze.Cells[target.point.r][target.point.c] = 1;

                if (target.point == maze.EndPoint)
                {
                    answer = target;
                    break;
                }

                foreach (var item in dirs)
                {
                    ArrayPoint2D enqueuePos = target.point + item;
                    if (!enqueuePos.IsValidPosition(size))
                    {
                        continue;
                    }

                    if (maze.HasWallBetween(target.point, enqueuePos))
                    {
                        continue;
                    }

                    if (hasVisited[enqueuePos.r][enqueuePos.c])
                    {
                        continue;
                    }

                    que.Enqueue(new PathNode(enqueuePos, target));
                    hasVisited[enqueuePos.r][enqueuePos.c] = true;
                }
                action();
                Thread.Sleep(MainWindow.delayTime);
            }

            foreach (var item in answer.path)
            {
                maze.Cells[item.r][item.c] = 2;
                action();
                Thread.Sleep(MainWindow.delayTime);
            }
        }
Пример #7
0
        public void Prepare()
        {
            // CLEAR ALL ENTITIES IN GRID //
            MazeGrid.Children.Clear();
            MazeGrid.RowDefinitions.Clear();
            MazeGrid.ColumnDefinitions.Clear();

            // MAKE DEFINITIONS //
            MazeGrid.RowDefinitions.Add(new RowDefinition {
                Height = new GridLength(1, GridUnitType.Star)
            });
            MazeGrid.ColumnDefinitions.Add(new ColumnDefinition {
                Width = new GridLength(1, GridUnitType.Star)
            });

            for (int i = 0; i < mainMaze.GetSize().r; i++)
            {
                MazeGrid.RowDefinitions.Add(new RowDefinition {
                    Height = new GridLength(2, GridUnitType.Star)
                });
                MazeGrid.RowDefinitions.Add(new RowDefinition {
                    Height = new GridLength(1, GridUnitType.Star)
                });
            }

            for (int i = 0; i < mainMaze.GetSize().c; i++)
            {
                MazeGrid.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = new GridLength(2, GridUnitType.Star)
                });
                MazeGrid.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = new GridLength(1, GridUnitType.Star)
                });
            }

            // DRAW DOTS //
            for (int i = 1; i < mainMaze.GetSize().r; i++)
            {
                for (int j = 1; j < mainMaze.GetSize().c; j++)
                {
                    Rectangle rectangle = new Rectangle
                    {
                        Fill            = Brushes.Black,
                        StrokeThickness = 0
                    };

                    MazeGrid.Children.Add(rectangle);
                    Grid.SetRow(rectangle, i * 2);
                    Grid.SetColumn(rectangle, j * 2);
                }
            }

            // DRAW 4 BIG WALLS //
            Rectangle leftWall = new Rectangle {
                Fill = Brushes.Black, StrokeThickness = 0
            };
            Rectangle rightWall = new Rectangle {
                Fill = Brushes.Black, StrokeThickness = 0
            };
            Rectangle upWall = new Rectangle {
                Fill = Brushes.Black, StrokeThickness = 0
            };
            Rectangle downWall = new Rectangle {
                Fill = Brushes.Black, StrokeThickness = 0
            };

            MazeGrid.Children.Add(leftWall);
            Grid.SetRow(leftWall, 0);
            Grid.SetColumn(leftWall, 0);
            Grid.SetRowSpan(leftWall, mainMaze.GetSize().r * 2 + 1);

            MazeGrid.Children.Add(rightWall);
            Grid.SetRow(rightWall, 0);
            Grid.SetColumn(rightWall, mainMaze.GetSize().c * 2);
            Grid.SetRowSpan(rightWall, mainMaze.GetSize().r * 2 + 1);

            MazeGrid.Children.Add(upWall);
            Grid.SetRow(upWall, 0);
            Grid.SetColumn(upWall, 0);
            Grid.SetColumnSpan(upWall, mainMaze.GetSize().c * 2 + 1);

            MazeGrid.Children.Add(downWall);
            Grid.SetRow(downWall, mainMaze.GetSize().r * 2);
            Grid.SetColumn(downWall, 0);
            Grid.SetColumnSpan(downWall, mainMaze.GetSize().c * 2 + 1);

            // DRAW HORIZONTAL WALLS //
            HolWallsRects = new List <List <Rectangle> >();
            for (int i = 0; i < mainMaze.GetSize().r - 1; i++)
            {
                HolWallsRects.Add(new List <Rectangle>());
                for (int j = 0; j < mainMaze.GetSize().c; j++)
                {
                    Rectangle rectangle = new Rectangle
                    {
                        Fill            = Brushes.Black,
                        StrokeThickness = 0
                    };
                    HolWallsRects[i].Add(rectangle);
                    MazeGrid.Children.Add(rectangle);
                    Grid.SetRow(rectangle, i * 2 + 2);
                    Grid.SetColumn(rectangle, j * 2 + 1);
                }
            }

            // DRAW VERTICAL WALLS //
            VerWallsRects = new List <List <Rectangle> >();
            for (int i = 0; i < mainMaze.GetSize().r; i++)
            {
                VerWallsRects.Add(new List <Rectangle>());
                for (int j = 0; j < mainMaze.GetSize().c - 1; j++)
                {
                    Rectangle rectangle = new Rectangle
                    {
                        Fill            = Brushes.Black,
                        StrokeThickness = 0
                    };
                    VerWallsRects[i].Add(rectangle);
                    MazeGrid.Children.Add(rectangle);
                    Grid.SetRow(rectangle, i * 2 + 1);
                    Grid.SetColumn(rectangle, j * 2 + 2);
                }
            }

            CellRects = new List <List <Rectangle> >();
            for (int i = 0; i < mainMaze.GetSize().r; i++)
            {
                CellRects.Add(new List <Rectangle>());
                for (int j = 0; j < mainMaze.GetSize().c; j++)
                {
                    Rectangle rectangle = new Rectangle
                    {
                        Fill            = Brushes.White,
                        StrokeThickness = 0
                    };
                    CellRects[i].Add(rectangle);
                    MazeGrid.Children.Add(rectangle);
                    Grid.SetRow(rectangle, i * 2 + 1);
                    Grid.SetColumn(rectangle, j * 2 + 1);
                }
            }

            return;
        }