用WPF做演示
1.用Stack记录和回溯
在现实生活中,在你迷路的时候,总是记录一些可记忆的建筑物作为返回的标志(比如你出去玩,总得回家的吧,那么就得记得回家的路)
(1)画迷宫
public class MazeElement : FrameworkElement
{
public MazeElement(int[,] mg)
{
this.mg = mg;
}
int[,] mg=null;
protected override void OnRender(DrawingContext dc)
{
var width = 40;
dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, 10 * width, 10 * width));
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (mg[i, j] == 1)
{
dc.DrawRectangle(Brushes.Gray, null, new Rect(j * (width), i * (width), width - 1, width - 1));
}
else
{
dc.DrawRectangle(Brushes.White, null, new Rect(j * (width), i * (width), width - 1, width - 1));
}
}
}
}
}
(2)白色表示可以通过的坐标,从坐标1,1寻找坐标(8,8)点
一个块的的数据结构如下,即坐标点加下个可寻找点的方向
public class Block
{
public Point Point { get; set; }
public int Direction { get; set; }
}
(3)若找到的下个是白点且没有重复的话,则继续寻找,否则就回溯,找另外的出口,其实就是穷举法了…
算法如下
public void MgPath(Point start, Point end)
{
Block temp = null;
bool find = false;
while (st.Count > 0)
{
temp = st.Peek();
_point = temp.Point;
Console.WriteLine(temp.Point.ToString());
var point = temp.Point;
var di = temp.Direction;
//UI Refresh don't care
System.Threading.Thread.Sleep(100);
Dispatcher.BeginInvoke(new Action(() =>
{
this.InvalidateVisual();
}), DispatcherPriority.Render);
if (point.Equals(end))
{
finished = true;
break;
}
//not find
find = false;
//find next block
while (di < 4 && !find)
{
di++;
switch (di)
{
case 0://top
point.Y = temp.Point.Y - 1;
point.X = temp.Point.X;
break;
case 1://right
point.X = temp.Point.X + 1;
point.Y = temp.Point.Y;
break;
case 2://bottom
point.Y = temp.Point.Y + 1;
point.X = temp.Point.X;
break;
case 3://left
point.X = temp.Point.X - 1;
point.Y = temp.Point.Y;
break;
}
if (mg[(int)point.X, (int)point.Y] == 0) find = true;
}
//if find
if (find)
{
temp.Direction = di;
st.Push(new Block() { Point = point, Direction = -1 });
//mark already visit
mg[(int)point.X, (int)point.Y] = -1;
}
else
{
//not find
mg[(int)temp.Point.X, (int)temp.Point.Y] = 0;
st.Pop();
}
break;
}
}