C# 实现迷宫游戏

news2024/11/16 15:34:03

智能提示:

 /// <summary>
    /// 迷宫
    /// </summary>
    internal class Maze : IDisposable
    {
        private MazeCell[,] cells;
        private readonly Stack<MazeCell> stack = new Stack<MazeCell>();
        private readonly Random rand = new Random();
        private int _width, _height;
        private Bitmap mazeBitmap; // 用于保存迷宫的位图
        private float cellWidth;
        private float cellHeight;
        private Point playerPosition;
        private float playerRadius;
        private bool _isMove = true;
        private int _canvasWidth;
        private int _canvasHeight;
        private MazeType _mazeType = MazeType.Default;
        public Maze()
        {

        }
        public Bitmap MazeBitmap => mazeBitmap;
        public bool IsMove => _isMove;
        public MazeType MazeType => _mazeType;
        public int CanvasWidth
        {
            get => _canvasWidth;
            set
            {
                _canvasWidth = value;
            }
        }
        public int CanvasHeight
        {
            get => _canvasHeight;
            set { _canvasHeight = value; }
        }
        private void GenerateMaze(MazeType mazeType)
        {
            switch(mazeType)
            {
                case MazeType.Default:
                    GenerateMaze_RecursiveBacktracking();
                    break;
                case MazeType.DFS:
                    GenerateMaze_DFS();
                    break;
                case MazeType.Prim:
                    GenerateMaze_Prim();
                    break;
                case MazeType.RecursiveDivision:
                    GenerateMaze_RecursiveDivision();
                    break;
                case MazeType.RecursiveBacktracking:
                    GenerateMaze_RecursiveBacktracking();
                    break;
            }
        }

        /// <summary>
        /// 获取方向
        /// </summary>
        /// <returns></returns>
        private IEnumerable<Tuple<int, int>> GetDirections()
        {
            yield return Tuple.Create(-1, 0);
            yield return Tuple.Create(1, 0);
            yield return Tuple.Create(0, -1);
            yield return Tuple.Create(0, 1);
        }

        #region 深度优先搜索算法
        private void GenerateMaze_DFS()
        {
            // 选择迷宫的左上角的点作为起始点
            int startX = 0;
            int startY = 0;

            // 使用DFS生成迷宫
            GenerateMaze(startX, startY);

            // 将起始点的左面的墙壁设为入口
            cells[startX, startY].LeftWall = false;

            // 找到迷宫的一个最远的边缘点,将它的边缘的墙壁设为出口
            int maxDist = 0;
            int endX = 0, endY = 0;
            bool isBottomEdge = false;
            for (int x = 0; x < _width; x++)
            {
                for (int y = 0; y < _height; y++)
                {
                    int dist = Math.Abs(x - startX) + Math.Abs(y - startY);
                    if (dist > maxDist && (x == 0 || y == 0 || x == _width - 1 || y == _height - 1))
                    {
                        maxDist = dist;
                        endX = x;
                        endY = y;
                        isBottomEdge = (y == _height - 1);
                    }
                }
            }
            if (isBottomEdge)
                cells[endX, endY].BottomWall = false;
            else
                cells[endX, endY].RightWall = false;
        }
        private void GenerateMaze(int x, int y)
        {
            // 标记当前点已被访问
            cells[x, y].Visited = true;

            var tempData = GetDirections().OrderBy(_ => rand.Next());
            // 随机访问四个方向
            foreach (var dir in tempData)
            {
                int newX = x + dir.Item1, newY = y + dir.Item2;
                if (newX >= 0 && newX < _width && newY >= 0 && newY < _height && !cells[newX, newY].Visited)
                {
                    // 移除两个单元格之间的墙壁
                    if (dir.Item1 == -1)
                    {
                        cells[x, y].LeftWall = false;
                        cells[newX, newY].RightWall = false;
                    }
                    else if (dir.Item1 == 1)
                    {
                        cells[x, y].RightWall = false;
                        cells[newX, newY].LeftWall = false;
                    }
                    else if (dir.Item2 == -1)
                    {
                        cells[x, y].TopWall = false;
                        cells[newX, newY].BottomWall = false;
                    }
                    else if (dir.Item2 == 1)
                    {
                        cells[x, y].BottomWall = false;
                        cells[newX, newY].TopWall = false;
                    }

                    // 递归访问下一个点
                    GenerateMaze(newX, newY);
                }
            }
        }

        #endregion

        #region 普里姆算法
        private void GenerateMaze_Prim()
        {
            // 选择迷宫的一个随机点作为起始点
            int startX = rand.Next(_width);
            int startY = rand.Next(_height);

            cells[startX, startY].Visited = true;

            // 初始化边缘列表,包含起始点的所有邻居
            Queue<MazeCell> frontier = new Queue<MazeCell>();
            AddUnvisitedNeighborsToFrontier(cells[startX, startY], frontier);

            // 使用Prim算法生成迷宫
            while (frontier.Count > 0)
            {
                // 从边缘列表中选择一个单元格,更倾向于选择最早添加的单元格
                var cell = frontier.Dequeue();

                // 找到与这个单元格相邻的已访问的单元格
                var neighbors = GetVisitedNeighbors(cell);

                if (neighbors.Count > 0)
                {
                    // 随机选择一个已访问的邻居
                    var neighbor = neighbors[rand.Next(neighbors.Count)];

                    // 移除两个单元格之间的墙壁
                    if (cell.X > neighbor.Item2.X) // 如果邻居在当前单元格的左侧
                    {
                        cell.LeftWall = false;
                        neighbor.Item2.RightWall = false;
                    }
                    else if (cell.X < neighbor.Item2.X) // 如果邻居在当前单元格的右侧
                    {
                        cell.RightWall = false;
                        neighbor.Item2.LeftWall = false;
                    }
                    else if (cell.Y > neighbor.Item2.Y) // 如果邻居在当前单元格的上方
                    {
                        cell.TopWall = false;
                        neighbor.Item2.BottomWall = false;
                    }
                    else if (cell.Y < neighbor.Item2.Y) // 如果邻居在当前单元格的下方
                    {
                        cell.BottomWall = false;
                        neighbor.Item2.TopWall = false;
                    }

                    // 将这个单元格标记为已访问,并将它的所有未访问的邻居添加到边缘列表中
                    cell.Visited = true;
                    AddUnvisitedNeighborsToFrontier(cell, frontier);
                }
            }
        }

        private void AddUnvisitedNeighborsToFrontier(MazeCell cell, Queue<MazeCell> frontier)
        {
            foreach (var dir in GetDirections())
            {
                int newX = cell.X + dir.Item1, newY = cell.Y + dir.Item2;
                if (newX >= 0 && newX < _width && newY >= 0 && newY < _height && !cells[newX, newY].Visited && !frontier.Contains(cells[newX, newY]))
                    frontier.Enqueue(cells[newX, newY]);
            }
        }


        private List<Tuple<int, MazeCell>> GetVisitedNeighbors(MazeCell cell)
        {
            var visitedNeighbors = new List<Tuple<int, MazeCell>>();

            foreach (var dir in GetDirections())
            {
                int newX = cell.X + dir.Item1, newY = cell.Y + dir.Item2;
                if (newX >= 0 && newX < _width && newY >= 0 && newY < _height && cells[newX, newY].Visited)
                    visitedNeighbors.Add(Tuple.Create(dir.Item1, cells[newX, newY]));
            }

            return visitedNeighbors;
        }

        #endregion

        #region 递归除法算法
        private void GenerateMaze_RecursiveDivision()
        {
            // 初始化迷宫,所有的墙都被移除
            for (int x = 0; x < _width; ++x)
            {
                for (int y = 0; y < _height; ++y)
                {
                    cells[x, y].TopWall = y == 0;
                    cells[x, y].BottomWall = y == _height - 1;
                    cells[x, y].LeftWall = x == 0;
                    cells[x, y].RightWall = x == _width - 1;
                }
            }

            // 递归分割迷宫
            Divide(0, 0, _width - 1, _height - 1);
        }
        private void Divide(int x, int y, int width, int height)
        {
            if (width < 3 || height < 3)
                return;

            bool horizontal = rand.Next(2) == 0;

            if (horizontal)
            {
                // 横向分割
                int splitY = y + 2 + rand.Next(height - 3);
                int holeX = x + rand.Next(width);

                for (int i = x; i < x + width; ++i)
                {
                    if (i != holeX)
                    {
                        cells[i, splitY].BottomWall = true;
                        if (splitY + 1 < _height)
                        {
                            cells[i, splitY + 1].TopWall = true;
                        }
                    }
                }

                Divide(x, y, width, splitY - y);
                Divide(x, splitY + 1, width, y + height - splitY - 1);
            }
            else
            {
                // 纵向分割
                int splitX = x + 2 + rand.Next(width - 3);
                int holeY = y + rand.Next(height);

                for (int i = y; i < y + height; ++i)
                {
                    if (i != holeY)
                    {
                        cells[splitX, i].RightWall = true;
                        if (splitX + 1 < _width)
                        {
                            cells[splitX + 1, i].LeftWall = true;
                        }
                    }
                }

                Divide(x, y, splitX - x, height);
                Divide(splitX + 1, y, x + width - splitX - 1, height);
            }
        }

        #endregion

        #region 时间回溯算法
        private void GenerateMaze_RecursiveBacktracking()
        {
            // 初始化迷宫,所有的墙都存在
            for (int x = 0; x < _width; ++x)
            {
                for (int y = 0; y < _height; ++y)
                {
                    cells[x, y].TopWall = true;
                    cells[x, y].BottomWall = true;
                    cells[x, y].LeftWall = true;
                    cells[x, y].RightWall = true;
                }
            }

            // 递归生成迷宫
            VisitCell(rand.Next(_width), rand.Next(_height));
        }

        private void VisitCell(int x, int y)
        {
            // 标记当前单元格为已访问
            cells[x, y].Visited = true;

            // 对邻居单元格的顺序进行随机排序
            foreach (var dir in GetDirections().OrderBy(d => rand.Next()))
            {
                int nx = x + dir.Item1;
                int ny = y + dir.Item2;

                // 如果邻居单元格在迷宫内并且未被访问过,则移除墙并递归访问邻居单元格
                if (nx >= 0 && ny >= 0 && nx < _width && ny < _height && !cells[nx, ny].Visited)
                {
                    RemoveWall(x, y, dir);
                    RemoveWall(nx, ny, Tuple.Create(-dir.Item1, -dir.Item2));
                    VisitCell(nx, ny);
                }
            }
        }

        private void RemoveWall(int x, int y, Tuple<int, int> direction)
        {
            if (direction.Equals(Tuple.Create(-1, 0))) // Left
            {
                cells[x, y].LeftWall = false;
            }
            else if (direction.Equals(Tuple.Create(1, 0))) // Right
            {
                cells[x, y].RightWall = false;
            }
            else if (direction.Equals(Tuple.Create(0, -1))) // Up
            {
                cells[x, y].TopWall = false;
            }
            else if (direction.Equals(Tuple.Create(0, 1))) // Down
            {
                cells[x, y].BottomWall = false;
            }
        }

        #endregion


        public void CreateMaze(int width, int height, int canvasWidth, int canvasHeight, MazeType mazeType= MazeType.Default,bool createOrUpdate=true)
        {
            mazeBitmap?.Dispose();
            _isMove = true;
            if (createOrUpdate)
            {
                playerPosition = new Point(0, 0); // 初始位置在迷宫的左上角
                stack.Clear();
                _width = width;
                _height = height;
                cells = new MazeCell[width, height];
                mazeBitmap = new Bitmap(width, height);
                _mazeType = mazeType;

                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        cells[x, y] = new MazeCell(x, y);
                    }
                }
            }

            GenerateMaze(mazeType);

            // 生成迷宫后,将其绘制到位图上
            mazeBitmap = new Bitmap(canvasWidth, canvasHeight);
            using (var g = Graphics.FromImage(mazeBitmap))
            {
                DrawMaze(g, canvasWidth, canvasHeight);
            }
        }
     
        private void DrawMaze(Graphics g, int canvasWidth, int canvasHeight)
        {
            int tempW = canvasWidth - 1;
            _canvasWidth = tempW;
            _canvasHeight = canvasHeight - 1;
            cellWidth = (float)_canvasWidth / _width;
            cellHeight = (float)_canvasHeight / _height;
            playerRadius = Math.Min(cellWidth, cellHeight) / 4;

            float lineWidth = 1f; // 线条的宽度
            float halfLineWidth = lineWidth / 2f; // 线条宽度的一半

            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;
            //g.SmoothingMode = SmoothingMode.AntiAlias;

            // 先绘制所有的垂直线
            for (int x = 0; x <= _width; x++)
            {
                float left = x * cellWidth;

                for (int y = 0; y < _height; y++)
                {
                    var cell = cells[Math.Min(x, _width - 1), y];

                    float top = y * cellHeight;
                    float bottom = (y + 1) * cellHeight;

                    if ((cell.LeftWall || x == _width) && !(x == _width && y == _height - 1))
                        g.DrawLine(Pens.Black, left, top - halfLineWidth, left, bottom + halfLineWidth);
                }
            }

            // 再绘制所有的水平线
            for (int y = 0; y <= _height; y++)
            {
                float top = y * cellHeight;

                for (int x = 0; x < _width; x++)
                {
                    var cell = cells[x, Math.Min(y, _height - 1)];

                    float left = x * cellWidth;
                    float right = (x + 1) * cellWidth;

                    if ((cell.TopWall || y == _height) && !(x == _width - 1 && y == _height))
                        g.DrawLine(Pens.Black, left - halfLineWidth, top, right + halfLineWidth, top);
                }
            }


        }

        public void Draw(Graphics g, int canvasWidth, int canvasHeight)
        {
            if (cells == null)
                return;

            int tempW = canvasWidth - 1;
            if (tempW != _canvasWidth)
            {
                CreateMaze(_width, _height, canvasWidth, canvasHeight, MazeType,false);
            }

            // 首先,绘制保存的迷宫位图
            g.DrawImage(mazeBitmap, 0, 0, canvasWidth, canvasHeight);


            // 在玩家位置处绘制一个小黑圆
            float playerX = (playerPosition.X + 0.5f) * cellWidth; // 玩家的X坐标
            float playerY = (playerPosition.Y + 0.5f) * cellHeight; // 玩家的Y坐标
            g.FillEllipse(Brushes.Black, playerX - playerRadius, playerY - playerRadius, 2 * playerRadius, 2 * playerRadius);

            // 在出口处写上"出口"
            //Font font = new Font("Arial", 16); // 设置字体和大小
            //float exitX = (_width - 2f) * cellWidth; // 出口的X坐标
            //float exitY = (_height - 1f) * cellHeight; // 出口的Y坐标
            //g.DrawString("出口", font, Brushes.Black, exitX, exitY);
        }


        public MoveResult Move(KeyEventArgs e)
        {
            if (cells == null || !_isMove)
                return new MoveResult();

            Point newPosition = playerPosition;

            switch (e.KeyCode)
            {
                case Keys.Up:
                    newPosition.Y--;
                    break;
                case Keys.Down:
                    newPosition.Y++;
                    break;
                case Keys.Left:
                    newPosition.X--;
                    break;
                case Keys.Right:
                    newPosition.X++;
                    break;
            }

            return Move(newPosition);
        }
        public MoveResult Move(Point newPosition)
        {
            // 计算小黑点移动前后的矩形区域
            Rectangle oldRect = GetPlayerRect(playerPosition);
            bool status = false;

            if (newPosition.X < 0 || newPosition.Y < 0)
            {
                goto Result;
            }

            int directionX = newPosition.X - playerPosition.X;
            if (directionX != 0)
            {
                if (directionX > 0)
                {
                    if (newPosition.X < _width && !cells[playerPosition.X, playerPosition.Y].RightWall && !cells[newPosition.X, newPosition.Y].LeftWall)
                    {
                        playerPosition = newPosition;
                        status = true;
                        goto Result;
                    }
                }
                else
                {
                    if (newPosition.X >= 0 && !cells[playerPosition.X, playerPosition.Y].LeftWall && !cells[newPosition.X, newPosition.Y].RightWall)
                    {
                        playerPosition = newPosition;
                        status = true;
                        goto Result;
                    }
                }
            }
            int directionY = newPosition.Y - playerPosition.Y;
            if (directionY != 0)
            {
                if (directionY > 0)
                {
                    if (newPosition.Y < _height && !cells[playerPosition.X, playerPosition.Y].BottomWall && !cells[newPosition.X, newPosition.Y].TopWall)
                    {
                        playerPosition = newPosition;
                        status = true;
                        goto Result;
                    }
                }
                else
                {
                    if (newPosition.Y >= 0 && !cells[playerPosition.X, playerPosition.Y].TopWall && !cells[newPosition.X, newPosition.Y].BottomWall)
                    {
                        playerPosition = newPosition;
                        status = true;
                        goto Result;
                    }
                }
            }

        // goto Result;
        Result:

            Rectangle newRect = GetPlayerRect(newPosition);
            bool isWin = playerPosition.X == _width - 1 && playerPosition.Y == _height - 1;
            _isMove = !isWin;
            return new MoveResult
            {
                IsInvalidate = status,
                IsWin = isWin,
                OldRect = oldRect,
                NewRect = newRect
            };
        }
        private Rectangle GetPlayerRect(Point position)
        {
            int x = (int)Math.Round(position.X * cellWidth, 0);
            int y = (int)Math.Round(position.Y * cellHeight, 0);
            return new Rectangle(x, y, (int)Math.Round(cellWidth, 0), (int)Math.Round(cellHeight, 0));
        }
        public Bitmap DrawPath(Bitmap bitmap)
        {
            if (mazeBitmap == null)
                return null;

            var path = FindPath();
            if (bitmap == null)
                bitmap = new Bitmap(_canvasWidth, _canvasHeight);

            // 创建一个Graphics对象
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                // 绘制路径
                if (path != null)
                {
                    var pathPen = new Pen(Color.Red, 2);  // 使用红色画笔来绘制路径
                    for (int i = 0; i < path.Count - 1; i++)
                    {
                        float x1 = (path[i].X + 0.5f) * cellWidth;
                        float y1 = (path[i].Y + 0.5f) * cellHeight;
                        float x2 = (path[i + 1].X + 0.5f) * cellWidth;
                        float y2 = (path[i + 1].Y + 0.5f) * cellHeight;
                        g.DrawLine(pathPen, x1, y1, x2, y2);
                    }
                }
            }

            return bitmap;
        }
        public List<MazeCell> FindPath()
        {
            var start = cells[0, 0];
            var end = cells[_width - 1, _height - 1];

            var queue = new Queue<MazeCell>();
            var prev = new Dictionary<MazeCell, MazeCell>();

            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                var cell = queue.Dequeue();

                if (cell == end)
                {
                    var path = new List<MazeCell>();
                    while (cell != start)
                    {
                        path.Add(cell);
                        cell = prev[cell];
                    }
                    path.Add(start);
                    path.Reverse();
                    return path;
                }

                foreach (var neighbor in GetNeighbors(cell))
                {
                    if (prev.ContainsKey(neighbor))
                        continue;

                    prev[neighbor] = cell;
                    queue.Enqueue(neighbor);
                }
            }

            return null;  // 没有找到路径
        }

        private IEnumerable<MazeCell> GetNeighbors(MazeCell cell)
        {
            var neighbors = new List<MazeCell>();

            if (cell.X > 0 && !cell.LeftWall)
                neighbors.Add(cells[cell.X - 1, cell.Y]);
            if (cell.X < _width - 1 && !cell.RightWall)
                neighbors.Add(cells[cell.X + 1, cell.Y]);
            if (cell.Y > 0 && !cell.TopWall)
                neighbors.Add(cells[cell.X, cell.Y - 1]);
            if (cell.Y < _height - 1 && !cell.BottomWall)
                neighbors.Add(cells[cell.X, cell.Y + 1]);

            return neighbors;
        }
        public void Dispose()
        {
            mazeBitmap?.Dispose();
        }

        ~Maze()
        {
            Dispose();
        }
    }
    public class MazeCell
    {
        public int X { get; set; }
        public int Y { get; set; }
        public bool Visited { get; set; }
        public bool TopWall = true, BottomWall = true, LeftWall = true, RightWall = true;

        public MazeCell(int x, int y)
        {
            X = x;
            Y = y;
            Visited = false;
            TopWall = BottomWall = LeftWall = RightWall = true;
        }
    }
    public class MoveResult
    {
        public bool IsInvalidate { get; set; }
        public Rectangle OldRect { get; set; }
        public Rectangle NewRect { get; set; }
        public bool IsWin { get; set; }
    }
    public enum MazeType
    {
        /// <summary>
        /// 默认RecursiveBacktracking
        /// </summary>
        Default,
        /// <summary>
        /// 深度优先搜索算法
        /// </summary>
        DFS,
        /// <summary>
        /// 普里姆算法
        /// </summary>
        Prim,
        /// <summary>
        /// 递归除法算法
        /// </summary>
        RecursiveDivision,
        /// <summary>
        /// 递归回溯算法
        /// </summary>
        RecursiveBacktracking
    }

 

