Exemplo n.º 1
0
    public void Generate()
    {
        InitializeMap();
        ClearMap();

        Stack <PairRowCol> st = new Stack <PairRowCol>();

        System.Random rng = new System.Random();

        var currentPos = new PairRowCol {
            Row = rng.Next(Height), Col = rng.Next(Width)
        };

        st.Push(currentPos);
        MarkVisited(currentPos);

        while (st.Count > 0)
        {
            var uns = GetUnvisitedNeighbors(currentPos).ToArray();
            if (uns.Length > 0)
            {
                var nextPos = uns[rng.Next(uns.Length)];
                Connect(currentPos, nextPos);
                st.Push(nextPos);
                MarkVisited(nextPos);
                currentPos = nextPos;
            }
            else
            {
                currentPos = st.Pop();
            }
        }

        CleanWalls();
    }
Exemplo n.º 2
0
 private void Connect(PairRowCol p1, PairRowCol p2)
 {
     if (p1.Row == p2.Row)
     {
         if (p1.Col < p2.Col)
         {
             _map[p1.Row, p1.Col].WallState ^= InvertX ? MazeCell.WallStates.Left : MazeCell.WallStates.Right;
             _map[p2.Row, p2.Col].WallState ^= InvertX ? MazeCell.WallStates.Right : MazeCell.WallStates.Left;
         }
         else if (p1.Col > p2.Col)
         {
             _map[p1.Row, p1.Col].WallState ^= InvertX ? MazeCell.WallStates.Right : MazeCell.WallStates.Left;
             _map[p2.Row, p2.Col].WallState ^= InvertX ? MazeCell.WallStates.Left : MazeCell.WallStates.Right;
         }
     }
     if (p1.Col == p2.Col)
     {
         if (p1.Row < p2.Row)
         {
             _map[p1.Row, p1.Col].WallState ^= InvertY ? MazeCell.WallStates.Top : MazeCell.WallStates.Bottom;
             _map[p2.Row, p2.Col].WallState ^= InvertY ? MazeCell.WallStates.Bottom : MazeCell.WallStates.Top;
         }
         else if (p1.Row > p2.Row)
         {
             _map[p1.Row, p1.Col].WallState ^= InvertY ? MazeCell.WallStates.Bottom : MazeCell.WallStates.Top;
             _map[p2.Row, p2.Col].WallState ^= InvertY ? MazeCell.WallStates.Top : MazeCell.WallStates.Bottom;
         }
     }
 }
Exemplo n.º 3
0
    PairRowCol GetRandomNonBlockedCell(int nRandom = 1)
    {
        PairRowCol pos     = PairRowCol.Create(0, 0);
        int        iterCnt = 0;

        do
        {
            pos.Row = Random.Range(0, MazeRows);
            pos.Col = Random.Range(0, MazeColumns);
        } while (iterCnt++ < nRandom && _mg.GetCell(pos).WallState.HasFlag(MazeGenerator.MazeCell.WallStates.All));

        return(pos);
    }
Exemplo n.º 4
0
    private IEnumerable <PairRowCol> GetNeighbors(PairRowCol p)
    {
        var l = new PairRowCol {
            Row = p.Row, Col = p.Col - 1
        };                                                       // left
        var r = new PairRowCol {
            Row = p.Row, Col = p.Col + 1
        };                                                       // right
        var a = new PairRowCol {
            Row = p.Row - 1, Col = p.Col
        };                                                       // above
        var b = new PairRowCol {
            Row = p.Row + 1, Col = p.Col
        };                                                       // below

        return(new[] { l, r, a, b }.Where(ValidPos));
    }
Exemplo n.º 5
0
 private void CleanWalls()
 {
     for (int row = 1; row < Height; ++row)
     {
         for (int col = 1; col < Width; ++col)
         {
             var current = GetCell(PairRowCol.Create(row, col));
             var left    = GetCell(PairRowCol.Create(row, col - 1));
             var above   = GetCell(PairRowCol.Create(row - 1, col));
             if (left.WallState.HasFlag(MazeCell.WallStates.Right) && current.WallState.HasFlag(MazeCell.WallStates.Left))
             {
                 left.WallState ^= MazeCell.WallStates.Right;
             }
             if (above.WallState.HasFlag(MazeCell.WallStates.Bottom) && current.WallState.HasFlag(MazeCell.WallStates.Top))
             {
                 above.WallState ^= MazeCell.WallStates.Bottom;
             }
         }
     }
 }
Exemplo n.º 6
0
 private bool ValidPos(PairRowCol p)
 {
     return(ValidPos(p.Row, p.Col));
 }
