代码改变世界

栈和队列 迷宫求解

2011-01-02 14:49  Clingingboy  阅读(776)  评论(0编辑  收藏  举报

用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));
                }
            }
        }
    }
}

image

(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;
    }
}

这个例子还是发上源码吧,做演示用

http://cid-e61fe49e5e4bce66.office.live.com/self.aspx/.Public/wpfdemo/maze1.rar