【路线搜索】 路线搜索算法C# WPF演示

本文介绍了一个路线搜索器的应用实例,展示了如何使用不同的搜索算法(如Dijkstra算法和A*算法)来寻找从起点到终点的最优路径。代码示例中包含了手动设定路线和随机生成路线的功能,并实现了交互式的界面,允许用户通过点击选择起点和终点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

945182c97a8705654024c8ade7fea03a.png

outside_default.png应用示例

视频演示

部分代码:

public partial class MainWindow : Window
    {
        RouteFinder rf = new RouteFinder();//路线搜索器


        public MainWindow()
        {
            InitializeComponent();
            SetupCbo();
            AddRoads(1);
        }
        //设置下拉列表框项
        private void SetupCbo()
        {   //添加搜素方法对象到下拉列表框
            cboMethod.Items.Add(new FinderMethodOption("Dijkstra(低效)", FinderMethod.Dijkstra));
            cboMethod.Items.Add(new FinderMethodOption("A* (糟糕实现)", FinderMethod.AStarImperfect));
            cboMethod.Items.Add(new FinderMethodOption("A* (正确)", FinderMethod.AStar));


            cboMethod.SelectedIndex = 0;
        }
        //添加路线  mapID: canvas索引
        private void AddRoads(int mapID)
        {
            rf.AllRoads.Clear();//清空所有路线


            switch(mapID)
            {
                case 1://手动添加路线
                    rf.AddRoad(0, 0, 0, 5);//起点->终点
                    rf.AddRoad(0, 0, 3, 0);
                    rf.AddRoad(3, 0, 4, 3);
                    rf.AddRoad(4, 3, 2, 1);
                    rf.AddRoad(2, 1, 0, 5);
                    rf.AddRoad(2, 1, 3, 0);
                    rf.AddRoad(3, 0, 5, 1);
                    rf.AddRoad(0, 5, 3, 5);
                    rf.AddRoad(0, 0, 1, 1);
                    rf.AddRoad(1, 1, 2, 1);
                    rf.AddRoad(1, 1, 1, 2);


                    rf.AddRoad(5, 9, 3, 4);
                    rf.AddRoad(4, 3, 5,7);
                    rf.AddRoad(5, 7, 3, 4);
                    rf.AddRoad(3, 5, 3, 4);
                    rf.AddRoad(0, 5, 4, 3);
                    rf.AddRoad(3, 5, 5, 9);
                    rf.AddRoad(5, 7, 5, 9);
                    rf.AddRoad(1, 2, 0, 5);
                    rf.AddRoad(5, 1, 4, 3);
                    break;


                case 2://生成随机路线
                    Random r = new Random();


                    for (int x = 0; x <= 9; x++)//x [0-9]
                    {
                        int ry = r.Next(5, 10);
                        for (int y = 0; y <= ry; y++)
                        {
                            rf.AddRoad(x, y, x + 1, y);
                            rf.AddRoad(x + 1, y, x + 1, y + 1);
                        }
                    }


                    for (int i = 1; i <= 45; i++)
                    {   //
                        int rn = r.Next(20, rf.AllRoads.Count - 20);
                        rf.AllRoads.RemoveAt(rn);
                    }
                    break;
            }


            DrawRoads();
            DrawPoints();
        }
        //绘制点  点画布
        private void DrawPoints()
        {
            PointsCanvas.Children.Clear();//点画布清空


            foreach (Road r in rf.AllRoads)//遍历路线
            {
                for(int i = 1; i <= 2; i++)
                {
                    int px;
                    int py;


                    if(i == 1)
                    {//路线起点
                        px = r.From.x;
                        py = r.From.y;
                    }
                    else
                    {//路线终点
                        px = r.To.x;
                        py = r.To.y;
                    }


                    Ellipse e = new Ellipse();//椭圆
                    e.Width = 10;
                    e.Height = 10;
                    e.Fill = Brushes.AliceBlue;//蓝色填充
                    e.Stroke = Brushes.Navy;//圆边线
                    e.Cursor = Cursors.Hand;//获取或设置当鼠标指针悬停在此元素上时显示的光标。


                    e.MouseLeftButtonUp += Point_LeftMouseUp;//节点左键单击抬起事件绑定处理函数
                    e.MouseRightButtonUp += Point_RightMouseUp;//右键抬起事件绑定处理函数


                    e.Tag = string.Format("{0},{1}", px, py);//节点标签
                    e.ToolTip = e.Tag;//获取或设置在用户界面 (UI) 中为此元素显示的工具提示对象。
                    //矫正圆心位置
                    Canvas.SetLeft(e, ConvertPoint(px) - 5);//设置给定依赖对象的 System.Windows.Controls.Canvas.Left 附加属性的值。
                    Canvas.SetTop(e, ConvertPoint(py) - 5);


                    PointsCanvas.Children.Add(e);//绘制节点
                }
            }
        }
        //单击点右键抬起
        private void Point_RightMouseUp(object sender, MouseButtonEventArgs e)
        {
            Ellipse ell = (sender as Ellipse);//获取单击的椭圆
            //获取终点位置坐标
            txtToX.Text = ell.Tag.ToString().Split(Convert.ToChar(","))[0]; 
            txtToY.Text = ell.Tag.ToString().Split(Convert.ToChar(","))[1];
        }
        //单击点左键抬起
        private void Point_LeftMouseUp(object sender, MouseButtonEventArgs e)
        {
            Ellipse ell = (sender as Ellipse);//获取单击的椭圆
            //获取起点位置坐标
            txtFromX.Text = ell.Tag.ToString().Split(Convert.ToChar(","))[0];
            txtFromY.Text = ell.Tag.ToString().Split(Convert.ToChar(","))[1];
        }
        //绘制路线  主画布
        private void DrawRoads()
        {
            MainCanvas.Children.Clear();//清空主画布
            foreach (Road r in rf.AllRoads)//遍历路线
                DrawPath(r, Brushes.Black, 1);//绘制路线
        }
        //绘制单个路线
        private void DrawPath(Road r, Brush colour, int lineThickness)
        {
            Line rl = new Line();//Line线条
            rl.X1 = ConvertPoint(r.From.x);
            rl.Y1 = ConvertPoint(r.From.y);
            rl.X2 = ConvertPoint(r.To.x);
            rl.Y2 = ConvertPoint(r.To.y);
            rl.StrokeThickness = lineThickness;
            rl.Stroke = colour;
            //绘制线条
            MainCanvas.Children.Add(rl);
        }
        //根据网格位置计算画布上对应坐标  画布宽高 400x400
        private int ConvertPoint(int gridpos)
        {
            return gridpos * 40 + 20;
        }
        //查找最近路线
        private void button_Click(object sender, RoutedEventArgs e)
        {
            DrawRoads();//绘制路线
            //设置RouteFinder的起点和终点  int型
            rf.StartX = Convert.ToInt32(txtFromX.Text);
            rf.StartY = Convert.ToInt32(txtFromY.Text);
            rf.DestinationX = Convert.ToInt32(txtToX.Text);
            rf.DestinationY = Convert.ToInt32(txtToY.Text);
            //设置搜索方法
            FinderMethodOption method = (FinderMethodOption)cboMethod.SelectedItem;
            rf.Method = method.Method;
            //计时
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                rf.Go();//搜索
            }
            catch(Exception ex)
            {//捕获异常后停止
                sw.Stop();
                MessageBox.Show("Exception: " + ex.Message);
                return;


            }
            sw.Stop();


            //搜索时间
            TimeSpan ts = sw.Elapsed;
            TimeLabel.Text = string.Format("Runtime: {0}ms", ts.TotalMilliseconds.ToString("0.000"));


            if(rf.Journeys != null)//找到路线
            {
                if (rf.Journeys.Count == 0)
                {
                    MessageBox.Show("Unable to complete route");
                }
                else//找到多条路线
                {
                    Journey j = rf.Shortest();//最短路线
                    foreach (Road r in j.Roads)//遍历路线的线段
                        DrawPath(r, Brushes.Red, 2);//绘制红色路径
                }
            }
        }
        //添加示例地图
        private void MapButton1_Checked(object sender, RoutedEventArgs e)
        {
            AddRoads(1);
        }
        //添加随机地图
        private void MapButton2_Checked(object sender, RoutedEventArgs e)
        {
            AddRoads(2);
        }
    }

参考:

https://zhuanlan.zhihu.com/p/346666812

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值