C#迷宫生成的算法

超级大笨狼 2008-07-24 10:52:39
加精
1,利用C#自带的几种集合类可以用来描述集合的概念,比如{1,2},{3,4,5}可以用List<List<int>>来表示集合的集合
2,所谓迷宫,并不是随机生成路其他的围墙,而是如何拆墙。比如{1,2},{3,4,5}拆掉2和3只间的墙,就形成了{1,2,3,4,5}
最初的格子状态就是{1},{2},{3},{4}.....如果随机找到2集合,再把其中的墙随机挑选一个拆掉,直到全部集合连通成一个几何,迷宫就生成完毕。
3,不需要递归,递归可能会带来低效率,如果可以不用就不用。
4,如果需要在集合里快速查找一个数据,建议用Dictionary<>,因为他查找一个Key的复杂度是O(1),如果在集合里随机挑选一个东东,用List<T>比较方便。
5,效果见http://www.dullwolf.cn/Wall/
6,代码还可以优化,有兴趣的同学试验一下:)


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;

namespace Wall
{
public partial class _Default : System.Web.UI.Page
{
protected StringBuilder HTML = new StringBuilder();
protected StringBuilder SCRIPT = new StringBuilder();
private List<List<int>> totalWays = new List<List<int>>();
private Dictionary<string, bool> allWalls = new Dictionary<string, bool>();
private Dictionary<string, bool> deleteWalls = new Dictionary<string, bool>();
protected int maxX;
protected int maxY;
protected void Page_Load(object sender, EventArgs e)
{
HTML.Append("");
maxX = Convert.ToInt32(this.TextBox1.Text);
maxY = Convert.ToInt32(this.TextBox2.Text);

for (int y = 0; y < maxY; y++)
{
HTML.Append("<tr>" );
for (int x = 1; x <= maxX; x++)
{
int id = x + y * maxX;
List<int> room = new List<int>();
room.Add(id);
totalWays.Add(room);
string theWall = makeWall(id, id + 1);
if (x < maxX) { allWalls.Add(theWall,true); }
theWall = makeWall(id, id + maxX);
if (y < maxY) { allWalls.Add(theWall, true); }
HTML.Append("<td id=td" + id + ">" + " </td>");
}
HTML.Append("</tr>");
}
while (totalWays.Count > 1)
{
makePuzzle();
}
foreach (string Key in deleteWalls.Keys)
{
SCRIPT.Append("d(" + Key + ");");
}
}
private void makePuzzle()
{
//随机在全部中选择一个回廊
int firstChoice = randomInt(totalWays.Count);
//列出该回廊全部相关回廊;
List<int> firstChoiceWay = totalWays[firstChoice];
List<List<int>> tempWay = new List<List<int>>();
for (int i = 0; i < totalWays.Count; i++)
{
if (i != firstChoice)
{
if (isNeighbor(firstChoiceWay, totalWays[i]))
{
tempWay.Add(totalWays[i]);
//break;
}
}
}
//随机在totalWays中选择一个回廊
int secondChoice = randomInt(tempWay.Count);
List<int> secondCoiceWay = tempWay[secondChoice];
//得到2者间全部可以拆的墙
List<string> tempWalls = new List<string>();
for (int i = 0; i < firstChoiceWay.Count; i++)
{
for (int j = 0; j < secondCoiceWay.Count; j++)
{
if (IsExsists(firstChoiceWay[i], secondCoiceWay[j]))
{
tempWalls.Add(makeWall(firstChoiceWay[i], secondCoiceWay[j]));
}
}
}
int thirdChoice = randomInt(tempWalls.Count);
string theWall = tempWalls[thirdChoice];
//纪录拆墙办法
deleteWalls.Add(theWall,true);
//增加一个新的
List<int> newWay = new List<int>();
newWay.AddRange(firstChoiceWay);
newWay.AddRange(secondCoiceWay);
totalWays.Add(newWay);
//移掉2个
totalWays.Remove(firstChoiceWay);
totalWays.Remove(secondCoiceWay);
allWalls.Remove(theWall);
}

private string makeWall(int x, int y)
{
if (x > y)
{
return y.ToString() + "," + x;
}
else
{
return x.ToString() + "," + y;
}
}
private int randomInt(int input)
{
Random rand = new Random(input);
//随机在全部中选择一个
//得到回廊的回廊
if (input == 0)
{
return 0;
}
else
{
return rand.Next(0, input);
}
}


/// <summary>
/// 判断两个集合是否是邻居
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
private bool isNeighbor(List<int> a, List<int> b)
{
bool re = false;
for (int i = 0; i < a.Count; i++)
{
for (int j = 0; j < b.Count; j++)
{
if (IsExsists(a[i], b[j]))
{
re = true;
break;
}
}
if (re) { break; }
}
return re;
}
private bool IsExsists(int x, int y)
{
bool re = false;
if (Math.Abs(x-y) == 1 || Math.Abs(x-y) == maxX)
{
string theWall = makeWall(x,y);
if (allWalls.ContainsKey(theWall))
{
re = true;
}
}
return re;
}
}
}








...全文
4931 143 打赏 收藏 转发到动态 举报
写回复
用AI写文章
143 条回复
切换为时间正序
请发表友善的回复…
发表回复
mosyangyang 2011-07-13
  • 打赏
  • 举报
回复
学习中~
zoedaid 2011-06-08
  • 打赏
  • 举报
回复
很强悍,初学者来学习
new_fengzi 2011-05-31
  • 打赏
  • 举报
回复
mark
Arcan 2009-10-15
  • 打赏
  • 举报
回复
拆墙的思想令我茅塞顿开。不过楼主的算法有些慢,面对大迷宫耗费时间太长了。
xylhx 2009-07-03
  • 打赏
  • 举报
回复
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{

}
}
zzlb0224 2009-02-13
  • 打赏
  • 举报
回复
拆墙确实比找路方便 嘿嘿
finalfantasy000 2008-10-14
  • 打赏
  • 举报
回复
mark
NiRuo 2008-10-13
  • 打赏
  • 举报
回复
[Quote=引用 124 楼 superdullwolf 的回复:]
如果想“路”的问题就麻烦了,所谓迷宫,并不是随机生成路和围墙,而是如何拆墙。
最开始所有单元格(回廊)都是不连通的,随机找到2个拆掉墙就连通成大的回廊了。
这样一直拆下去,每次都是随机选择回廊,随机选择拆一个墙,一直到最后全部连通。
[/Quote]

恕小女不才,希望能得到比这更详细的说明,例如:回廊和可以拆的墙的详细解释。
看了几遍还是没有看懂。。。惭愧!!
超级大笨狼 2008-10-13
  • 打赏
  • 举报
回复
恩,思路就是拆墙.
代码不必用我这个,明白了自己写最好了.

假设有4000个格子,思路:
最开始的状态:{1}{2}{3}{4}{5}{6}...{4000}
随便合并某两个,假设是4和2:{1}{3}{4,2}{5}{6}...{4000}
再随便合并某两个,,假设是4和2和101:{1}{3}{4,2,101}{6}...{4000}

一直重复下去,直到只剩下一个集合

就完成了.

zcsheng2008 2008-10-13
  • 打赏
  • 举报
回复
我操,看不懂
Jack_xiao 2008-10-11
  • 打赏
  • 举报
回复
顶!
多谢分享!
StuRun 2008-10-10
  • 打赏
  • 举报
回复
MARK
windywell 2008-09-06
  • 打赏
  • 举报
回复
厉害
不过不是很懂
zjgrape 2008-09-02
  • 打赏
  • 举报
回复
好强悍东西.顶一个
kai333hui 2008-08-28
  • 打赏
  • 举报
回复
刚刚测试了下 好东西 强悍 学习学习!!!
  • 打赏
  • 举报
回复
算了!顶下!
超级大笨狼 2008-08-05
  • 打赏
  • 举报
回复
如果想“路”的问题就麻烦了,所谓迷宫,并不是随机生成路和围墙,而是如何拆墙。
最开始所有单元格(回廊)都是不连通的,随机找到2个拆掉墙就连通成大的回廊了。
这样一直拆下去,每次都是随机选择回廊,随机选择拆一个墙,一直到最后全部连通。
Code従業員 2008-08-05
  • 打赏
  • 举报
回复
以前想做过,然而,不清楚在如何在保证只有一条路的时候创建分支。好好学习学习
starsky1984 2008-08-04
  • 打赏
  • 举报
回复
看不懂,继续学习...
ChDw 2008-08-04
  • 打赏
  • 举报
回复
[Quote=引用 119 楼 zbd695321 的回复:]
为何不随机生成一个S型的通路,然后覆盖在全是围墙的迷宫上呢? 这样是不是更快一些?
[/Quote]

那么这个迷宫有什么意义,只有一条路线,也就不存在任何的分叉路了,无论迷宫多大都可以在马上搞掂。
加载更多回复(118)

25,985

社区成员

发帖
与我相关
我的任务
社区描述
高性能WEB开发
社区管理员
  • 高性能WEB开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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