分享一个C#实现的迷宫生成程序,继续演示LINQ语法在C#中的运用

threenewbee 2012-03-25 09:53:39
加精
简单地介绍下这个程序的功能。程序可以自动产生一个迷宫。迷宫的大小可以在
MazeModel mm = new MazeModel(7, 5);
这一行配置。为了简化起见,程序使用控制台输出,稍微修改,可以做到GUI中,效果更好。

迷宫中可以走的路径用|或者-标出,任意两点有且只有一条通路可以到达。大家可以看看自己解迷宫的水平哦。

迷宫算法本质上是一个最小生成树产生算法,这个数据结构大家都学过,忘记的可以自己找出来看看,在本程序中首先建立完整的通路图,然后随机从图中移除一条边,如果移除导致有顶点不可以到达,以后不再尝试移除它,直到图中没有可以移除的边为止。

最后显示输出。

下面是完整的代码,用了一些LINQ来简化搜索边的操作。

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

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MazeModel mm = new MazeModel(7, 5);
mm.DisplayMaze();
}
}

class MazeModel
{
private bool[] edges;

public int HorizontalVertex { get; private set; }

public int VerticalVertex { get; private set; }

private bool getEdgeValue(int edgeindex)
{
try
{
return edges[edgeindex];
}
catch
{
return false;
}
}

private void setEdgeValue(int edgeindex, bool value)
{
try
{
edges[edgeindex] = value;
}
catch { }
}

private int nodeToEdgeIndex(int x, int y, int dir)
{
if (x == 0 && dir == 1) return -1;
if (x % HorizontalVertex == HorizontalVertex - 1 && dir == 2) return -1;
if (y == 0 && dir == 0) return -1;
if (y >= HorizontalVertex * (VerticalVertex - 1) && dir == 3) return -1;

return (y * 2 + ((dir == 1 || dir == 2) ? 0 : (dir == 0 ? -1 : 1))) * HorizontalVertex + x - (dir == 1 ? 1 : 0);
}

private int nodeindexToEdgeIndex(int nodeindex, int dir)
{
int x;
int y;
nodeIndexToNode(nodeindex, out x, out y);
return nodeToEdgeIndex(x, y, dir);
}

private void nodeIndexToNode(int nodeindex, out int x, out int y)
{
x = nodeindex % HorizontalVertex;
y = nodeindex / HorizontalVertex;
}

private int nodeToNodeIndex(int x, int y)
{
return y * HorizontalVertex + x;
}

private void edgeIndexToNodeIndex(int edgeindex, out int node1, out int node2)
{
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
if (edgeindex / HorizontalVertex % 2 != 0)
{
x1 = x2 = edgeindex % HorizontalVertex;
y1 = edgeindex / (HorizontalVertex * 2);
y2 = y1 + 1;
}
else
{
x1 = edgeindex % HorizontalVertex;
x2 = x1 + 1;
y1 = y2 = edgeindex / (HorizontalVertex * 2);
}
node1 = nodeToNodeIndex(x1, y1);
node2 = nodeToNodeIndex(x2, y2);
}

private int edgeIndexToNodeIndex(int edgeindex, int node)
{
int node1, node2;
edgeIndexToNodeIndex(edgeindex, out node1, out node2);
return node1 == node ? node2 : node1;
}

private IEnumerable<int> getNodeEdges(int nodeIndex, List<int> blocklist)
{
return Enumerable
.Range(0, 4)
.Select(x => nodeindexToEdgeIndex(nodeIndex, x))
.Where(x => getEdgeValue(x) && !blocklist.Contains(x));
}

private void generateMaze()
{
List<int> blockEdges = new List<int>();
while (blockEdges.Count < HorizontalVertex * VerticalVertex - 1)
{
var nodes = Enumerable.Range(0, HorizontalVertex * VerticalVertex)
.Where(x => getNodeEdges(x, blockEdges).Count() > 1).ToList()
.Select(x => new { k = Guid.NewGuid(), v = x })
.OrderBy(x => x.k)
.Select(x => x.v).ToList();
if (nodes.Count == 0) return;
int node = nodes.First();
var tedges = getNodeEdges(node, blockEdges).ToList()
.Select(x => new { k = Guid.NewGuid(), v = x })
.OrderBy(x => x.k)
.Select(x => x.v).ToList();
if (tedges.Count == 0) return;
int edge = tedges.First();
var edgesbackup = edges.ToArray();
setEdgeValue(edge, false);
if (!testMaze())
{
blockEdges.Add(edge);
edges = edgesbackup;
}
}
}

private bool testMaze()
{
var found = new List<int>() { 0 };
findNode(0, found);
return found.Count() == HorizontalVertex * VerticalVertex;
}

private void findNode(int nodeindex, List<int> found)
{
var nextNodes = getNodeEdges(nodeindex, new List<int>())
.Select(x => edgeIndexToNodeIndex(x, nodeindex))
.Where(x => !found.Contains(x))
.ToList();
foreach (int item in nextNodes)
{
found.Add(item);
}
foreach (int item in nextNodes)
{
findNode(item, found);
}
}

public MazeModel(int horizontalvertex, int verticalvertex)
{
HorizontalVertex = horizontalvertex;
VerticalVertex = verticalvertex;
edges = Enumerable
.Range(0, horizontalvertex * (verticalvertex * 2 - 1) - 1)
.Select(x =>
x % horizontalvertex != horizontalvertex - 1 ||
x / horizontalvertex % 2 != 0
).ToArray();
generateMaze();
}

public void DisplayMaze()
{
for (int i = 0; i < VerticalVertex; i++)
{
for (int j = 0; j < HorizontalVertex; j++)
{
Console.Write("X");
if (j != HorizontalVertex - 1)
{
Console.Write(getEdgeValue(nodeToEdgeIndex(j, i, 2)) ? "-" : " ");
}
}
Console.WriteLine();
for (int j = 0; j < HorizontalVertex; j++)
{
if (i != VerticalVertex - 1)
{
Console.Write(getEdgeValue(nodeToEdgeIndex(j, i, 3)) ? "|" : " ");
Console.Write(" ");
}
}
Console.WriteLine();
}
}
}
}
...全文
3894 110 打赏 收藏 转发到动态 举报
写回复
用AI写文章
110 条回复
切换为时间正序
请发表友善的回复…
发表回复
L974888169 2014-10-31
  • 打赏
  • 举报