FrmMain主窗体:

 

 public partial class FrmMain : Form
    {
        private readonly Maze _maze;
        private System.Windows.Forms.Timer _timer;
        public FrmMain()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.DoubleBuffer |
               ControlStyles.UserPaint |
               ControlStyles.AllPaintingInWmPaint,
               true);
            this.UpdateStyles();
            _maze = new Maze();
        }

        private void FrmGame_Load(object sender, EventArgs e)
        {
            this.KeyPreview = true;

            BindType(typeof(MazeType), this.cbMazeType, "Default");
        }
        private void BindType(Type type, ComboBox comboBox, string defaultValue)
        {
            var enumValues = Enum.GetValues(type);
            var list = new List<IdValues>();
            int index = 0, curIndex = 0;
            foreach (Enum value in enumValues)
            {
                int hc = value.GetHashCode();
                list.Add(new IdValues
                {
                    Id = hc.ToString(),
                    Value = value.ToString(),
                    Standby = hc
                });
                if (value.ToString() == defaultValue)
                    index = curIndex;

                curIndex++;
            }

            comboBox.ValueMember = "Id";
            comboBox.DisplayMember = "Value";
            comboBox.DataSource = list;
            comboBox.SelectedIndex = index;
        }
        private void FrmGame_FormClosing(object sender, FormClosingEventArgs e)
        {
            _maze.Dispose();
            this.Dispose();
        }

        private bool _isPlayGame = false;
        public bool IsPlayGame
        {
            get => _isPlayGame;
            set
            {
                if (_isPlayGame == value)
                    return;

                _isPlayGame = value;
                if (value)
                {
                    btnPlayGame.ExecBeginInvoke(() =>
                    {
                        btnPlayGame.Text = "重新开始";
                    });
                }
                else
                {
                    btnPlayGame.ExecBeginInvoke(() =>
                    {
                        btnPlayGame.Text = "开启游戏";
                    });
                }
            }
        }
        private void btnPlayGame_Click(object sender, EventArgs e)
        {
            if (IsPlayGame)
            {
                if (MessageBox.Show("正在游戏中,确认重新开始吗?", "迷宫游戏提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    plGame.Focus();
                    return;
                }
            }

            if (_timer != null)
            {
                _timer.Stop();
                _timer.Dispose();
                _timer = null;
            }


            _isAutoMove = false;
            IsPlayGame = true;
            int w = 10, h = 8;
            if (rbEasy.Checked)
            {
                w = 30;
                h = 21;
            }
            else if (rbMedium.Checked)
            {
                w = 66;
                h = 45;
            }
            else
            {
                w = 100;
                h = 67;
            }
            using var g = plGame.CreateGraphics();
            MazeType mazeType = (MazeType)(this.cbMazeType.Items[cbMazeType.SelectedIndex] as IdValues).Standby;
            _maze.CreateMaze(w, h, plGame.Width, plGame.Height, mazeType);

            plGame.Controls.Clear();
            g.Clear(plGame.BackColor);
            _maze.Draw(g, plGame.Width, plGame.Height);

            _timer = new System.Windows.Forms.Timer();
            _timer.Interval = 1000;
            time = 0;
            _timer.Tick += timer_Tick;
            _timer.Start();

            plGame.Focus();
        }
        long time = 0;
        private void timer_Tick(object? sender, EventArgs e)
        {
            lblTime.ExecBeginInvoke(() =>
            {
                lblTime.Text = Compute(++time);
            });

        }

        public string Compute(long time)
        {
            if (time < 60)
                return $"00:{ChangeString(time)}";
            long minute = time / 60;
            if (minute < 60)
                return $"{ChangeString(minute)}:{ChangeString(time % 60)}";
            long hour = minute / 60;
            return $"{ChangeString(hour)}:{Compute(time - hour * 3600)}";
        }
        private string ChangeString(long val)
        {
            return val.ToString("D2");
        }
        private void plGame_Paint(object sender, PaintEventArgs e)
        {
            plGame.Controls.Clear();
            e.Graphics.Clear(plGame.BackColor);

            _maze.Draw(e.Graphics, plGame.Width, plGame.Height);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (_isAutoMove)
                return;

            base.OnKeyDown(e);
            var result = _maze.Move(e);
            RefreshResult(result);
        }
        private void RefreshResult(MoveResult result)
        {
            if (result.IsInvalidate)
            {
                plGame.ExecInvoke(() =>
                {
                    // 重绘迷宫
                    plGame.Invalidate(result.OldRect);
                    plGame.Invalidate(result.NewRect);
                });

                if (result.IsWin)
                {
                    IsPlayGame = false;
                    if (_timer != null)
                    {
                        _timer.Stop();
                        _timer.Dispose();
                        _timer = null;
                    }
                    MessageBox.Show("通过", "迷宫通过提示");
                }
            }
        }
        private void FrmMain_Activated(object sender, EventArgs e)
        {
            plGame.Focus();
        }
        /// <summary>
        /// 提示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrompt_Click(object sender, EventArgs e)
        {
            if (_maze.MazeBitmap == null)
            {

                return;
            }
            Bitmap bmp = new Bitmap(plGame.Width, plGame.Height);
            plGame.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
            int size = 0;
            if (rbEasy.Checked)
                size = 0;
            else if (rbMedium.Checked)
                size = 1;
            else
                size = 2;
            FrmPrompt frmPrompt = new FrmPrompt(_maze.DrawPath(bmp), size);
            frmPrompt.Show();
            plGame.Focus();
        }

        private bool _isAutoMove = false;
        /// <summary>
        /// 一键通过
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPass_Click(object sender, EventArgs e)
        {
            if (!_maze.IsMove)
                return;

            _isAutoMove = true;
            Task.Run(() =>
            {
                var path = _maze.FindPath();
                if (path != null)
                {
                    Point point = new Point(0, 0);
                    foreach (var item in path)
                    {
                        if (!_isAutoMove)
                            break;

                        point.X = item.X;
                        point.Y = item.Y;
                        var result = _maze.Move(point);
                        RefreshResult(result);
                        plGame.ExecInvoke(() =>
                        {
                            plGame.Update();
                        });

                        Thread.Sleep(50);
                    }
                }
                _isAutoMove = false;
            });
        }

        private void plGame_Resize(object sender, EventArgs e)
        {

        }
    }

    public class IdValues
    {
        public string Id { get; set; }
        public string Value { get; set; }
        public string Value2 { get; set; }
        public string Value3 { get; set; }
        public string Value4 { get; set; }
        public string Value5 { get; set; }
        public int Standby { get; set; }

        public static bool operator ==(IdValues idValues, IdValues idValues2)
        {
            return idValues.Equals(idValues2);
        }
        public static bool operator !=(IdValues idValues, IdValues idValues2)
        {
            return !idValues.Equals(idValues2);
        }
        public override int GetHashCode()
        {
            var code = (Id, Value, Value2, Value3, Value4, Value5, Standby).GetHashCode();
            return code;
        }
        public override bool Equals(object? obj)
        {
            return obj?.GetHashCode() == GetHashCode();
        }
        const int TARGET = 0x1F;
        /// <summary>
        /// 将连续字段的哈希代码左移两位或更多位来加权各个哈希代码(最佳情况下,超出位 31 的位应环绕,而不是被丢弃)
        /// </summary>
        /// <param name="value"></param>
        /// <param name="positions"></param>
        /// <returns></returns>
        public int ShiftAndWrap(int value, int positions = 3)
        {
            positions &= TARGET;
            uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
            uint wrapped = number >> (32 - positions);
            return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
        }
    }

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1018981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 文件写入操作

