我尝试实现此答案中给出的 Java 代码的 C# 版本来生成随机迷宫,但我的代码并没有完全正确地生成迷宫 – 它创建了“孤立”的墙部分,换句话说:
p>
#####
# #
# # #
# #
#####
… 一个墙段被 7 个通道段包围。这个算法的整个迷宫是这样的:
###########
# #
# # # ### #
# # #
### # ### #
# # # #
# ### # # #
# #
### ### # #
# #
###########
我不确定我链接到的算法如何避免这种情况,以及我正在做的不同是导致它。迷宫应该只是走廊,没有孤立的墙壁部分,例如:
谁能帮助我我的算法做错了什么?这是我的算法:
namespace MazeGenerator {
public class MazeGenerator {
private readonly Random _rnd = new Random(1212);
// NOTE: cells grid dimensions must be odd, odd (will give size 1 border around maze)
private readonly bool[,] _cells = new bool[11,11]; // All maze cells default to wall (false), not path (true)
private struct CellPosition {
public int X;
public int Y;
public override string ToString() {
return $"{X}, {Y}";
}
}
public bool[,] GenerateMaze() {
Console.Clear();
// Random starting position must be odd, odd (will give size 1 border around maze)
//var posRnd = new CellPosition {
// X = _rnd.Next(0, _cells.GetLength(0)),
// Y = _rnd.Next(0, _cells.GetLength(1))
//};
var posRnd = new CellPosition {
X = 1,
Y = 1
};
setCell(posRnd, true); // Set initial random cell to path
var candidateCells = new List();
candidateCells.AddRange(getCandidateCellsFor(posRnd, false)); // Get cell's wall candidates
while (candidateCells.Count > 0) {
// Pick random cell from candidate collection
int thisCellIndex;
var thisCell = candidateCells[thisCellIndex = _rnd.Next(0, candidateCells.Count)];
// Get cell's path candidates
var pathCandidates = getCandidateCellsFor(thisCell, true);
if (pathCandidates.Count > 0) {
// Connect random path candidate with cell
connectCell(pathCandidates[_rnd.Next(0, pathCandidates.Count)], thisCell);
}
// Add this candidate cell's wall candidates to collection to process
candidateCells.AddRange(getCandidateCellsFor(thisCell, false));
// Remove this candidate call from collection
candidateCells.RemoveAt(thisCellIndex);
renderMaze(_cells);
//Thread.Sleep(1000);
}
return _cells;
}
///
/// Sets the cell in the given position to the given state.
///
/// The position of the cell to set.
/// The state to set the cell to. If true, sets to path; otherwise, sets to wall.
private void setCell(CellPosition posRnd, bool isPath) {
_cells[posRnd.X, posRnd.Y] = isPath;
}
///
/// Connects two cells that are a distance of 2 apart with path, where cell A is already a path cell.
///
/// Path cell to connect cell B to.
/// Wall cell to connect to cell A.
private void connectCell(CellPosition cellA, CellPosition cellB) {
var x = (cellA.X + cellB.X) / 2;
var y = (cellA.Y + cellB.Y) / 2;
_cells[cellB.X, cellB.Y] = true;
_cells[x, y] = true;
}
private bool cellHasValidPosition(CellPosition position) {
return
position.X >= 0 &&
position.Y >= 0 &&
position.X < _cells.GetLength(0) &&
position.Y < _cells.GetLength(1);
}
///
/// Gets candidate cells for a given cell given its position.
///
/// The cell's position.
/// If true, gets path candidate cells; otherwise, gets wall candidate cells.
/// The candidate cells for the given cell.
private IList getCandidateCellsFor(CellPosition position, bool getPathCells) {
var candidatePathCells = new List();
var candidateWallCells = new List();
var northCandidate = new CellPosition { X = position.X, Y = position.Y - 2 };
var eastCandidate = new CellPosition { X = position.X + 2, Y = position.Y };
var southCandidate = new CellPosition { X = position.X, Y = position.Y + 2 };
var westCandidate = new CellPosition { X = position.X - 2, Y = position.Y };
if (cellHasValidPosition(northCandidate)) {
if (_cells[northCandidate.X, northCandidate.Y]) { candidatePathCells.Add(northCandidate); }
else { candidateWallCells.Add(northCandidate); }
}
if (cellHasValidPosition(eastCandidate)) {
if (_cells[eastCandidate.X, eastCandidate.Y]) { candidatePathCells.Add(eastCandidate); }
else { candidateWallCells.Add(eastCandidate); }
}
if (cellHasValidPosition(southCandidate)) {
if (_cells[southCandidate.X, southCandidate.Y]) { candidatePathCells.Add(southCandidate); }
else { candidateWallCells.Add(southCandidate); }
}
if (cellHasValidPosition(westCandidate)) {
if (_cells[westCandidate.X, westCandidate.Y]) { candidatePathCells.Add(westCandidate); }
else { candidateWallCells.Add(westCandidate); }
}
if (getPathCells) { return candidatePathCells; }
else { return candidateWallCells; }
}
private static void renderMaze(bool[,] maze) {
Console.Clear();
for (var x = 0; x < maze.GetLength(0); x++) {
for (var y = 0; y < maze.GetLength(1); y++) {
Console.Write($"{(maze[x,y] ? " " : "#")}");
}
Console.WriteLine();
}
}
}
}
© 版权声明
本站下载的源码均来自公开网络收集转发二次开发而来,
若侵犯了您的合法权益,请来信通知我们1413333033@qq.com,
我们会及时删除,给您带来的不便,我们深表歉意。
下载用户仅供学习交流,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担,访问及下载者下载默认同意本站声明的免责申明,请合理使用切勿商用。
THE END
暂无评论内容