private void GoGenerate(InnerMap map, Maze maze, Random r, Action<int, int, long, long> pixelChangedCallback)
        {
            long totSteps = (((long)maze.Width - 1L) / 2L) * (((long)maze.Height - 1L) / 2L);
            long currentStep = 1;

            int width = maze.Width;
            int height = maze.Height;
            int x = 1;
            int y = 1;

            //Stack<MazePoint> stackje = new Stack<MazePoint>();
            //stackje.Push(new MazePoint(x, y));
            map[x, y] = true;
            pixelChangedCallback.Invoke(x, y, currentStep, totSteps);

            MazePoint[] targets = new MazePoint[4];

            QuatroStack quatro = new QuatroStack(); //0 == top, 1 == right, 2 == bot, 3 == left

            Boolean backtracking = false;
            int prex = 0;
            int prey = 0;

            while (true)
            {
                //Console.WriteLine(quatro.Count + ", X: " + x + " Y: " + y);

                int targetCount = 0;
                if (x - 2 > 0 && !map[x - 2, y])
                {
                    targets[targetCount].X = x - 2;
                    targets[targetCount].Y = y;
                    targetCount++;
                }
                if (x + 2 < width - 1 && !map[x + 2, y])
                {
                    targets[targetCount].X = x + 2;
                    targets[targetCount].Y = y;
                    targetCount++;
                }
                if (y - 2 > 0 && !map[x, y - 2])
                {
                    targets[targetCount].X = x;
                    targets[targetCount].Y = y - 2;
                    targetCount++;
                }
                if (y + 2 < height - 1 && !map[x, y + 2])
                {
                    targets[targetCount].X = x;
                    targets[targetCount].Y = y + 2;
                    targetCount++;
                }

                //Thread.Sleep(1000);

                if (targetCount > 0)
                {

                    var target = targets[r.Next(targetCount)];

                    if (backtracking)
                    {
                        backtracking = false;

                        targetCount = 0;

                        if (map[x - 1, y]) //Wall open at the left
                        {
                            targets[targetCount].X = x - 2;
                            targets[targetCount].Y = y;
                            targetCount++;
                        }
                        if (map[x + 1, y]) //Wall open at the right
                        {
                            targets[targetCount].X = x + 2;
                            targets[targetCount].Y = y;
                            targetCount++;
                        }
                        if (map[x, y - 1]) //Wall open at the top
                        {
                            targets[targetCount].X = x;
                            targets[targetCount].Y = y - 2;
                            targetCount++;
                        }
                        if (map[x, y + 1]) //Wall open at the bottom
                        {
                            targets[targetCount].X = x;
                            targets[targetCount].Y = y + 2;
                            targetCount++;
                        }

                        if (targetCount <= 2) //If currently only 2 exist at this tile, create junction
                        {
                            for (int i = 0; i < targetCount; i++)
                            {
                                var curMazePoint = targets[i];
                                if (curMazePoint.X != prex || curMazePoint.Y != prey)
                                {
                                    if (curMazePoint.Y < y)
                                    {
                                        quatro.Push(0);
                                        //g.FillRectangle(Brushes.Green, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.X > x)
                                    {
                                        quatro.Push(1);
                                        //g.FillRectangle(Brushes.Violet, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.Y > y)
                                    {
                                        quatro.Push(2);
                                        //g.FillRectangle(Brushes.Blue, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.X < x)
                                    {
                                        quatro.Push(3);
                                        //g.FillRectangle(Brushes.Brown, x * 5, y * 5, 5, 5);
                                    }

                                    break;
                                }
                            }
                        }
                    }

                    //stackje.Push(target);
                    map[target.X, target.Y] = true;

                    currentStep++;

                    if (target.X < x)
                    {
                        map[x - 1, y] = true;
                        pixelChangedCallback.Invoke(x - 1, y, currentStep, totSteps);
                    }
                    else if (target.X > x)
                    {
                        map[x + 1, y] = true;
                        pixelChangedCallback.Invoke(x + 1, y, currentStep, totSteps);
                    }
                    else if (target.Y < y)
                    {
                        map[x, y - 1] = true;
                        pixelChangedCallback.Invoke(x, y - 1, currentStep, totSteps);
                    }
                    else if (target.Y > y)
                    {
                        map[x, y + 1] = true;
                        pixelChangedCallback.Invoke(x, y + 1, currentStep, totSteps);
                    }

                    x = target.X;
                    y = target.Y;

                    prex = -1;
                    prey = -1;

                    pixelChangedCallback.Invoke(target.X, target.Y, currentStep, totSteps);
                }
                else
                {
                    backtracking = true;

                    if (map[x - 1, y]) //Wall open at the left
                    {
                        targets[targetCount].X = x - 2;
                        targets[targetCount].Y = y;
                        targetCount++;
                    }
                    if (map[x + 1, y]) //Wall open at the right
                    {
                        targets[targetCount].X = x + 2;
                        targets[targetCount].Y = y;
                        targetCount++;
                    }
                    if (map[x, y - 1]) //Wall open at the top
                    {
                        targets[targetCount].X = x;
                        targets[targetCount].Y = y - 2;
                        targetCount++;
                    }
                    if (map[x, y + 1]) //Wall open at the bottom
                    {
                        targets[targetCount].X = x;
                        targets[targetCount].Y = y + 2;
                        targetCount++;
                    }

                    if (targetCount > 2) //Junction
                    {
                        prex = x;
                        prey = y;

                        int whereToGo = quatro.Pop();
                        if (whereToGo == 0)
                        {
                            y -= 2;
                        }
                        else if (whereToGo == 1)
                        {
                            x += 2;
                        }
                        else if (whereToGo == 2)
                        {
                            y += 2;
                        }
                        else if (whereToGo == 3)
                        {
                            x -= 2;
                        }
                    }
                    else
                    {
                        for (int i = 0; i < targetCount; i++)
                        {
                            var curMazePoint = targets[i];
                            if (curMazePoint.X != prex || curMazePoint.Y != prey)
                            {
                                prex = x;
                                prey = y;
                                x = curMazePoint.X;
                                y = curMazePoint.Y;
                                break;
                            }
                        }
                    }

                    pixelChangedCallback.Invoke(x, y, currentStep, totSteps);

                }

                if (x == 1 && y == 1)
                {
                    break;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Finds the path between the start and the endpoint in a maze
        /// </summary>
        /// <param name="start">The start point</param>
        /// <param name="end">The end point</param>
        /// <param name="map">The maze.InnerMap</param>
        /// <param name="callBack">The callback that can be used to see what the pathfinder is doing (or null), the boolean true = a new path find thingy or false when it determined that path is not correct</param>
        /// <returns>The direction from begin to end</returns>
        public static QuatroStack GoFind(MazePoint start, MazePoint end, InnerMap map, Action <int, int, PathFinderAction> callBack)
        {
            if (callBack == null)
            {
                callBack = (x, y, z) => { };
            }


            //Callback won't work nice with this since it will find its path from back to front
            //Swap them so we don't have to reverse at the end ;)
            MazePoint temp = start;

            start = end;
            end   = temp;



            int width  = map.Width;
            int height = map.Height;


            //List<MazePoint> stackje = new List<MazePoint>();
            //stackje.Add(start);
            QuatroStack quatro = new QuatroStack(); //0 == top, 1 == right, 2 == bot, 3 == left

            MazePoint cur  = start;
            MazePoint prev = new MazePoint(-1, -1);


            Boolean backtracking = false;

            var possibleDirections      = new MazePoint[4];
            int possibleDirectionsCount = 0;
            int maxTimesAtStart         = -1;

            while (true)
            {
                //cur = stackje[stackje.Count - 1];
                var x = cur.X;
                var y = cur.Y;


                if (!backtracking)
                {
                    callBack(x, y, PathFinderAction.Step);
                }
                else
                {
                    callBack(x, y, PathFinderAction.Backtrack);
                }

                possibleDirectionsCount = 0;
                if ((prev.X != x - 1 || prev.Y != y) && x - 1 > 0 && map[x - 1, y])
                {
                    possibleDirections[possibleDirectionsCount].X = x - 1;
                    possibleDirections[possibleDirectionsCount].Y = y;
                    possibleDirectionsCount++;
                }
                if ((prev.X != x || prev.Y != y - 1) && y - 1 > 0 && map[x, y - 1])
                {
                    possibleDirections[possibleDirectionsCount].X = x;
                    possibleDirections[possibleDirectionsCount].Y = y - 1;
                    possibleDirectionsCount++;
                }
                if ((prev.X != x + 1 || prev.Y != y) && x + 1 < width - 1 && map[x + 1, y])
                {
                    possibleDirections[possibleDirectionsCount].X = x + 1;
                    possibleDirections[possibleDirectionsCount].Y = y;
                    possibleDirectionsCount++;
                }
                if ((prev.X != x || prev.Y != y + 1) && y + 1 < height - 1 && map[x, y + 1])
                {
                    possibleDirections[possibleDirectionsCount].X = x;
                    possibleDirections[possibleDirectionsCount].Y = y + 1;
                    possibleDirectionsCount++;
                }

                if (maxTimesAtStart == -1)
                {
                    //Only the first time when we are actually at start
                    maxTimesAtStart = possibleDirectionsCount;
                }
                else if (cur.X == start.X && cur.Y == start.Y)
                {
                    maxTimesAtStart--;
                    if (maxTimesAtStart == 0)
                    {
                        Console.WriteLine("No path found...");
                        break;
                    }
                }

                //If we have more then 2 directions we got a junction (only if we're not backtracking) (This is actually 3 directions but we only count 2 because we don't count previous direction)
                //If we are however at the start (which is actually the end because we swap them around) we don't create a direction because you're at the end and don't need directions
                //If we are however at the end (which is the start) we will create a direction if we have more then 2 directions (This is 2 because we don't have a previous one yet)
                if ((possibleDirectionsCount >= 2 && !backtracking && (x != start.X || y != start.Y)) || (possibleDirectionsCount >= 1 && x == end.X && y == end.Y))
                {
                    //Create junction
                    callBack(x, y, PathFinderAction.Junction);

                    int directionWeCameFrom = -1;
                    if (prev.X > cur.X)
                    {
                        directionWeCameFrom = 1; //Previous x was bigger so we came from the right
                    }
                    else if (prev.Y > cur.Y)
                    {
                        directionWeCameFrom = 2;
                    }
                    else if (prev.X < cur.X)
                    {
                        directionWeCameFrom = 3;
                    }
                    else if (prev.Y < cur.Y)
                    {
                        directionWeCameFrom = 0;
                    }
                    quatro.Push(directionWeCameFrom);
                }

                if (x == end.X && y == end.Y)
                {
                    //path found
                    return(quatro);
                }

                if (possibleDirectionsCount > 0)
                {
                    if (backtracking && cur.X == start.X && cur.Y == start.Y)
                    {
                        //This is because we don't have a junction at the start point but we want to stop backtracking anyway
                        backtracking = false;
                    }


                    if (backtracking)
                    {
                        if (possibleDirectionsCount >= 2) //Make sure we don't start searching again in the direction we originally came from
                        {
                            callBack(x, y, PathFinderAction.RefoundJunction);

                            //Set the direction we backtracked from
                            var lastBackTrackDir = -1;
                            if (prev.X < cur.X)
                            {
                                lastBackTrackDir = 0;
                            }
                            else if (prev.Y < cur.Y)
                            {
                                lastBackTrackDir = 1;
                            }
                            else if (prev.X > cur.X)
                            {
                                lastBackTrackDir = 2;
                            }
                            else if (prev.Y > cur.Y)
                            {
                                lastBackTrackDir = 3;
                            }

                            var foundJunction = quatro.Peek();

                            int previousDirectionX = 0;
                            int previousDirectionY = 0;
                            switch (foundJunction)
                            {
                            case 0:
                                previousDirectionY = -1;
                                break;

                            case 1:
                                previousDirectionX = 1;
                                break;

                            case 2:
                                previousDirectionY = 1;
                                break;

                            case 3:
                                previousDirectionX = -1;
                                break;
                            }

                            Boolean foundSomething = false;
                            for (int i = 0; i < possibleDirectionsCount; i++)
                            {
                                var probDir = possibleDirections[i];
                                if (probDir.X != x + previousDirectionX || probDir.Y != y + previousDirectionY)
                                {
                                    var directionOfThisDir = -1;
                                    if (probDir.X < cur.X)
                                    {
                                        directionOfThisDir = 0;
                                    }
                                    else if (probDir.Y < cur.Y)
                                    {
                                        directionOfThisDir = 1;
                                    }
                                    else if (probDir.X > cur.X)
                                    {
                                        directionOfThisDir = 2;
                                    }
                                    else if (probDir.Y > cur.Y)
                                    {
                                        directionOfThisDir = 3;
                                    }

                                    if (directionOfThisDir > lastBackTrackDir)
                                    {
                                        prev           = cur;
                                        cur            = probDir;
                                        foundSomething = true;
                                        backtracking   = false;
                                        break;
                                    }
                                }
                            }

                            if (!foundSomething)
                            {
                                callBack(x, y, PathFinderAction.RemovingJunction);
                                quatro.Pop();

                                prev   = cur;
                                cur.X += previousDirectionX;
                                cur.Y += previousDirectionY;
                            }
                        }
                        else
                        {
                            prev = cur;
                            cur  = possibleDirections[0];
                        }
                    }
                    else
                    {
                        prev = cur;
                        cur  = possibleDirections[0];
                    }
                }
                else
                {
                    MazePoint curtemp = cur;
                    cur          = prev;
                    prev         = curtemp;
                    backtracking = true;
                }
            }

            return(new QuatroStack());
        }
Example #3
0
        private void GoGenerate(InnerMap map, Maze maze, Random r, Action <int, int, long, long> pixelChangedCallback)
        {
            long totSteps    = (((long)maze.Width - 1L) / 2L) * (((long)maze.Height - 1L) / 2L);
            long currentStep = 1;

            int width  = maze.Width;
            int height = maze.Height;
            int x      = 1;
            int y      = 1;

            //Stack<MazePoint> stackje = new Stack<MazePoint>();
            //stackje.Push(new MazePoint(x, y));
            map[x, y] = true;
            pixelChangedCallback.Invoke(x, y, currentStep, totSteps);

            MazePoint[] targets = new MazePoint[4];

            QuatroStack quatro = new QuatroStack(); //0 == top, 1 == right, 2 == bot, 3 == left

            Boolean backtracking = false;
            int     prex         = 0;
            int     prey         = 0;

            while (true)
            {
                //Console.WriteLine(quatro.Count + ", X: " + x + " Y: " + y);

                int targetCount = 0;
                if (x - 2 > 0 && !map[x - 2, y])
                {
                    targets[targetCount].X = x - 2;
                    targets[targetCount].Y = y;
                    targetCount++;
                }
                if (x + 2 < width - 1 && !map[x + 2, y])
                {
                    targets[targetCount].X = x + 2;
                    targets[targetCount].Y = y;
                    targetCount++;
                }
                if (y - 2 > 0 && !map[x, y - 2])
                {
                    targets[targetCount].X = x;
                    targets[targetCount].Y = y - 2;
                    targetCount++;
                }
                if (y + 2 < height - 1 && !map[x, y + 2])
                {
                    targets[targetCount].X = x;
                    targets[targetCount].Y = y + 2;
                    targetCount++;
                }

                //Thread.Sleep(1000);

                if (targetCount > 0)
                {
                    var target = targets[r.Next(targetCount)];

                    if (backtracking)
                    {
                        backtracking = false;

                        targetCount = 0;

                        if (map[x - 1, y]) //Wall open at the left
                        {
                            targets[targetCount].X = x - 2;
                            targets[targetCount].Y = y;
                            targetCount++;
                        }
                        if (map[x + 1, y]) //Wall open at the right
                        {
                            targets[targetCount].X = x + 2;
                            targets[targetCount].Y = y;
                            targetCount++;
                        }
                        if (map[x, y - 1]) //Wall open at the top
                        {
                            targets[targetCount].X = x;
                            targets[targetCount].Y = y - 2;
                            targetCount++;
                        }
                        if (map[x, y + 1]) //Wall open at the bottom
                        {
                            targets[targetCount].X = x;
                            targets[targetCount].Y = y + 2;
                            targetCount++;
                        }

                        if (targetCount <= 2) //If currently only 2 exist at this tile, create junction
                        {
                            for (int i = 0; i < targetCount; i++)
                            {
                                var curMazePoint = targets[i];
                                if (curMazePoint.X != prex || curMazePoint.Y != prey)
                                {
                                    if (curMazePoint.Y < y)
                                    {
                                        quatro.Push(0);
                                        //g.FillRectangle(Brushes.Green, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.X > x)
                                    {
                                        quatro.Push(1);
                                        //g.FillRectangle(Brushes.Violet, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.Y > y)
                                    {
                                        quatro.Push(2);
                                        //g.FillRectangle(Brushes.Blue, x * 5, y * 5, 5, 5);
                                    }
                                    else if (curMazePoint.X < x)
                                    {
                                        quatro.Push(3);
                                        //g.FillRectangle(Brushes.Brown, x * 5, y * 5, 5, 5);
                                    }

                                    break;
                                }
                            }
                        }
                    }



                    //stackje.Push(target);
                    map[target.X, target.Y] = true;

                    currentStep++;

                    if (target.X < x)
                    {
                        map[x - 1, y] = true;
                        pixelChangedCallback.Invoke(x - 1, y, currentStep, totSteps);
                    }
                    else if (target.X > x)
                    {
                        map[x + 1, y] = true;
                        pixelChangedCallback.Invoke(x + 1, y, currentStep, totSteps);
                    }
                    else if (target.Y < y)
                    {
                        map[x, y - 1] = true;
                        pixelChangedCallback.Invoke(x, y - 1, currentStep, totSteps);
                    }
                    else if (target.Y > y)
                    {
                        map[x, y + 1] = true;
                        pixelChangedCallback.Invoke(x, y + 1, currentStep, totSteps);
                    }

                    x = target.X;
                    y = target.Y;

                    prex = -1;
                    prey = -1;

                    pixelChangedCallback.Invoke(target.X, target.Y, currentStep, totSteps);
                }
                else
                {
                    backtracking = true;

                    if (map[x - 1, y]) //Wall open at the left
                    {
                        targets[targetCount].X = x - 2;
                        targets[targetCount].Y = y;
                        targetCount++;
                    }
                    if (map[x + 1, y]) //Wall open at the right
                    {
                        targets[targetCount].X = x + 2;
                        targets[targetCount].Y = y;
                        targetCount++;
                    }
                    if (map[x, y - 1]) //Wall open at the top
                    {
                        targets[targetCount].X = x;
                        targets[targetCount].Y = y - 2;
                        targetCount++;
                    }
                    if (map[x, y + 1]) //Wall open at the bottom
                    {
                        targets[targetCount].X = x;
                        targets[targetCount].Y = y + 2;
                        targetCount++;
                    }

                    if (targetCount > 2) //Junction
                    {
                        prex = x;
                        prey = y;

                        int whereToGo = quatro.Pop();
                        if (whereToGo == 0)
                        {
                            y -= 2;
                        }
                        else if (whereToGo == 1)
                        {
                            x += 2;
                        }
                        else if (whereToGo == 2)
                        {
                            y += 2;
                        }
                        else if (whereToGo == 3)
                        {
                            x -= 2;
                        }
                    }
                    else
                    {
                        for (int i = 0; i < targetCount; i++)
                        {
                            var curMazePoint = targets[i];
                            if (curMazePoint.X != prex || curMazePoint.Y != prey)
                            {
                                prex = x;
                                prey = y;
                                x    = curMazePoint.X;
                                y    = curMazePoint.Y;
                                break;
                            }
                        }
                    }

                    pixelChangedCallback.Invoke(x, y, currentStep, totSteps);
                }

                if (x == 1 && y == 1)
                {
                    break;
                }
            }
        }