wpf+c#路径迷宫鼠标绘制

说明:wpf路径迷宫鼠标绘制

效果图:

step1:C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MainWindow.xaml.cs

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        private const int CellSize = 30;
        private List<Point> _path = new();
        private List<Point> _userPath = new();
        private Cell[,] _maze = new Cell[0, 0];
        private bool _isDrawing;

        public MainWindow()
        {
            InitializeComponent();
        }

        #region Maze Drawing
        private void DrawMaze()
        {
            MazeCanvas.Children.Clear();
            if (_maze == null) return;

            // Draw walls
            for (int y = 0; y < _maze.GetLength(0); y++)
                for (int x = 0; x < _maze.GetLength(1); x++)
                    DrawWalls(x, y, _maze[y, x]);

            // Draw start/end markers
            DrawCircle(0, 0, Brushes.Green);
            DrawCircle(_maze.GetLength(1) - 1, _maze.GetLength(0) - 1, Brushes.Red);
        }

        private void DrawWalls(int x, int y, Cell cell)
        {
            var x1 = x * CellSize;
            var y1 = y * CellSize;
            
            if (cell.North) DrawLine(x1, y1, x1 + CellSize, y1);
            if (cell.South) DrawLine(x1, y1 + CellSize, x1 + CellSize, y1 + CellSize);
            if (cell.West) DrawLine(x1, y1, x1, y1 + CellSize);
            if (cell.East) DrawLine(x1 + CellSize, y1, x1 + CellSize, y1 + CellSize);
        }

        private void DrawLine(double x1, double y1, double x2, double y2)
        {
            MazeCanvas.Children.Add(new Line
            {
                X1 = x1,
                Y1 = y1,
                X2 = x2,
                Y2 = y2,
                Stroke = Brushes.Black,
                StrokeThickness = 1
            });
        }
        #endregion

        #region Path Handling
        private void DrawUserPath()
        {
            // Clear existing green lines
            var oldLines = MazeCanvas.Children.OfType<Line>()
                .Where(l => l.Stroke == Brushes.Green).ToList();
            oldLines.ForEach(l => MazeCanvas.Children.Remove(l));

            // Draw new path
            for (int i = 1; i < _userPath.Count; i++)
            {
                var prev = _userPath[i - 1];
                var curr = _userPath[i];
                
                MazeCanvas.Children.Add(new Line
                {
                    X1 = (prev.X + 0.5) * CellSize,
                    Y1 = (prev.Y + 0.5) * CellSize,
                    X2 = (curr.X + 0.5) * CellSize,
                    Y2 = (curr.Y + 0.5) * CellSize,
                    Stroke = Brushes.Green,
                    StrokeThickness = 3
                });
            }
        }

        private bool ValidatePath()
        {
            // Check if reached end
            var end = new Point(_maze.GetLength(1)-1, _maze.GetLength(0)-1);
            if (_userPath.LastOrDefault() != end) return false;

            // Validate each step
            for (int i = 1; i < _userPath.Count; i++)
            {
                var prev = _userPath[i - 1];
                var curr = _userPath[i];
                
                if (!IsValidMove((int)prev.X, (int)prev.Y, 
                               (int)curr.X, (int)curr.Y))
                    return false;
            }
            return true;
        }

        private bool IsValidMove(int fromX, int fromY, int toX, int toY)
        {
            var cell = _maze[fromY, fromX];
            var dx = toX - fromX;
            var dy = toY - fromY;

            return (dx, dy) switch
            {
                (1, 0) => !cell.East,   // Right
                (-1, 0) => !cell.West,  // Left
                (0, 1) => !cell.South,  // Down
                (0, -1) => !cell.North, // Up
                _ => false
            };
        }
        #endregion

        #region Mouse Handling
        private void MazeCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (_maze == null) return;
            
            var pos = e.GetPosition(MazeCanvas);
            int x = (int)(pos.X / CellSize);
            int y = (int)(pos.Y / CellSize);

            // Must start from origin
            if (x == 0 && y == 0)
            {
                _isDrawing = true;
                _userPath.Clear();
                _userPath.Add(new Point(x, y));
                DrawUserPath();
            }
        }

        private void MazeCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_isDrawing || _maze == null) return;

            var pos = e.GetPosition(MazeCanvas);
            int x = (int)(pos.X / CellSize);
            int y = (int)(pos.Y / CellSize);

            // Validate cell position
            if (x < 0 || x >= _maze.GetLength(1) || 
                y < 0 || y >= _maze.GetLength(0)) return;

            var last = _userPath.LastOrDefault();
            
            // Allow only adjacent moves
            if (Math.Abs(x - last.X) + Math.Abs(y - last.Y) != 1) return;
            
            // Prevent backtracking
            if (_userPath.Any(p => p.X == x && p.Y == y)) return;

            if (IsValidMove((int)last.X, (int)last.Y, x, y))
            {
                _userPath.Add(new Point(x, y));
                DrawUserPath();
            }
        }

        private void MazeCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!_isDrawing) return;
            _isDrawing = false;

            bool success = ValidatePath();
            string message = success ? 
                "Congratulations! Restart?" : "Wrong path! Try again?";
            
            if (MessageBox.Show(message, "Result", 
                MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                BtnGenerate_Click(null, null);
            }
            else
            {
                _userPath.Clear();
                DrawUserPath();
            }
        }
        #endregion

        #region UI Events
        private void BtnGenerate_Click(object sender, RoutedEventArgs e)
        {
            // Generate new maze
            _maze = new MazeGenerator().Generate(15, 15);
            
            // Reset state
            _path.Clear();
            _userPath.Clear();
            _isDrawing = false;
            
            // Clear drawings
            MazeCanvas.Children.Clear();
            DrawMaze();
        }

        private void BtnSolve_Click(object sender, RoutedEventArgs e)
        {
            if (_maze == null) return;
            
            // Show auto-solved path
            _path = new PathSolver().SolveBFS(_maze);
            DrawMaze();
            
            // Draw solution path
            foreach (var point in _path)
            {
                MazeCanvas.Children.Add(new Ellipse
                {
                    Width = 4,
                    Height = 4,
                    Fill = Brushes.Blue,
                    Margin = new Thickness(
                        (point.X + 0.5) * CellSize - 2,
                        (point.Y + 0.5) * CellSize - 2, 0, 0)
                });
            }
        }
        #endregion

        #region Helpers
        private void DrawCircle(int x, int y, Brush color)
        {
            MazeCanvas.Children.Add(new Ellipse
            {
                Width = CellSize / 2,
                Height = CellSize / 2,
                Fill = color,
                Margin = new Thickness(
                    x * CellSize + CellSize / 4,
                    y * CellSize + CellSize / 4, 0, 0)
            });
        }
        #endregion
    }
}

step2:C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MazeGenerator.cs

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApp1;

public struct Cell
{
    public bool North;
    public bool South;
    public bool East;
    public bool West;
    public bool Visited;
}

public class MazeGenerator
{
    private Cell[,] _maze = new Cell[0,0]; // 初始化
    private readonly Random _random = new();
    // 修改方向处理
    private readonly (int dx, int dy)[] _directions = 
    {
        (0, -1),  // North
        (0, 1),   // South
        (1, 0),   // East
        (-1, 0)   // West
    };

    public Cell[,] Generate(int width, int height)
    {
        _maze = new Cell[height, width];
        InitializeCells();
        GenerateWithBacktracking();
        return _maze;
    }

    private void InitializeCells()
    {
        for (int y = 0; y < _maze.GetLength(0); y++)
        for (int x = 0; x < _maze.GetLength(1); x++)
            _maze[y, x] = new Cell
            {
                North = true, South = true, 
                East = true, West = true,
                Visited = false
            };
    }

    private void GenerateWithBacktracking()
    {
        var stack = new Stack<(int x, int y)>();
        stack.Push((0, 0));
        _maze[0, 0].Visited = true;

        var directions = new[]
        {
            new Point(0, -1),  // North
            new Point(0, 1),   // South
            new Point(1, 0),   // East
            new Point(-1, 0)   // West
        };

        while (stack.Count > 0)
        {
            var (x, y) = stack.Pop();
            
            var validDirs = _directions
                .Select((d, i) => new { Direction = d, Index = i })
                .Where(d => 
                {
                    var (dx, dy) = d.Direction;
                    int nx = x + dx;
                    int ny = y + dy;
                    return IsValidCell(nx, ny) && !_maze[ny, nx].Visited;
                })
                .ToList();

            if (validDirs.Count > 0)
            {
                var selected = validDirs[_random.Next(validDirs.Count)];
                var (dx, dy) = selected.Direction;
                int nx = x + dx;
                int ny = y + dy;

                RemoveWalls(x, y, selected.Index);
                _maze[ny, nx].Visited = true;
                stack.Push((x, y));
                stack.Push((nx, ny));
            }
        }
    }

    private void RemoveWalls(int x, int y, int dir)
    {
        switch (dir)
        {
            case 0: // North
                _maze[y, x].North = false;
                _maze[y - 1, x].South = false;
                break;
            case 1: // South
                _maze[y, x].South = false;
                _maze[y + 1, x].North = false;
                break;
            case 2: // East
                _maze[y, x].East = false;
                _maze[y, x + 1].West = false;
                break;
            case 3: // West
                _maze[y, x].West = false;
                _maze[y, x - 1].East = false;
                break;
        }
    }

    private bool IsValidCell(int x, int y) => 
        x >= 0 && x < _maze.GetLength(1) && 
        y >= 0 && y < _maze.GetLength(0);
}

step3:C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\PathSolver.cs

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApp1;

public class PathSolver
{
     
    
    public List<Point> SolveBFS(Cell[,] maze)
    {
        int width = maze.GetLength(1);
        int height = maze.GetLength(0);
        var visited = new bool[height, width];
        var prev = new (int x, int y)[height, width];
        var queue = new Queue<(int x, int y)>();
        var directions = new[] { (0, -1), (0, 1), (1, 0), (-1, 0) };

        queue.Enqueue((0, 0));
        visited[0, 0] = true;

        while (queue.Count > 0)
        {
            var (x, y) = queue.Dequeue();
            if (x == width - 1 && y == height - 1)
                return ReconstructPath(prev);

            foreach (var (dx, dy) in directions)
            {
                int nx = x + dx;
                int ny = y + dy;

                if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
                if (visited[ny, nx]) continue;
                
                if (!CanMove(maze[y, x], GetDirectionIndex(dx, dy))) continue;

                visited[ny, nx] = true;
                prev[ny, nx] = (x, y);
                queue.Enqueue((nx, ny));
            }
        }
        return new List<Point>();
    }

    
    

    private int GetDirectionIndex(int dx, int dy) => (dx, dy) switch
    {
        (0, -1) => 0,  // North
        (0, 1) => 1,   // South
        (1, 0) => 2,   // East
        (-1, 0) => 3,  // West
        _ => -1
    };



    

    private List<Point> ReconstructPath((int x, int y)[,] prev)
    {
        var path = new List<Point>();
        (int x, int y) current = (prev.GetLength(1) - 1, prev.GetLength(0) - 1);
        
        while (current.x != 0 || current.y != 0)
        {
            path.Add(new Point(current.x, current.y));
            current = prev[current.y, current.x];
        }
        path.Add(new Point(0, 0));
        path.Reverse();
        return path;
    }



    private bool CanMove(Cell cell, int dir) => dir switch
    {
        0 => !cell.North,
        1 => !cell.South,
        2 => !cell.East,
        3 => !cell.West,
        _ => false
    };

    private List<Point> ReconstructPath(Point[,] prev)
    {
        var path = new List<Point>();
        var current = new Point(prev.GetLength(1) - 1, prev.GetLength(0) - 1);
        
        while (current.X != 0 || current.Y != 0)
        {
            path.Add(current);
            current = prev[(int)current.Y, (int)current.X];
        }
        path.Add(new Point(0, 0));
        path.Reverse();
        return path;
    }
}

step4:C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MainWindow.xaml

xml 复制代码
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Maze Generator" Height="600" Width="800">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="5">
            <Button x:Name="BtnGenerate" Content="Generate Maze" 
                    Click="BtnGenerate_Click" Margin="5" Padding="10 3"/>
            <Button x:Name="BtnSolve" Content="Solve Maze" 
                    Click="BtnSolve_Click" Margin="5" Padding="10 3"/>
        </StackPanel>
        <Canvas x:Name="MazeCanvas" Background="White" Margin="10" ClipToBounds="True"
                MouseLeftButtonDown="MazeCanvas_MouseLeftButtonDown"
                MouseMove="MazeCanvas_MouseMove"
                MouseLeftButtonUp="MazeCanvas_MouseLeftButtonUp"/>
    </DockPanel>
</Window>

step5:纯界面

typescript 复制代码
   C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MainWindow.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApp1;

public partial class MainWindow : Window
{
    private const int CellSize = 20;
    private List<Point> _path = new();
    private Cell[,] _maze = new Cell[0,0]; // 初始化为空数组
    
    public MainWindow()
    {
        InitializeComponent();
    }

    private void DrawMaze()
    {
        MazeCanvas.Children.Clear();
        if (_maze == null) return;

        for (int y = 0; y < _maze.GetLength(0); y++)
        {
            for (int x = 0; x < _maze.GetLength(1); x++)
            {
                var cell = _maze[y, x];
                DrawWalls(x, y, cell);
            }
        }
        DrawStartEnd();
    }

    private void DrawWalls(int x, int y, Cell cell)
    {
        var x1 = x * CellSize;
        var y1 = y * CellSize;
        var x2 = (x + 1) * CellSize;
        var y2 = (y + 1) * CellSize;

        if (cell.North) DrawLine(x1, y1, x2, y1);
        if (cell.South) DrawLine(x1, y2, x2, y2);
        if (cell.West) DrawLine(x1, y1, x1, y2);
        if (cell.East) DrawLine(x2, y1, x2, y2);
    }

    private void DrawLine(double x1, double y1, double x2, double y2)
    {
        var line = new Line
        {
            X1 = x1,
            Y1 = y1,
            X2 = x2,
            Y2 = y2,
            Stroke = Brushes.Black,
            StrokeThickness = 1
        };
        MazeCanvas.Children.Add(line);
    }

    private void DrawStartEnd()
    {
        DrawCircle(0, 0, Brushes.Green);
        var lastX = _maze.GetLength(1) - 1;
        var lastY = _maze.GetLength(0) - 1;
        DrawCircle(lastX, lastY, Brushes.Red);
    }

    private void DrawCircle(int x, int y, Brush color)
    {
        var ellipse = new Ellipse
        {
            Width = CellSize / 2,
            Height = CellSize / 2,
            Fill = color,
            Margin = new Thickness(x * CellSize + CellSize / 4, 
                                 y * CellSize + CellSize / 4, 0, 0)
        };
        MazeCanvas.Children.Add(ellipse);
    }

    private void DrawPath()
    {
        var pathColor = Brushes.Blue;
        foreach (var point in _path)
        {
            var x = (point.X + 0.5) * CellSize;
            var y = (point.Y + 0.5) * CellSize;
            var dot = new Ellipse
            {
                Width = 4,
                Height = 4,
                Fill = pathColor,
                Margin = new Thickness(x - 2, y - 2, 0, 0)
            };
            MazeCanvas.Children.Add(dot);
        }
    }

    private void BtnGenerate_Click(object sender, RoutedEventArgs e)
    {
        var generator = new MazeGenerator();
        _maze = generator.Generate(15, 15);
        _path.Clear();
        DrawMaze();
    }

    private void BtnSolve_Click(object sender, RoutedEventArgs e)
    {
        if (_maze == null) return;
        var solver = new PathSolver();
        _path = solver.SolveBFS(_maze);
        DrawMaze();
        DrawPath();
    }
}

C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MazeGenerator.cs
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApp1;

public struct Cell
{
    public bool North;
    public bool South;
    public bool East;
    public bool West;
    public bool Visited;
}

public class MazeGenerator
{
    private Cell[,] _maze = new Cell[0,0]; // 初始化
    private readonly Random _random = new();
    // 修改方向处理
    private readonly (int dx, int dy)[] _directions = 
    {
        (0, -1),  // North
        (0, 1),   // South
        (1, 0),   // East
        (-1, 0)   // West
    };

    public Cell[,] Generate(int width, int height)
    {
        _maze = new Cell[height, width];
        InitializeCells();
        GenerateWithBacktracking();
        return _maze;
    }

    private void InitializeCells()
    {
        for (int y = 0; y < _maze.GetLength(0); y++)
        for (int x = 0; x < _maze.GetLength(1); x++)
            _maze[y, x] = new Cell
            {
                North = true, South = true, 
                East = true, West = true,
                Visited = false
            };
    }

    private void GenerateWithBacktracking()
    {
        var stack = new Stack<(int x, int y)>();
        stack.Push((0, 0));
        _maze[0, 0].Visited = true;

        var directions = new[]
        {
            new Point(0, -1),  // North
            new Point(0, 1),   // South
            new Point(1, 0),   // East
            new Point(-1, 0)   // West
        };

        while (stack.Count > 0)
        {
            var (x, y) = stack.Pop();
            
            var validDirs = _directions
                .Select((d, i) => new { Direction = d, Index = i })
                .Where(d => 
                {
                    var (dx, dy) = d.Direction;
                    int nx = x + dx;
                    int ny = y + dy;
                    return IsValidCell(nx, ny) && !_maze[ny, nx].Visited;
                })
                .ToList();

            if (validDirs.Count > 0)
            {
                var selected = validDirs[_random.Next(validDirs.Count)];
                var (dx, dy) = selected.Direction;
                int nx = x + dx;
                int ny = y + dy;

                RemoveWalls(x, y, selected.Index);
                _maze[ny, nx].Visited = true;
                stack.Push((x, y));
                stack.Push((nx, ny));
            }
        }
    }

    private void RemoveWalls(int x, int y, int dir)
    {
        switch (dir)
        {
            case 0: // North
                _maze[y, x].North = false;
                _maze[y - 1, x].South = false;
                break;
            case 1: // South
                _maze[y, x].South = false;
                _maze[y + 1, x].North = false;
                break;
            case 2: // East
                _maze[y, x].East = false;
                _maze[y, x + 1].West = false;
                break;
            case 3: // West
                _maze[y, x].West = false;
                _maze[y, x - 1].East = false;
                break;
        }
    }

    private bool IsValidCell(int x, int y) => 
        x >= 0 && x < _maze.GetLength(1) && 
        y >= 0 && y < _maze.GetLength(0);
}

C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\PathSolver.cs
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApp1;

public class PathSolver
{
     
    
    public List<Point> SolveBFS(Cell[,] maze)
    {
        int width = maze.GetLength(1);
        int height = maze.GetLength(0);
        var visited = new bool[height, width];
        var prev = new (int x, int y)[height, width];
        var queue = new Queue<(int x, int y)>();
        var directions = new[] { (0, -1), (0, 1), (1, 0), (-1, 0) };

        queue.Enqueue((0, 0));
        visited[0, 0] = true;

        while (queue.Count > 0)
        {
            var (x, y) = queue.Dequeue();
            if (x == width - 1 && y == height - 1)
                return ReconstructPath(prev);

            foreach (var (dx, dy) in directions)
            {
                int nx = x + dx;
                int ny = y + dy;

                if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
                if (visited[ny, nx]) continue;
                
                if (!CanMove(maze[y, x], GetDirectionIndex(dx, dy))) continue;

                visited[ny, nx] = true;
                prev[ny, nx] = (x, y);
                queue.Enqueue((nx, ny));
            }
        }
        return new List<Point>();
    }

    
    

    private int GetDirectionIndex(int dx, int dy) => (dx, dy) switch
    {
        (0, -1) => 0,  // North
        (0, 1) => 1,   // South
        (1, 0) => 2,   // East
        (-1, 0) => 3,  // West
        _ => -1
    };



    