视频版教程 Python3零基础7天入门实战视频教程 w模式是写入&#xff0c;通过write方法写入内容。 # 打开文件 模式w写入&#xff0c;文件不存在&#xff0c;则自动创建 f open("D:/测试3.txt", "w", encoding"UTF-8")# write写入操作 内容写入…

电脑软件:火绒应用商店功能体验(附下载)

火绒作为国内杀毒软件的一股清流&#xff0c;相信很多电脑爱好者都使用火绒软件作为自己的电脑杀毒软件&#xff0c;火绒杀毒软件的最大特点是软件没有弹窗广告、电脑杀毒可靠、完全免费使用、支持拦截烦人的弹窗广告。今天主要给大家介绍火绒官方内测了一款电脑应用商店独立软…

RK3588平台开发系列讲解(安卓篇)Android12 获取 root 权限

文章目录 一、关闭 selinux二、注释用户组权限检测三、su 文件默认授予 root 权限沉淀、分享、成长,让自己和他人都能有所收获!😄 📢获取Android设备的root权限是指取得超级用户(root用户)的权限,使得用户可以对系统进行更广泛的修改和操作。但需要注意,获取root权限…

VMware Workstation Pro各版本下载安装教程

VMware Workstation Pro下载 打开浏览器&#xff0c;输入VMware Workstation Pro 找到VMware Workstation Pro官网并点击进入&#xff0c;官网地址&#xff1a;https://www.vmware.com/cn/products/workstation-pro.html 进入官网首页后可以下载最新版本的VMware Workstation P…