Exemplo n.º 7
0
 private void MarkVisited(PairRowCol p)
 {
     MarkVisited(p.Row, p.Col);
 }
Exemplo n.º 8
0
 public MazeCell GetCell(PairRowCol p) => GetCell(p.Row, p.Col);
Exemplo n.º 9
0
 private IEnumerable <PairRowCol> GetUnvisitedNeighbors(PairRowCol p)
 {
     return(GetNeighbors(p).Where(_p => !_map[_p.Row, _p.Col].Visited));
 }
Exemplo n.º 10
0
    // Start is called before the first frame update
    void Start()
    {
        Cursor.lockState = CursorLockMode.Confined;

        _mg.Height  = MazeRows;
        _mg.Width   = MazeColumns;
        _mg.InvertY = true;

        _mg.Generate();

        var halfHeight = MazeRows / 2f;
        var halfWidth  = MazeColumns / 2f;

        for (int row = 0; row < MazeRows; ++row)
        {
            for (int col = 0; col < MazeColumns; ++col)
            {
                Vector3 cellPos = new Vector3(col - halfWidth + 0.5f, 0, row - halfHeight + 0.5f);
                var     cell    = _mg.GetCell(row, col);

                if (cell.WallState.HasFlag(MazeGenerator.MazeCell.WallStates.Top))
                {
                    GameObject g = Instantiate(_horizontalWallPrefab, _wallParent is null ? this.transform : _wallParent.transform);
                    g.name = $"Wall (N) ({row}, {col})";
                    g.transform.position = cellPos + new Vector3(0, g.transform.localScale.y / 2, +0.5f);
                }
                if (cell.WallState.HasFlag(MazeGenerator.MazeCell.WallStates.Bottom))
                {
                    GameObject g = Instantiate(_horizontalWallPrefab, _wallParent is null ? this.transform : _wallParent.transform);
                    g.name = $"Wall (S) ({row}, {col})";
                    g.transform.position = cellPos + new Vector3(0, g.transform.localScale.y / 2, -0.5f);
                }

                if (cell.WallState.HasFlag(MazeGenerator.MazeCell.WallStates.Left))
                {
                    GameObject g = Instantiate(_verticalWallPrefab, _wallParent is null ? this.transform : _wallParent.transform);
                    g.name = $"Wall (W) ({row}, {col})";
                    g.transform.position = cellPos + new Vector3(-0.5f, g.transform.localScale.y / 2, 0);
                }
                if (cell.WallState.HasFlag(MazeGenerator.MazeCell.WallStates.Right))
                {
                    GameObject g = Instantiate(_verticalWallPrefab, _wallParent is null ? this.transform : _wallParent.transform);
                    g.name = $"Wall (E) ({row}, {col})";
                    g.transform.position = cellPos + new Vector3(+0.5f, g.transform.localScale.y / 2, 0);
                }
            }
        }

        {
            var ballPos      = GetRandomNonBlockedCell();
            var ballLocalPos = CellToLocal(ballPos);

            SpawnBall(CellToLocal(ballPos) + new Vector3(0, InitialBallHeight, 0));

            PairRowCol winPos = PairRowCol.Create(0, 0);
            var        dist   = (CellToLocal(winPos) - ballLocalPos).sqrMagnitude;
            for (int row = 0; row < MazeRows; ++row)
            {
                for (int col = 0; col < MazeColumns; ++col)
                {
                    PairRowCol pos = PairRowCol.Create(row, col);
                    if (_mg.GetCell(pos).WallState.HasFlag(MazeGenerator.MazeCell.WallStates.All))
                    {
                        continue;
                    }
                    var d = (CellToLocal(pos) - ballLocalPos).sqrMagnitude;
                    if (d > dist)
                    {
                        dist   = d;
                        winPos = pos;
                    }
                }
            }

            if (_debug)
            {
                SpawnWinningSpot(CellToLocal(PairRowCol.Create(ballPos.Row, ballPos.Col - 1)) + new Vector3(0, _winningSpotPrefab.transform.localScale.y / 2, 0));
            }
            else
            {
                SpawnWinningSpot(CellToLocal(winPos) + new Vector3(0, _winningSpotPrefab.transform.localScale.y / 2, 0));
            }
        }
    }
Exemplo n.º 11
0
 Vector3 CellToLocal(PairRowCol p)
 {
     return(new Vector3(p.Col - MazeColumns / 2f + 0.5f, 0, p.Row - MazeRows / 2f + 0.5f));
 }