示例#1
0
        internal override IEnumerable <MazeTransformationStep> InternalGenerateMazeFullSize()
        {
            InitializeMaze();
            entrance = new MazeCoordinate(upperleft.X + 1 + Random.Next(this.CurrentMaze.GetWidth() - 2), upperleft.Y);

            pointStack.Push(entrance);

            Nullable <MazeCoordinate> newCorridor;

            while (pointStack.Count() != 0)
            {
                newCorridor = FindWay();

                if (newCorridor == null)
                {
                    newCorridor = pointStack.Pop(); // One step back
                    if (newCorridor != null && CurrentMaze.WouldChangeMazeFieldType(newCorridor.Value, MazeFieldType.Corridor))
                    {
                        yield return(CurrentMaze.SetMazeTypeOnPos(newCorridor.Value, MazeFieldType.Corridor));
                    }
                }
                else
                {
                    pointStack.Push(newCorridor.Value);
                    yield return(CurrentMaze.SetMazeTypeOnPos(newCorridor.Value, MazeFieldType.Corridor));
                }
            }

            yield return(TryPlaceEntrance());

            yield return(TryPlaceExit());
        }
示例#2
0
        private bool IsValidWay(MazeCoordinate point, MazeCoordinate comeFrom)
        {
            if (!this.CurrentMaze.IsPointInMaze(point))
            {
                return(false);
            }

            // Already something other than a wall?
            if (this.CurrentMaze.GetMazeTypeOnPos(point) != MazeFieldType.Wall)
            {
                return(false);
            }

            // Make sure we do not create a way through a wall.
            MazeCoordinate up    = new MazeCoordinate(point.X, point.Y - 1);
            MazeCoordinate right = new MazeCoordinate(point.X + 1, point.Y);
            MazeCoordinate down  = new MazeCoordinate(point.X, point.Y + 1);
            MazeCoordinate left  = new MazeCoordinate(point.X - 1, point.Y);

            MazeCoordinate[] pointsToCheck = { up, right, down, left };

            for (int i = 0; i < pointsToCheck.Length; i++)
            {
                if (!pointsToCheck[i].Equals(comeFrom))
                {
                    if (CurrentMaze.GetMazeTypeOnPos(pointsToCheck[i]) == MazeFieldType.Corridor)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#3
0
        /// <summary>
        /// Tries to find a place for the wall in the specified rectangle.
        /// </summary>
        /// <returns>An integer which describes the x coordinate where the wall should be placed</returns>
        private int TryPlaceWallVertical(MazeCoordinate recUpperleft, MazeCoordinate recDownright, Strategy strategy)
        {
            // first collect all possible coordinates
            int from  = recUpperleft.X + 2;
            int to    = recDownright.X - 2;
            int count = to - from;

            if (count <= 0)
            {
                return(-1);
            }

            var possibleVerticalCoordinates = Enumerable.Range(from, to - from).ToList();

            while (possibleVerticalCoordinates.Count() > 0)
            {
                //try them one by one
                int coordinateToTest = ChooseCoordinateBasedOnStrategy(strategy, possibleVerticalCoordinates);

                // will it cover a corridor?
                if (!(CurrentMaze.IsCorridor(new MazeCoordinate(coordinateToTest, recUpperleft.Y)) ||
                      CurrentMaze.IsCorridor(new MazeCoordinate(coordinateToTest, recDownright.Y))))
                {
                    // found valid coordinate
                    return(coordinateToTest);
                }
                possibleVerticalCoordinates.Remove(coordinateToTest);
            }

            // Failed to find a good coordinate.
            return(-1);
        }
示例#4
0
        private Nullable <MazeCoordinate> FindWay()
        {
            MazeCoordinate akt = pointStack.Peek();

            possibleWays.Clear();

            // four possible directions
            possibleWays.Add(new MazeCoordinate(akt.X, akt.Y - 1));
            possibleWays.Add(new MazeCoordinate(akt.X + 1, akt.Y));
            possibleWays.Add(new MazeCoordinate(akt.X - 1, akt.Y));
            possibleWays.Add(new MazeCoordinate(akt.X, akt.Y + 1));

            int i = Random.Next(possibleWays.Count);

            while (possibleWays.Count != 0)
            {
                if (IsValidWay(possibleWays[i], akt))
                {
                    return(possibleWays[i]);
                }
                else
                {
                    possibleWays.Remove(possibleWays[i]);
                    if (possibleWays.Count != 0)
                    {
                        i = Random.Next(possibleWays.Count);
                    }
                }
            }
            return(null);
        }
示例#5
0
        public void MazeCoordinate_EqualsReturnsFalse_WhenComparedWithDiffObject()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1336, 42);

            Assert.False(foo.Equals(bar));
            Assert.False(bar.Equals(foo));
        }
示例#6
0
        public void MazeCoordinate_IsAdjacentReturnsTrue_ifDirectlyAdjacent()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1337, 41);

            Assert.True(foo.IsAdjacentTo(bar));
            Assert.True(bar.IsAdjacentTo(foo));
        }