【JAVA-Day21】序列化和反序列化,学会Java的编解码方法

标题序列化和反序列化&#xff0c;学会Java的编解码方法 序列化和反序列化&#xff0c;学会Java的编解码方法摘要引言一、什么是序列化1.1 序列化的过程 二、什么是反序列化2.1 反序列化的过程 三、为什么要进行序列化和反序列化3.1 主要目的3.2 应用场景 四、总结参考资料 博主…

linux-gic中断分析

linux-gic中断分析 这里主要分析 linux kernel 中 GICv3 中断控制器的代码(drivers/irqchip/irq-gic-v3.c)。 一、设备树 先来看下中断控制器的设备树信息&#xff1a; gic: interrupt-controller3400000 {compatible "arm,gic-v3";#interrupt-cells <3>;…

【pytest】conftest.py使用

1. 创建test_project 目录 test_project/sub/test_sub.py def test_baidu(test_url):print(fsub {test_url}) test_project/conftest.py 设置钩子函数 只对当前目录 和子目录起作用 import pytest #设置测试钩子函数 pytest.fixture() def test_url():return "http…

性能测试-性能测试的标准依据和价值(1)

性能测试的依据 国际标准化组织ISO/IEC JTC1/SC7/WG6开展了软件质量度量和评价的标准化工作&#xff0c;制定了ISO/IEC 25000 SQuaRE系列国际标准。 GB/T 25000.1—2021《系统与软件工程 系统与软件质量要求和评价(SQuaRE)第1部分&#xff1a;SQuaRE指南》便是采纳ISO/IEC 25…

巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器的相同和不同之处

巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器的相同和不同之处 1、概述 用 MATLAB 中的函数可以设计巴特沃斯、切比雪夫I型、切比雪夫Ⅱ型和椭圆型滤波器&#xff0c;我们用MATLAB的函数&#xff0c;在相同的条件下观察巴特沃斯、切比雪夫I型、 切比雪夫Ⅱ型和椭圆型滤…

如何看待近期tiktok大批量封号问题?

近期大量客户反馈Tiktok账号大批量被封&#xff0c;了解这类客户的情况后&#xff0c;得知被封的账号大部分都是为搬运国内视频上传的账号类型&#xff0c;从这次的事件可以看出&#xff0c;tk对视频的检测以及内容要求度越来越高&#xff0c;Tk风控升级&#xff0c;回导致很多…

【Nacos】Nacos服务注册源码分析(二)

在上篇文章中&#xff0c;我们主要聚焦于Nacos服务注册在服务端grpc设计层面的一些代码。本篇文章将深入探讨服务注册的相关逻辑&#xff0c;通过细致的分析来更全面地理解这一过程。 NamingGrpcClientProxy.registerService 我们从NamingGrpcClientProxy的registerService方法…

Vue项目中使用element-plus的el-table组件-组件使用-样式修改

项目配置 <div class"table-wrap"><el-tableclass"table-card-container":data"tableData"style"width: 100%"><template v-for"column in tableColumn"><el-table-columnv-if"column.isShow&qu…