回复
不错!mark & study
baidu_22708709 2014-10-30
  • 打赏
  • 举报
回复
黑窗口里什么都没有,lz接下来怎么办,我是菜鸟,真心求教
wzuomin 2012-04-17
  • 打赏
  • 举报
回复
很精彩。顶
l_g_guo 2012-04-02
  • 打赏
  • 举报
回复
找时间学习一下。
风萧萧 2012-03-31
  • 打赏
  • 举报
回复
还没学到linq,看起来不错,
崇拜。。
okgoood 2012-03-31
  • 打赏
  • 举报
回复
翻页



okgoood 2012-03-31
  • 打赏
  • 举报
回复
100楼
okgoood 2012-03-31
  • 打赏
  • 举报
回复
盖楼
vagaas 2012-03-31
  • 打赏
  • 举报
回复
咔啪咔啪 2012-03-31
  • 打赏
  • 举报
回复
生成15*15的,i5-2310 4GRAM,5分钟过去了,表示很蛋疼
zy87741294 2012-03-31
  • 打赏
  • 举报
回复
不错啊
十年小白菜 2012-03-31
  • 打赏
  • 举报
回复
[Quote=引用 80 楼 的回复:]

引用 75 楼 的回复:
Linq太TM恶心了,效率太慢。

我用Lonq to SQL 参与开发过一个项目,还用的MVC3.0的框架。

项目做好后,我才知道原来所谓的Linq就这么恶心,说句实话都不如三层跑的快!

就这个网站,好长时间没登了,不知道怎么样了(我辞职了)。
到处都建议不用linq访问数据库,你们自己不听能怪谁。
[/Quote]不是吧。。。那还有不要继续研究学习么?
super_admi 2012-03-30
  • 打赏
  • 举报
回复
lin什么来着?干啥用的?值多少钱?我买了!
hfdsoft 2012-03-30
  • 打赏
  • 举报
回复
生成 20 x 20,五分钟了。i3/4G RAM
MagicKM 2012-03-30
  • 打赏
  • 举报
回复
很好很强大啊咯住!
linuxpxc 2012-03-30
  • 打赏
  • 举报
回复
MAZE~~~想象中~
xiaoyidon 2012-03-30
  • 打赏
  • 举报
回复
谢谢分享
liuyuainil 2012-03-30
  • 打赏
  • 举报
回复
一直都知道LINQ的强大,但实际中实在用的太少了,看来我们都必须花点心思来琢磨琢磨它。
叫我 Teacher 周 2012-03-30
  • 打赏
  • 举报
回复
[Quote=引用 75 楼 的回复:]
Linq太TM恶心了,效率太慢。

我用Lonq to SQL 参与开发过一个项目,还用的MVC3.0的框架。

项目做好后,我才知道原来所谓的Linq就这么恶心,说句实话都不如三层跑的快!

就这个网站,好长时间没登了,不知道怎么样了(我辞职了)。
[/Quote]

那是你经验不足
tiangong789 2012-03-30
  • 打赏
  • 举报
回复
LINQ应该是一种提高开发效率但是降低了运行效率的东西。。而且不宜调试,不能过于追捧。只能写些小程序,比如学校老师布置给学生的小作业。。
加载更多回复(51)

110,532

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