示例#7
0
        public void MazeCoordinate_IsAdjacentReturnsFalse_ifTheSameCoordinate()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1337, 42);

            Assert.False(foo.IsAdjacentTo(bar));
            Assert.False(bar.IsAdjacentTo(foo));
        }
示例#8
0
        public void MazeCoordinate_IsAdjacentReturnsFalse_ifNotAdjacentVerticalOrHorizontal()
        {
            var foo = new MazeCoordinate(1336, 41);
            var bar = new MazeCoordinate(1337, 42);

            Assert.False(foo.IsAdjacentTo(bar));
            Assert.False(bar.IsAdjacentTo(foo));
        }
示例#9
0
        public void MazeCoordinate_EqualsReturnsTrue_WhenComparedWithEqualObject()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1337, 42);

            Assert.True(foo.Equals(bar));
            Assert.True(bar.Equals(foo));
        }
示例#10
0
        public override IEnumerable <MazeTransformationStep> InitializeMaze()
        {
            downright = new MazeCoordinate(CurrentMaze.GetWidth() - 1, 0);
            upperleft = new MazeCoordinate(0, CurrentMaze.GetHeight() - 1);

            CurrentMaze.OverrideAllMazeFields(MazeFieldType.Wall);
            return(null);
        }
示例#11
0
        public override IEnumerable <MazeTransformationStep> InitializeMaze()
        {
            this.CurrentMaze.OverrideAllMazeFields();
            downright = new MazeCoordinate(this.CurrentMaze.GetWidth() - 1, 0);
            upperleft = new MazeCoordinate(0, this.CurrentMaze.GetHeight() - 1);

            foreach (var step in this.CurrentMaze.MakeRectangle(upperleft, downright))
            {
                yield return(step);
            }
        }
示例#12
0
        public void MazeCoordinate_ListContainsWorks_WhenLookingForDiffObj()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1337, 41);

            var list = new List <MazeCoordinate>();

            list.Add(foo);

            Assert.DoesNotContain(bar, list);
        }
示例#13
0
        public void MazeCoordinate_ListContainsWorks_WhenLookingForIdenticalObj()
        {
            var foo = new MazeCoordinate(1337, 42);
            var bar = new MazeCoordinate(1337, 42);

            var list = new List <MazeCoordinate>();

            list.Add(foo);

            Assert.Contains(bar, list);
        }
示例#14
0
        private int FindVerticalCorridor(ref MazeCoordinate recUpperleft, ref MazeCoordinate recDownright)
        {
            int type = Random.Next(2);

            switch (type)
            {
            case 1:     // top
                return(recUpperleft.Y - 1);

            default:     // bottom
                return(recDownright.Y + 1);
            }
        }
示例#15
0
        private int FindHorizontalCorridor(ref MazeCoordinate recUpperleft, ref MazeCoordinate recDownright)
        {
            int type = Random.Next(2);

            switch (type)
            {
            case 1:     // right
                return(recDownright.X - 1);

            default:     // left
                return(recUpperleft.X + 1);
            }
        }
示例#16
0
        internal override IEnumerable <MazeTransformationStep> InternalGenerateMazeFullSize()
        {
            InitializeMaze();

            VisitedList = new HashSet <MazeCoordinate>();
            WallsList   = new HashSet <MazeCoordinate>();

            // Pick a cell and mark it as part of the maze
            entrance = new MazeCoordinate(Random.Next(1, this.CurrentMaze.GetWidth() - 2), this.CurrentMaze.GetHeight() - 2);

            VisitedList.Add(entrance);
            yield return(this.CurrentMaze.SetMazeTypeOnPos(entrance, MazeFieldType.Corridor));

            //add the walls to the wall list
            AddToWallList(entrance);

            int            rand;
            MazeCoordinate temp;

            while (WallsList.Count > 0) // while there are walls
            {
                // Pick random wall
                rand = Random.Next(WallsList.Count);
                temp = WallsList.ElementAt(rand);

                // If the wall does not divide two cells
                if (!checkIfWallDividesTwoCorridors(temp))
                {
                    VisitedList.Add(temp);

                    // make the wall a passage
                    yield return(this.CurrentMaze.SetMazeTypeOnPos(temp, MazeFieldType.Corridor));

                    WallsList.Remove(temp);

                    addSourroundingWallsToWallList(temp);
                }
                else
                {
                    WallsList.Remove(temp);
                }
            }

            yield return(TryPlaceExit());

            yield return(TryPlaceEntrance());
        }
示例#17
0
        private void addSourroundingWallsToWallList(MazeCoordinate target)
        {
            MazeCoordinate[] temp = MazeCoordinate.GetHorizontalVerticalAdjacentCoordinates(target);

            for (int i = 0; i < temp.Length; i++)
            {
                if (this.CurrentMaze.IsPointInMaze(temp[i]))
                {
                    if (!VisitedList.Contains(temp[i]))
                    {
                        if (!WallsList.Contains(temp[i]))
                        {
                            WallsList.Add(temp[i]);
                        }
                    }
                }
            }
        }
