I decided to make my own dungeon generator, after reading a bit about it. This is my first effort. I can only say that it works, but I believe there's room for some improvement, because I believe my self-taught coding skills are basic.
To use this code, call:
dungeonGenerator = new DungeonGenerator();
dungeonGenerator.CreateDungeonRoom(115, 32);
dungeonGenerator.CellsToGenerate = 1500;
dungeonGenerator.CreateDungeonScenery();
dungeonGenerator.LogDungeon();
Tile.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace DungeonGenerator
{
struct Cell
{
/// <summary>
/// Location in the grid
/// </summary>
public CellType CellType;
public Cell(CellType cellType)
{
CellType = cellType;
}
public override string ToString()
{
return "Type: " + CellType;
}
}
}
CellType.cs
/// <summary>
/// If the cell is walkable or not
/// </summary>
public enum CellType
{
WALL, GROUND, START
}
Direction.cs
enum Direction
{
UP, DOWN, LEFT, RIGHT
}
DungeonGenerator.cs
using System;
namespace DungeonGenerator
{
public class DungeonGenerator
{
public int Width { get; set; }
public int Height { get; set; }
public int CellsToGenerate { get; set; }
Cell[,] DungeonCells { get; set; }
public void CreateDungeonRoom(int RoomWidth, int RoomHeight)
{
Width = RoomWidth;
Height = RoomHeight;
DungeonCells = new Cell[Width,Height];
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
CellType cellType = CellType.WALL;
DungeonCells[x, y] = new Cell(cellType);
}
}
}
/// <summary>
/// Populate the insides of the room
/// </summary>
public void CreateDungeonScenery()
{
//Make it so that the outside walls are untouched
int minValueXY = 1;
int maxValueX = Width - 2;
int maxValueY = Height - 2;
//Choose a random position in the room
Random random = new Random();
int startX = random.Next(minValueXY, maxValueX);
int startY = random.Next(minValueXY, maxValueY);
//Mark it as the starting position, for player placement, maybe?
DungeonCells[startX, startY] = new Cell(CellType.START);
//Get directions to an array for random choosing
Array values = Enum.GetValues(typeof(Direction));
//From the starting position, proceed to create X number of ground cells
int cellCount = 0;
while (cellCount < CellsToGenerate)
{
//Choose a direction at random
Direction direction = (Direction)values.GetValue(random.Next(values.Length));
if (direction == Direction.UP)
{
startY -= 1;
if (startY < minValueXY) { startY = minValueXY; }
}
else if (direction == Direction.DOWN)
{
if (startY < maxValueY) { startY += 1; }
}
else if (direction == Direction.LEFT)
{
startX -= 1;
if (startX < minValueXY) { startX = minValueXY; }
}
else if (direction == Direction.RIGHT)
{
if (startX < maxValueX) { startX += 1; }
}
//From the position chosen, mark it as ground, if possible
if (CreateGround(startX, startY))
{
//Mark the cell as ground
DungeonCells[startX, startY].CellType = CellType.GROUND;
//Add one to cells created
cellCount++;
}
}
}
private bool CreateGround(int startX, int startY)
{
//There's not a wall there, so there's nothing to be done here
if (DungeonCells[startX, startY].CellType != CellType.WALL)
{
return false;
}
return true;
}
public void LogDungeon()
{
Console.Clear();
for (int y = 0; y < Height; y++)
{
string line = "";
for (int x = 0; x < Width; x++)
{
if (DungeonCells[x, y].CellType == CellType.GROUND)
{
line += "O";
}
else if (DungeonCells[x, y].CellType == CellType.WALL)
{
line += "█";
}
else if (DungeonCells[x, y].CellType == CellType.START)
{
line += "H";
}
}
Console.WriteLine(line);
}
}
}
}
From the start, I realize I can improve the code:
By preventing backtracking, but backtracking sometimes makes some nice crevices here and there. Resolve this by making impossible to select the direct opposite of the previous direction? I want to figure out a way to improve that direction choosing part (currently I don't know how).
On purpose, I left the number of cells to generate out of the CreateDungeonRoom() method because I'm still deciding if I really want to make users insert the number of ground tiles as a specific number or a percentage, or enum. We will see.
Here is an example of a dungeon with 115 width, 32 height and 1500 ground tiles and the player starting position (it's the H somewhere)
as incisive as [needed]
beats indecisive almost every time - or nearly? Almost always? Often? Arrghh…) \$\endgroup\$