I'm trying to make a maze generator in C#. None of the cells are ever set to CLOSED_TOP, CLOSED_BOTTOM, CLOSED_LEFT, CLOSED_RIGHT, or OPEN even when they do go down that new path.
I'm implementing a DFS algorithm for generating the maze:
- Pick any random cell in the grid (In this implementation we use the upper left hand corner.)
- Find a random neighboring cell that hasn't been visited yet.
- If you find one, strip the wall between the current cell and the neighboring cell.
- If you don't find one, return to the previous cell.
- Repeat steps 2 and 3 (or steps 2 and 4) for every cell in the grid.
The problem comes in when I have returned to a previous cell (cell A), and continuing on to a new neighboring cell (cell B) that hasn't been visited yet. I know my code visits the new cell (cell B) and continues down that path, but it never marks the previous cell (cell A) as having three open sides.
I don't know what is wrong in my logic. I know that the entire grid gets populated. What am I doing wrong?
using System;
using System.Collections.Generic;
using System.Text;
namespace MazeGenerator
{
class MapGenerator
{
private Random random = new Random();
public const int CLOSED = -1;
public const int OPEN_TOP = 0;
public const int OPEN_LEFT = 1;
public const int OPEN_RIGHT = 2;
public const int OPEN_BOTTOM = 3;
public const int OPEN_TOP_LEFT = 4;
public const int OPEN_TOP_RIGHT = 5;
public const int OPEN_TOP_BOTTOM = 6;
public const int OPEN_LEFT_RIGHT = 7;
public const int OPEN_LEFT_BOTTOM = 8;
public const int OPEN_RIGHT_BOTTOM = 9;
public const int CLOSED_TOP = 10;
public const int CLOSED_LEFT = 11;
public const int CLOSED_RIGHT = 12;
public const int CLOSED_BOTTOM = 13;
public const int OPEN = 14;
public int[] StartingPoint { get; }
public int[] EndingPoint { get; }
public int NumCols { get; set; }
public int NumRows { get; set; }
public int[,] MapGrid { get; }
public MapGenerator(int numRows, int numCols)
{
NumCols = numCols;
NumRows = numRows;
MapGrid = new int[numRows, numCols];
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
MapGrid[i,j] = CLOSED;
}
}
StartingPoint = new int[] { 0, 0 };
EndingPoint = new int[] { numRows - 1, numCols - 1 };
GoDownPath(0, 0);
}
private void GoDownPath(int row, int col)
{
int cellState = MapGrid[row, col];
while (NumberUnvisitedNeighbors(row, col) > 0)
{
// go down this path
int nextCellWall = random.Next(0, 4);
if (nextCellWall == 0)
{
// go up
if (row > 0 && MapGrid[row - 1, col] == CLOSED)
{
switch (cellState)
{
case CLOSED:
MapGrid[row, col] = OPEN_TOP;
break;
case OPEN_LEFT:
MapGrid[row, col] = OPEN_TOP_LEFT;
break;
case OPEN_RIGHT:
MapGrid[row, col] = OPEN_TOP_RIGHT;
break;
case OPEN_BOTTOM:
MapGrid[row, col] = OPEN_TOP_BOTTOM;
break;
case OPEN_LEFT_RIGHT:
MapGrid[row, col] = CLOSED_BOTTOM;
break;
case OPEN_LEFT_BOTTOM:
MapGrid[row, col] = CLOSED_RIGHT;
break;
case OPEN_RIGHT_BOTTOM:
MapGrid[row, col] = CLOSED_LEFT;
break;
case CLOSED_TOP:
MapGrid[row, col] = OPEN;
break;
default:
MapGrid[row, col] = OPEN;
break;
}
MapGrid[row - 1, col] = OPEN_BOTTOM;
GoDownPath(row - 1, col);
}
} else if (nextCellWall == 1)
{
// go down
if (row < NumRows - 1 && MapGrid[row + 1, col] == CLOSED)
{
switch (cellState)
{
case CLOSED:
MapGrid[row, col] = OPEN_BOTTOM;
break;
case OPEN_TOP:
MapGrid[row, col] = OPEN_TOP_BOTTOM;
break;
case OPEN_LEFT:
MapGrid[row, col] = OPEN_LEFT_BOTTOM;
break;
case OPEN_RIGHT:
MapGrid[row, col] = OPEN_RIGHT_BOTTOM;
break;
case OPEN_TOP_LEFT:
MapGrid[row, col] = CLOSED_RIGHT;
break;
case OPEN_TOP_RIGHT:
MapGrid[row, col] = CLOSED_LEFT;
break;
case OPEN_LEFT_RIGHT:
MapGrid[row, col] = CLOSED_TOP;
break;
case CLOSED_BOTTOM:
MapGrid[row, col] = OPEN;
break;
default:
MapGrid[row, col] = OPEN;
break;
}
MapGrid[row + 1, col] = OPEN_TOP;
GoDownPath(row + 1, col);
}
} else if (nextCellWall == 2)
{
// go left
if (col > 0 && MapGrid[row, col - 1] == CLOSED)
{
switch (cellState)
{
case CLOSED:
MapGrid[row, col] = OPEN_LEFT;
break;
case OPEN_TOP:
MapGrid[row, col] = OPEN_TOP_LEFT;
break;
case OPEN_RIGHT:
MapGrid[row, col] = OPEN_LEFT_RIGHT;
break;
case OPEN_BOTTOM:
MapGrid[row, col] = OPEN_LEFT_BOTTOM;
break;
case OPEN_TOP_RIGHT:
MapGrid[row, col] = CLOSED_BOTTOM;
break;
case OPEN_TOP_BOTTOM:
MapGrid[row, col] = CLOSED_RIGHT;
break;
case OPEN_RIGHT_BOTTOM:
MapGrid[row, col] = CLOSED_TOP;
break;
case CLOSED_LEFT:
MapGrid[row, col] = OPEN;
break;
default:
MapGrid[row, col] = OPEN;
break;
}
MapGrid[row, col - 1] = OPEN_RIGHT;
GoDownPath(row, col - 1);
}
} else if (nextCellWall == 3)
{
// go right
if (col < NumCols - 1 && MapGrid[row, col + 1] == CLOSED)
{
switch (cellState)
{
case CLOSED:
MapGrid[row, col] = OPEN_RIGHT;
break;
case OPEN_TOP:
MapGrid[row, col] = OPEN_TOP_RIGHT;
break;
case OPEN_LEFT:
MapGrid[row, col] = OPEN_LEFT_RIGHT;
break;
case OPEN_BOTTOM:
MapGrid[row, col] = OPEN_RIGHT_BOTTOM;
break;
case OPEN_TOP_LEFT:
MapGrid[row, col] = CLOSED_BOTTOM;
break;
case OPEN_TOP_BOTTOM:
MapGrid[row, col] = CLOSED_LEFT;
break;
case OPEN_LEFT_BOTTOM:
MapGrid[row, col] = CLOSED_TOP;
break;
case CLOSED_RIGHT:
MapGrid[row, col] = OPEN;
break;
default:
MapGrid[row, col] = OPEN;
break;
}
MapGrid[row, col + 1] = OPEN_LEFT;
GoDownPath(row, col + 1);
}
}
}
}
private int NumberUnvisitedNeighbors(int row, int col)
{
int numUnvisited = 0;
if (row > 0 && MapGrid[row - 1, col] == CLOSED) numUnvisited++;
if (row < NumRows - 1 && MapGrid[row + 1, col] == CLOSED) numUnvisited++;
if (col > 0 && MapGrid[row, col - 1] == CLOSED) numUnvisited++;
if (col < NumCols - 1 && MapGrid[row, col + 1] == CLOSED) numUnvisited++;
return numUnvisited;
}
}
}