Para o jogo que estou criando preciso de uns labirintos e como não achei algo que pudesse gerar para um arquivo texto, estou implementando o meu mesmo, com algumas leituras vi que o algoritmo mais fácil para este caso seria a através de uma pilha assim eu garanto que percorri todos os elementos do labirinto.

o algortimo consiste em escolher uma posicao aleatoria, e buscar os vizinhos nao visitados ao redor, encontrando um abre caminho ateh ele e empilha o mesmo, e vai fazendo isto até que não existam vizinhos não visitados, assim vai desempilhando para voltar no caminho e tentando achar vizinhos não visitados no caminho de volta.
Assim percorremos todo o mapa mas ainda ficam uns becos sem saída, como pode ver marcado neste desenho que fiz quando estava testando manualmente o algoritmo

o teste foi de 5×5 e marquei com bolinhas abobora os becos sem saída, na próxima versão do algoritmo vou guardar os becos sem saída e conectar com algum vizinho =) eh melhor fazzer andar em círculos do que encontrar um beco em saída, hehehe

Seguem os códigos fonte, do gerador e do programa que esta gravando num arquivo texto o maze gerado, que por sinal esta com algum problema ainda …

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MazeGenerator
{
class Program
{
static void Main(string[] args)
{
MazeGen mazeGen = new MazeGen();
MazeGen.MazeCell[,] maze = mazeGen.generateMaze(5,5);

string fileName = “c:/work/maze” + DateTime.Now.ToBinary() + “.txt”;
FileStream stream = File.Open(fileName, FileMode.OpenOrCreate);
StreamWriter writer = new StreamWriter(stream);

for (int n = 0; n < maze.GetLength(0); n++)
{
for (int conn = 0; conn < 3; conn++)
{
for (int m = 0; m < maze.GetLength(1); m++)
{
writer.Write(maze[n, m].conections[conn, 0] == MazeGen.OPEN ? "_" : "*");
writer.Write(maze[n, m].conections[conn, 1] == MazeGen.OPEN ? "_" : "*");
writer.Write(maze[n, m].conections[conn, 2] == MazeGen.OPEN ? "_" : "*");
}
writer.WriteLine();
}
}
writer.Close();
}
}
}

MazeGen,cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MazeGenerator
{
public class MazeGen
{
public const Boolean DEBUG = true;
public const int CLOSED = 0;
public const int OPEN = 1;

public const int NEIGHBOR_X = 0;
public const int NEIGHBOR_Y = 1;
public const int NEIGHBOR_CONNECTION_2OPEN_X = 2;
public const int NEIGHBOR_CONNECTION_2OPEN_Y = 3;
public const int POSSIBLE_NEIGHBORS = 4;

public static Random random = new Random();

public class MazeCell
{
public MazeCell(int X, int Y)
{
this.X = X;
this.Y = Y;
this.Visited = false;
}

public Boolean Visited = false;
public int X;
public int Y;
// north, east, south, west
public byte[,] conections = { { CLOSED, CLOSED, CLOSED },
{ CLOSED, OPEN, CLOSED },
{ CLOSED, CLOSED, CLOSED } };

public override string ToString()
{
string buffer = "";
foreach( byte one in conections){
buffer += one.ToString();
}

return X + "," + Y + " [" + buffer +"] ";
}
}

// used to random the neighbor cell
// { increment of X, increment of Y, connection to open in the neighbor }
int[,] SearchNeighBorNumbers = { { 0, -1, 1, 2 }, { 1, 0, 0, 1 }, { 0, 1, 1, 0 }, { -1, 0, 2, 1 } };

public MazeCell[,] generateMaze(int rows, int cols)
{

// fill the matrix
MazeCell[,] result = new MazeCell[rows, cols];
for (int n = 0; n < result.GetLength(0); n++)
{
for (int m = 0; m < result.GetLength(1); m++)
{
result[n, m] = new MazeCell(n, m);
}
}

int visited = 1;
int total = rows * cols;

Stack path = new Stack();

int x = random.Next(1, rows - 1);
int y = random.Next(1, cols - 1);

result[x, y].Visited = true;

path.Push(result[x, y]);
MazeCell current = result[x, y];

while (visited < total)
{
// try the unvisited neighbors
int neighborRow = random.Next(0, 3);
MazeCell neighbor = nextRandomUnvisited(result, current, neighborRow);

int tries = 1;
while (tries < POSSIBLE_NEIGHBORS && neighbor == null)
{
neighborRow ++;
if( neighborRow >= POSSIBLE_NEIGHBORS ){
neighborRow = 0;
}
neighbor = nextRandomUnvisited(result, current, neighborRow);
tries ++;
}

if (neighbor == null)
{
current = (MazeCell)path.Pop();
}
else
{
current.conections[
1 + SearchNeighBorNumbers[neighborRow, NEIGHBOR_X],
1 + SearchNeighBorNumbers[neighborRow, NEIGHBOR_Y]] = OPEN;

neighbor.Visited = true;
neighbor.conections[
SearchNeighBorNumbers[neighborRow, NEIGHBOR_CONNECTION_2OPEN_X],
SearchNeighBorNumbers[neighborRow, NEIGHBOR_CONNECTION_2OPEN_Y]] = OPEN;

if (DEBUG){Console.WriteLine(“from {0} to {1}”, current, neighbor);}

path.Push(neighbor);
current = neighbor;
visited++;
}
}

return result;
}

public MazeCell nextRandomUnvisited(MazeCell[,] result, MazeCell current, int neighborRow)
{

int testX = current.X + SearchNeighBorNumbers[neighborRow, NEIGHBOR_X];
int testY = current.Y + SearchNeighBorNumbers[neighborRow, NEIGHBOR_Y];

// check if neighbor exists
// if not will try again
if (testX >= 0 && testX < result.GetLength(0) && testY >= 0 && testY < result.GetLength(1))
{

if (!result[testX, testY].Visited)
{
return result[testX, testY];
}
}

return null;
}

}
}