Initial commit

This commit is contained in:
dlmw
2020-11-19 11:59:29 +01:00
commit a03e1b510c
5 changed files with 300 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@ -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/

16
MazeSandbox.sln Normal file
View File

@ -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

View File

@ -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.");
}
}
}
}

View File

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>

212
MazeSandbox/Program.cs Normal file
View File

@ -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<CardinalPoint, Cell> exits = new Dictionary<CardinalPoint, Cell>();
public Vector2 position;
public Cell(Vector2 position)
{
this.position = position;
}
}
class Maze
{
private int width;
private int height;
private Cell startingCell;
private List<List<Cell>> cells = new List<List<Cell>>();
private static Random random = new Random();
private Stack<Cell> lastCells = new Stack<Cell>();
public Maze(int width, int height)
{
this.width = width;
this.height = height;
for (int i = 0; i < height; i++)
{
List<Cell> cellsRow = new List<Cell>();
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<Cell> 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<Cell> adjacentUnvisitedCells = GetAdjacentUnvisitedCells(cell);
return adjacentUnvisitedCells[random.Next(adjacentUnvisitedCells.Count)];
}
private List<Cell> GetAdjacentUnvisitedCells(Cell cell)
{
List<Cell> adjacentUnvisitedCells = new List<Cell>();
List<Cell> 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<Cell> GetAdjacentCellsOfCell(Cell cell)
{
List<Cell> adjacentCells = new List<Cell>();
foreach (List<Cell> 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);
}
}
}