前端笔试2

1.下面哪一个是检验对象是否有一个以自身定义的属性? foo.hasOwnProperty("bar")bar in foo foo["bar"] ! undefinedfoo.bar ! null 解析&#xff1a; bar in foo 检查 foo 对象是否包含名为 bar 的属性&#xff0c;但是这个属性可以是从原型链继承来的&a…

华为云云耀云服务器L实例评测|轻量级应用服务器对决:基于 fio 深度测评华为云云耀云服务器L实例的磁盘性能

本文收录在专栏&#xff1a;#云计算入门与实践 - 华为云 专栏中&#xff0c;本系列博文还在更新中 相关华为云云耀云服务器L实例评测文章列表如下&#xff1a; 华为云云耀云服务器L实例评测 | 从零开始&#xff1a;云耀云服务器L实例的全面使用解析指南华为云云耀云服务器L实…

JVM:如何判断对象已死?

对象已死&#xff1f; 在堆里面存放着Java世界中几乎所有的对象实例&#xff0c;垃圾收集器在对堆进行回收前&#xff0c;第一件事情就是要确定这些对象之中哪些还“存活”着&#xff0c;哪些已经“死去”&#xff08;“死去”即不可能再被任何途径使用的对象&#xff09;了。…

2023/09/17

文章目录 1. vscode展开所有代码快捷键ctrl k j2. git删除所有stash或指定stash git stash drop [可选stash名]3. vue在函数默认参数后增加新参数4. git push 添加“-u”参数5. vscode快捷输入符号$的使用6. WebGL之什么是GLB&GLTF文件&#xff1f;7. WebGL之什么是HDR&a…