示例#18
0
        private IEnumerable <MazeTransformationStep> RekursiveDiv(MazeCoordinate recUpperleft, MazeCoordinate recDownright, bool horizontal)
        {
            int width   = recDownright.X - recUpperleft.X;
            int height  = recUpperleft.Y - recDownright.Y;
            int minSize = 0;

            Strategy currentStrategy = CheckWhichStrategyToUse(width, height);

            if (!(width < minSize && height < minSize))
            {
                // Override the random decision for horizontal/vertical wall placement, this reduces long stretched corridors

                if (width > height)
                {
                    horizontal = false;
                }
                else
                {
                    horizontal = true;
                }

                if (horizontal)
                {// Horizontal
                    int newWallY = TryPlaceWallHorizontal(recUpperleft, recDownright, currentStrategy);
                    if (newWallY > 0)
                    {
                        for (int i = 1; i < width; i++)
                        { // Create wall
                            yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(recUpperleft.X + i, newWallY), MazeFieldType.Wall));
                        }

                        // Place corridor
                        int randX = FindHorizontalCorridor(ref recUpperleft, ref recDownright);
                        yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(randX, newWallY), MazeFieldType.Corridor));

                        // up
                        MazeCoordinate upperleftNew = new MazeCoordinate(recUpperleft.X, recUpperleft.Y);
                        MazeCoordinate downrightNew = new MazeCoordinate(recDownright.X, newWallY);

                        foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0))
                        {
                            yield return(recursiveResult);
                        }

                        // down
                        upperleftNew = new MazeCoordinate(recUpperleft.X, newWallY);
                        downrightNew = new MazeCoordinate(recDownright.X, recDownright.Y);

                        foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0))
                        {
                            yield return(recursiveResult);
                        }
                    }
                }
                else
                {// Vertical
                    int newWallX = TryPlaceWallVertical(recUpperleft, recDownright, currentStrategy);
                    if (newWallX > 0)
                    {
                        for (int i = 1; i < height; i++)
                        { // Create Wall
                            yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(newWallX, recDownright.Y + i), MazeFieldType.Wall));
                        }

                        // Place corridor
                        int randY = FindVerticalCorridor(ref recUpperleft, ref recDownright);
                        yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(newWallX, randY), MazeFieldType.Corridor));

                        //left
                        MazeCoordinate upperleftNew = new MazeCoordinate(recUpperleft.X, recUpperleft.Y);
                        MazeCoordinate downrightNew = new MazeCoordinate(newWallX, recDownright.Y);

                        foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0))
                        {
                            yield return(recursiveResult);
                        }

                        //right
                        upperleftNew = new MazeCoordinate(newWallX, recUpperleft.Y);
                        downrightNew = new MazeCoordinate(recDownright.X, recDownright.Y);

                        foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0))
                        {
                            yield return(recursiveResult);
                        }
                    }
                }
            }
        }
示例#19
0
        private bool checkIfWallDividesTwoCorridors(MazeCoordinate target)
        {
            MazeCoordinate[] temp = MazeCoordinate.GetHorizontalVerticalAdjacentCoordinates(target);

            int TargetWallAlignsWithCorridors = 0;

            foreach (MazeCoordinate c in temp)
            {
                if (this.CurrentMaze.GetMazeTypeOnPos(c) == MazeFieldType.Corridor)
                {
                    if (target.X == c.X || target.Y == c.Y)
                    {
                        TargetWallAlignsWithCorridors++;
                    }
                }
            }

            // direct connection
            if (TargetWallAlignsWithCorridors > 2)
            {
                return(true);
            }

            temp = MazeCoordinate.GetAllAdjacentCoordinates(target);

            int CorridorFieldsInCloseProximity   = 0;
            HashSet <MazeCoordinate> inProximity = new HashSet <MazeCoordinate>();

            foreach (MazeCoordinate c in temp)
            {
                if (CurrentMaze.GetMazeTypeOnPos(c) != MazeFieldType.Wall)
                {
                    CorridorFieldsInCloseProximity++;
                    inProximity.Add(c);
                }
            }
            // This value can be reduced to create more narrow sideways, maybe make it configurable ?
            if (CorridorFieldsInCloseProximity >= 3)
            {
                return(true);
            }

            if (CorridorFieldsInCloseProximity == 2)
            {
                // check if the corridors are adjacent each other then its OK.
                foreach (MazeCoordinate c in inProximity)
                {
                    var  subset      = inProximity.Where(x => x != c).AsEnumerable();
                    bool allAdjacent = subset.All(x => x.IsAdjacentTo(c));
                    if (allAdjacent)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            if (TargetWallAlignsWithCorridors > 1 && CorridorFieldsInCloseProximity >= 2)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }