commit a03e1b510c6671e4b543f274122df6623a2cd847 Author: dlmw <12473240+dlmw@users.noreply.github.com> Date: Thu Nov 19 11:59:29 2020 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a437a65 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +*.swp +*.*~ +project.lock.json +.DS_Store +*.pyc +nupkg/ + +# Visual Studio Code +.vscode + +# Rider +.idea + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +msbuild.log +msbuild.err +msbuild.wrn + +# Visual Studio 2015 +.vs/ diff --git a/MazeSandbox.sln b/MazeSandbox.sln new file mode 100644 index 0000000..f306214 --- /dev/null +++ b/MazeSandbox.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MazeSandbox", "MazeSandbox\MazeSandbox.csproj", "{C38E834B-D358-49A7-AA67-50F1079F12FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C38E834B-D358-49A7-AA67-50F1079F12FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C38E834B-D358-49A7-AA67-50F1079F12FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C38E834B-D358-49A7-AA67-50F1079F12FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C38E834B-D358-49A7-AA67-50F1079F12FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/MazeSandbox/CardinalPoint.cs b/MazeSandbox/CardinalPoint.cs new file mode 100644 index 0000000..7aa3f73 --- /dev/null +++ b/MazeSandbox/CardinalPoint.cs @@ -0,0 +1,27 @@ +using System; + +namespace TalesOfSenylan.Models.Dungeon +{ + public enum CardinalPoint + { + NORTH, + SOUTH, + EAST, + WEST + } + + static class CardinalPointExtension + { + public static CardinalPoint Opposite(this CardinalPoint cardinalPoint) + { + switch (cardinalPoint) + { + case CardinalPoint.NORTH: return CardinalPoint.SOUTH; + case CardinalPoint.SOUTH: return CardinalPoint.NORTH; + case CardinalPoint.EAST: return CardinalPoint.WEST; + case CardinalPoint.WEST: return CardinalPoint.EAST; + default: throw new Exception(cardinalPoint + " doesn't have any opposite."); + } + } + } +} \ No newline at end of file diff --git a/MazeSandbox/MazeSandbox.csproj b/MazeSandbox/MazeSandbox.csproj new file mode 100644 index 0000000..2c0dacc --- /dev/null +++ b/MazeSandbox/MazeSandbox.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/MazeSandbox/Program.cs b/MazeSandbox/Program.cs new file mode 100644 index 0000000..b28ae4a --- /dev/null +++ b/MazeSandbox/Program.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Microsoft.VisualBasic.CompilerServices; +using TalesOfSenylan.Models.Dungeon; + +namespace MazeSandbox +{ + class Cell + { + public bool visited; + public Dictionary exits = new Dictionary(); + public Vector2 position; + + public Cell(Vector2 position) + { + this.position = position; + } + } + + class Maze + { + private int width; + private int height; + private Cell startingCell; + + private List> cells = new List>(); + private static Random random = new Random(); + private Stack lastCells = new Stack(); + + public Maze(int width, int height) + { + this.width = width; + this.height = height; + + for (int i = 0; i < height; i++) + { + List cellsRow = new List(); + for (int j = 0; j < width; j++) + { + Cell c = new Cell(new Vector2(j, i)); + cellsRow.Add(c); + } + cells.Add(cellsRow); + } + + startingCell = GetRandomCell(); + VisitCell(startingCell); + } + + private void VisitCell(Cell cell) + { + if (!cell.visited) + { + lastCells.Push(cell); + } + cell.visited = true; + + // Puis on regarde quelles sont les cellules voisines possibles et non visitées. + List adjacentUnvisitedCells = GetAdjacentUnvisitedCells(cell); + if (adjacentUnvisitedCells.Count > 0) + { + // S'il y a au moins une possibilité, on en choisit une au hasard, on ouvre le mur et on recommence avec la nouvelle cellule. + Cell selectedExit = GetRandomAdjacentUnvisitedCell(cell); + + CardinalPoint cp = GetExitFromCell(cell, selectedExit); + + cell.exits.Remove(cp); + cell.exits.Add(cp, selectedExit); + + selectedExit.exits.Remove(cp.Opposite()); + selectedExit.exits.Add(cp.Opposite(), cell); + + VisitCell(selectedExit); + } + // Lorsque l'on est revenu à la case de départ et qu'il n'y a plus de possibilités, le labyrinthe est terminé. + else if (lastCells.Count > 0 && startingCell.Equals(lastCells.Peek())) + { + return; + } + // S'il n'y en pas, on revient à la case précédente et on recommence. + else + { + if (lastCells.Count > 0) + { + lastCells.Pop(); + VisitCell(lastCells.Peek()); + } + } + } + + private CardinalPoint GetExitFromCell(Cell startingCell, Cell targetCell) + { + if (startingCell.position.X.Equals(targetCell.position.X)) + { + if (startingCell.position.Y - targetCell.position.Y == 1) + { + return CardinalPoint.NORTH; + } + if (startingCell.position.Y - targetCell.position.Y == -1) + { + return CardinalPoint.SOUTH; + } + } + else if (startingCell.position.Y.Equals(targetCell.position.Y)) + { + if (startingCell.position.X - targetCell.position.X == 1) + { + return CardinalPoint.WEST; + } + if (startingCell.position.X - targetCell.position.X == -1) + { + return CardinalPoint.EAST; + } + } + + return CardinalPoint.NORTH; // This means there is an error (potential TODO) + } + + private Cell GetRandomAdjacentUnvisitedCell(Cell cell) + { + List adjacentUnvisitedCells = GetAdjacentUnvisitedCells(cell); + return adjacentUnvisitedCells[random.Next(adjacentUnvisitedCells.Count)]; + } + + private List GetAdjacentUnvisitedCells(Cell cell) + { + List adjacentUnvisitedCells = new List(); + + List adjacentCells = GetAdjacentCellsOfCell(cell); + foreach (Cell adjacentCell in adjacentCells) + { + if (!adjacentCell.visited) + { + adjacentUnvisitedCells.Add(adjacentCell); + } + } + + return adjacentUnvisitedCells; + } + + private Cell GetRandomCell() + { + int randomX = random.Next(width); + int randomY = random.Next(height); + + return cells[randomX][randomY]; + } + + private List GetAdjacentCellsOfCell(Cell cell) + { + List adjacentCells = new List(); + + foreach (List cellsRow in cells) + { + foreach (Cell c in cellsRow) + { + if (IsAdjacent(c, cell)) + { + adjacentCells.Add(c); + } + } + } + + return adjacentCells; + } + + private static bool IsAdjacent(Cell c1, Cell c2) + { + if (AreOnDifferentColumnsAndRows(c1, c2)) + { + return false; + } + + return IsAdjacentX(c1, c2) || IsAdjacentY(c1, c2); + } + + private static bool IsAdjacentX(Cell c1, Cell c2) + { + if (c1.position.X + 1 == c2.position.X || c1.position.X - 1 == c2.position.X) + { + return true; + } + + return false; + } + + private static bool IsAdjacentY(Cell c1, Cell c2) + { + if (c1.position.Y + 1 == c2.position.Y || c1.position.Y - 1 == c2.position.Y) + { + return true; + } + + return false; + } + + private static bool AreOnDifferentColumnsAndRows(Cell c1, Cell c2) + { + return c1.position.X != c2.position.X && c1.position.Y != c2.position.Y; + } + } + + class Program + { + static void Main(string[] args) + { + Maze m = new Maze(3, 3); + } + } +} \ No newline at end of file