python之pyQt5实例:Matplotlib的应用

1、显示逻辑 1.1MatplotlibWidget.py import sys import random import matplotlibmatplotlib.use("Qt5Agg") from PyQt5 import QtCore from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QSizePolicy, QWidget from numpy import arange, si…

nginx日志分割

nginx日志分割 有的用nginx做代理的&#xff0c;日志产生的特别多&#xff0c;而nginx的日志又是一整个&#xff0c;所以需要我们自己来写分割脚本了 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.写脚本 #!/bin/bash #nginx日志分割 LOGPATH/home/oldlogs CURLOG…

多目标优化算法:基于非支配排序的小龙虾优化算法(NSCOA)MATLAB

一、小龙虾优化算法COA 小龙虾优化算法&#xff08;Crayfsh optimization algorithm&#xff0c;COA&#xff09;由Jia Heming 等人于2023年提出&#xff0c;该算法模拟小龙虾的避暑、竞争和觅食行为&#xff0c;具有搜索速度快&#xff0c;搜索能力强&#xff0c;能够有效平衡…

前端用JavaScript实现桑基图(Sankey图)

前端用JavaScript实现桑基图&#xff08;Sankey图&#xff09; 桑基图&#xff08;Sankey图&#xff09;&#xff0c;是流图的一种&#xff0c;常用来展示事物的数量、发展方向、数据量大小等&#xff0c;在可视化分析中经常使用。 本文&#xff0c;演示如何在前端用JavaScri…