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; } } }
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 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]; //form.drawPixel(x, y, brushThisUses); while (stackje.Count != 0) { MazePoint cur = stackje.Peek(); x = cur.X; y = cur.Y; int targetCount = 0; if (isValid(x - 2, y, map, maze)) { targets[targetCount].X = x - 2; targets[targetCount].Y = y; targetCount++; } if (isValid(x + 2, y, map, maze)) { targets[targetCount].X = x + 2; targets[targetCount].Y = y; targetCount++; } if (isValid(x, y - 2, map, maze)) { targets[targetCount].X = x; targets[targetCount].Y = y - 2; targetCount++; } if (isValid(x, y + 2, map, maze)) { targets[targetCount].X = x; targets[targetCount].Y = y + 2; targetCount++; } //Thread.Sleep(1000); if (targetCount > 0) { var target = targets[r.Next(targetCount)]; 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); //form.drawPixel(x - 1, y, brushThisUses); } else if (target.X > x) { map[x + 1, y] = true; pixelChangedCallback.Invoke(x + 1, y, currentStep, totSteps); //form.drawPixel(x + 1, y, brushThisUses); } else if (target.Y < y) { map[x, y - 1] = true; pixelChangedCallback.Invoke(x, y - 1, currentStep, totSteps); //form.drawPixel(x, y - 1, brushThisUses); } else if (target.Y > y) { map[x, y + 1] = true; pixelChangedCallback.Invoke(x, y + 1, currentStep, totSteps); //form.drawPixel(x, y + 1, brushThisUses); } pixelChangedCallback.Invoke(target.X, target.Y, currentStep, totSteps); //form.drawPixel(target.X, target.Y, brushThisUses); } else { stackje.Pop(); } } }
private InnerMap GoGenerateInternal(InnerMap map, IRandom random, Action <int, int, long, long> pixelChangedCallback) { if (pixelChangedCallback == null) { pixelChangedCallback = (vvv, yyy, zzz, www) => { }; } long totSteps = (map.Width - 1L) / 2L * ((map.Height - 1L) / 2L); long currentStep = 1; int width = map.Width; int height = map.Height; int x = 1; int y = 1; var 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]; while (stackje.Count != 0) { MazePoint cur = stackje.Peek(); x = cur.X; y = cur.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++; } if (targetCount > 0) { var target = targets[random.Next(targetCount)]; 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); } pixelChangedCallback.Invoke(target.X, target.Y, currentStep, totSteps); } else { stackje.Pop(); } } return(map); }
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; } } }
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]; //form.drawPixel(x, y, brushThisUses); while (stackje.Count != 0) { MazePoint cur = stackje.Peek(); x = cur.X; y = cur.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)]; 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); //form.drawPixel(x - 1, y, brushThisUses); } else if (target.X > x) { map[x + 1, y] = true; pixelChangedCallback.Invoke(x + 1, y, currentStep, totSteps); //form.drawPixel(x + 1, y, brushThisUses); } else if (target.Y < y) { map[x, y - 1] = true; pixelChangedCallback.Invoke(x, y - 1, currentStep, totSteps); //form.drawPixel(x, y - 1, brushThisUses); } else if (target.Y > y) { map[x, y + 1] = true; pixelChangedCallback.Invoke(x, y + 1, currentStep, totSteps); //form.drawPixel(x, y + 1, brushThisUses); } pixelChangedCallback.Invoke(target.X, target.Y, currentStep, totSteps); //form.drawPixel(target.X, target.Y, brushThisUses); } else { stackje.Pop(); } } }
/// <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 shortest path in a list of points</returns> public static List<MazePointPos> GoFind(MazePoint startBefore, MazePoint endBefore, InnerMap map, Action<int, int, Boolean> callBack) { if (callBack == null) { callBack = (x, y, z) => { }; } var start = new MazePointPos(startBefore.X, startBefore.Y); var end = new MazePointPos(endBefore.X, endBefore.Y); //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<MazePointPos> stackje = new List<MazePointPos>(); stackje.Add(start); MazePointPos cur = new MazePointPos(); MazePointPos prev = new MazePointPos(-1, -1); var lastBackTrackDir = -1; while (stackje.Count != 0) { cur = stackje[stackje.Count - 1]; var x = cur.X; var y = cur.Y; MazePointPos target = new MazePointPos(-1, -1); //Make sure the point was not the previous point, also make sure that if we backtracked we don't go to a direction we already went to, also make sure that the point is white if ((prev.X != x + 1 || prev.Y != y) && lastBackTrackDir < 0 && x + 1 < width - 1 && map[x + 1, y]) { target = new MazePointPos(x + 1, y); } else if ((prev.X != x || prev.Y != y + 1) && lastBackTrackDir < 1 && y + 1 < height - 1 && map[x, y + 1]) { target = new MazePointPos(x, y + 1); } else if ((prev.X != x - 1 || prev.Y != y) && lastBackTrackDir < 2 && x - 1 > 0 && map[x - 1, y]) { target = new MazePointPos(x - 1, y); } else if ((prev.X != x || prev.Y != y - 1) && lastBackTrackDir < 3 && y - 1 > 0 && map[x, y - 1]) { target = new MazePointPos(x, y - 1); } else { var prepoppy = stackje[stackje.Count - 1]; stackje.RemoveAt(stackje.Count - 1); if (stackje.Count == 0) { //No path found break; } var newcur = stackje[stackje.Count - 1]; //Set the new previous point if (stackje.Count == 1) { prev = new MazePointPos(-1, -1); } else { prev = stackje.ElementAt(stackje.Count - 2); } //Console.WriteLine("Backtracking to X: " + newcur.X + " Y: " + newcur.Y); //Console.WriteLine("Setting new prev: " + prev.X + " Y: " + prev.Y); callBack.Invoke(prepoppy.X, prepoppy.Y, false); //Set the direction we backtracked from if (prepoppy.X > newcur.X) { lastBackTrackDir = 0; } else if (prepoppy.Y > newcur.Y) { lastBackTrackDir = 1; } else if (prepoppy.X < newcur.X) { lastBackTrackDir = 2; } else if (prepoppy.Y < newcur.Y) { lastBackTrackDir = 3; } //Console.WriteLine("Lastbacktrackdir: " + lastBackTrackDir); continue; } lastBackTrackDir = -1; //Console.WriteLine("Going to X: " + target.X + " Y: " + target.Y); callBack.Invoke(x, y, true); stackje.Add(target); if (target.X == end.X && target.Y == end.Y) { //Path found break; } prev = cur; } for (int i = 0; i < stackje.Count; i++) { byte formulathing = (byte)((double)i / (double)stackje.Count * 255.0); var currentStackjeThing = stackje[i]; stackje[i] = new MazePointPos(currentStackjeThing.X, currentStackjeThing.Y, formulathing); } return stackje; }
/// <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 shortest path in a list of points</returns> public static List<MazePoint> GoFind(MazePoint start, MazePoint end, InnerMap map, Action<int, int, Boolean> 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> pointlist = new List<MazePoint>(); //@todo Controleer dit InnerMap visited = new BitArreintjeFastInnerMap(width, height); for (int x = 0; x < width; x++) { //visited[x] = new BitArreintjeFast(height); for (int y = 0; y < height; y++) { if (x == 0 || y == 0 || x == width || y == height) { visited[x, y] = true; } //else //{ // visited[x][y] = false; //} } } //Hier begint het gedoe Stack<MazePoint> stackje = new Stack<MazePoint>(); stackje.Push(start); visited[start.X, start.Y] = true; callBack.Invoke(start.X, start.Y, true); //form.pixelDraw(x, y, Brushes.White); while (stackje.Count != 0) { MazePoint cur = stackje.Peek(); int x = cur.X; int y = cur.Y; if (end.X == x && end.Y == y) { callBack.Invoke(x, y, true); break; } MazePoint target = new MazePoint(-1, -1); if (x + 1 < width - 1 && !visited[x + 1, y] && map[x + 1, y]) { target = new MazePoint(x + 1, y); } else if (y + 1 < height - 1 && !visited[x, y + 1] && map[x, y + 1]) { target = new MazePoint(x, y + 1); } else if (x - 1 > 0 && !visited[x - 1, y] && map[x - 1, y]) { target = new MazePoint(x - 1, y); } else if (y - 1 > 0 && !visited[x, y - 1] && map[x, y - 1]) { target = new MazePoint(x, y - 1); } //Thread.Sleep(1000); if (target.X != -1) { callBack.Invoke(x, y, true); //var target = targets[r.Next(targets.Count)]; stackje.Push(target); visited[target.X, target.Y] = true; //form.pixelDraw(target.X, target.Y, Brushes.Blue); //Thread.Sleep(200); //if (target.X < x) //{ // visited[x - 1][y] = true; // //form.pixelDraw(x - 1, y, Brushes.White); //} //else if (target.X > x) //{ // visited[x + 1][y] = true; // //form.pixelDraw(x + 1, y, Brushes.White); //} //else if (target.Y < y) //{ // visited[x][y - 1] = true; // //form.pixelDraw(x, y - 1, Brushes.White); //} //else if (target.Y > y) //{ // visited[x][y + 1] = true; // //form.pixelDraw(x, y + 1, Brushes.White); //} } else { callBack.Invoke(x, y, false); stackje.Pop(); } } pointlist.AddRange(stackje); pointlist.Reverse(); return pointlist; }