    private List<Point> ReconstructPath((int x, int y)[,] prev)
    {
        var path = new List<Point>();
        (int x, int y) current = (prev.GetLength(1) - 1, prev.GetLength(0) - 1);
        
        while (current.x != 0 || current.y != 0)
        {
            path.Add(new Point(current.x, current.y));
            current = prev[current.y, current.x];
        }
        path.Add(new Point(0, 0));
        path.Reverse();
        return path;
    }



    private bool CanMove(Cell cell, int dir) => dir switch
    {
        0 => !cell.North,
        1 => !cell.South,
        2 => !cell.East,
        3 => !cell.West,
        _ => false
    };

    private List<Point> ReconstructPath(Point[,] prev)
    {
        var path = new List<Point>();
        var current = new Point(prev.GetLength(1) - 1, prev.GetLength(0) - 1);
        
        while (current.X != 0 || current.Y != 0)
        {
            path.Add(current);
            current = prev[(int)current.Y, (int)current.X];
        }
        path.Add(new Point(0, 0));
        path.Reverse();
        return path;
    }
}

C:\Users\wangrusheng\RiderProjects\WpfApp1\WpfApp1\MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Maze Generator" Height="600" Width="800">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="5">
            <Button x:Name="BtnGenerate" Content="Generate Maze" 
                    Click="BtnGenerate_Click" Margin="5" Padding="10 3"/>
            <Button x:Name="BtnSolve" Content="Solve Maze" 
                    Click="BtnSolve_Click" Margin="5" Padding="10 3"/>
        </StackPanel>
        <Canvas x:Name="MazeCanvas" Background="White" 
                Margin="10" ClipToBounds="True"/>
    </DockPanel>
</Window>

step6:纯算法

cpp 复制代码
C:\Users\wangrusheng\CLionProjects\untitled22\CMakeLists.txt

cmake_minimum_required(VERSION 3.30)
project(untitled22)

set(CMAKE_CXX_STANDARD 20)

add_executable(untitled22 main.cpp)


C:\Users\wangrusheng\CLionProjects\untitled22\main.cpp

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <ctime>

using namespace std;

struct Cell {
    bool north;
    bool south;
    bool east;
    bool west;
    bool visited;
};

vector<vector<Cell>> maze;

// 生成迷宫
void generateMaze(int width, int height) {
    maze.resize(height, vector<Cell>(width));
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            maze[y][x] = {true, true, true, true, false};
        }
    }

    srand(time(0));

    stack<pair<int, int>> stk;
    stk.push({0, 0});
    maze[0][0].visited = true;

    vector<pair<int, int>> dirs = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

    while (!stk.empty()) {
        int x = stk.top().first;
        int y = stk.top().second;

        vector<int> possibleDirs;
        for (int i = 0; i < 4; ++i) {
            int nx = x + dirs[i].first;
            int ny = y + dirs[i].second;
            if (nx >= 0 && nx < width && ny >= 0 && ny < height && !maze[ny][nx].visited) {
                possibleDirs.push_back(i);
            }
        }

        if (!possibleDirs.empty()) {
            int dir = possibleDirs[rand() % possibleDirs.size()];
            int nx = x + dirs[dir].first;
            int ny = y + dirs[dir].second;

            switch (dir) {
                case 0: // North
                    maze[y][x].north = false;
                    maze[ny][nx].south = false;
                    break;
                case 1: // South
                    maze[y][x].south = false;
                    maze[ny][nx].north = false;
                    break;
                case 2: // East
                    maze[y][x].east = false;
                    maze[ny][nx].west = false;
                    break;
                case 3: // West
                    maze[y][x].west = false;
                    maze[ny][nx].east = false;
                    break;
            }

            maze[ny][nx].visited = true;
            stk.push({nx, ny});
        } else {
            stk.pop();
        }
    }
}

// 创建字符网格表示迷宫
vector<vector<char>> createGrid(int width, int height) {
    int gridWidth = 2 * width + 1;
    int gridHeight = 2 * height + 1;
    vector<vector<char>> grid(gridHeight, vector<char>(gridWidth, '#'));

    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            int cx = 2 * x + 1;
            int cy = 2 * y + 1;
            grid[cy][cx] = ' ';

            if (!maze[y][x].north) grid[cy - 1][cx] = ' ';
            if (!maze[y][x].south) grid[cy + 1][cx] = ' ';
            if (!maze[y][x].east) grid[cy][cx + 1] = ' ';
            if (!maze[y][x].west) grid[cy][cx - 1] = ' ';
        }
    }

    grid[1][1] = 'S';
    grid[gridHeight - 2][gridWidth - 2] = 'E';
    return grid;
}

// 定义点结构体用于路径追踪
struct Point {
    int x, y;
};

// BFS求解最短路径
bool solveMazeBFS(int startX, int startY, int endX, int endY, vector<Point>& path) {
    int width = maze[0].size();
    int height = maze.size();

    vector<vector<bool>> visited(height, vector<bool>(width, false));
    vector<vector<Point>> prev(height, vector<Point>(width, {-1, -1}));
    queue<Point> q;

    q.push({startX, startY});
    visited[startY][startX] = true;

    vector<pair<int, int>> dirs = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

    while (!q.empty()) {
        Point curr = q.front();
        q.pop();

        if (curr.x == endX && curr.y == endY) {
            // 回溯路径
            Point p = curr;
            while (p.x != -1 || p.y != -1) {
                path.push_back(p);
                p = prev[p.y][p.x];
            }
            reverse(path.begin(), path.end());
            return true;
        }

        for (int i = 0; i < 4; ++i) {
            int nx = curr.x + dirs[i].first;
            int ny = curr.y + dirs[i].second;

            if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;

            bool canMove = false;
            switch (i) {
                case 0: canMove = !maze[curr.y][curr.x].north; break;
                case 1: canMove = !maze[curr.y][curr.x].south; break;
                case 2: canMove = !maze[curr.y][curr.x].east; break;
                case 3: canMove = !maze[curr.y][curr.x].west; break;
            }

            if (canMove && !visited[ny][nx]) {
                visited[ny][nx] = true;
                prev[ny][nx] = curr;
                q.push({nx, ny});
            }
        }
    }
    return false;
}

// 打印网格
void printGrid(const vector<vector<char>>& grid) {
    for (const auto& row : grid) {
        for (char c : row) {
            cout << c;
        }
        cout << endl;
    }
}

int main() {
    int width = 5, height = 5;
    generateMaze(width, height);
    auto grid = createGrid(width, height);

    cout << "Generated Maze:" << endl;
    printGrid(grid);

    vector<Point> path;
    if (solveMazeBFS(0, 0, width-1, height-1, path)) {
        cout << "\nPath Found:" << endl;
        // 标记路径
        for (const auto& p : path) {
            int cx = 2 * p.x + 1;
            int cy = 2 * p.y + 1;
            if (grid[cy][cx] != 'S' && grid[cy][cx] != 'E') {
                grid[cy][cx] = '.';
            }
        }
        printGrid(grid);
    } else {
        cout << "\nNo Path Found!" << endl;
    }

    return 0;
}

end

相关推荐
陈皮话梅糖@2 小时前
使用 Provider 和 GetX 实现 Flutter 局部刷新的几个示例
开发语言·javascript·flutter
hvinsion3 小时前
基于PyQt5的自动化任务管理软件:高效、智能的任务调度与执行管理
开发语言·python·自动化·自动化任务管理
Aphelios3803 小时前
Java全栈面试宝典:线程机制与Spring IOC容器深度解析
java·开发语言·jvm·学习·rbac
qq_529835353 小时前
装饰器模式:如何用Java打扮一个对象?
java·开发语言·装饰器模式
日暮南城故里4 小时前
Java学习------源码解析之StringBuilder
java·开发语言·学习·源码
Vitalia4 小时前
从零开始学Rust:枚举(enum)与模式匹配核心机制
开发语言·后端·rust
双叶8364 小时前
(C语言)虚数运算(结构体教程)(指针解法)(C语言教程)
c语言·开发语言·数据结构·c++·算法·microsoft
Marzlam5 小时前
一文了解WPF技术简介
wpf
一个public的class6 小时前
什么是 Java 泛型
java·开发语言·后端
士别三日&&当刮目相看6 小时前
JAVA学习*Object类
java·开发语言·学习