C#迷宫Winform小游戏,生成可连通的迷宫地图

article/2025/3/11 9:05:48

上一篇本人已经写了一个控制台小游戏,这次使用Winform来生成可连通的地图,并测试运行游戏

迷宫小游戏控制台

一、先更改控制台游戏的一点点代码,用于测试迷宫是否连通的【即:从起点可以到达终点】。只用更改 MazeUtil.cs的查找路径方法FindPath()。用于返回是否连通。

整体更改后的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MazeDemo
{
    /// <summary>
    /// 迷宫可以认为是一个N*M的行列式,也可以认为是一个二维数组,每个元素都是一个单元格MazeGrid
    /// </summary>
    public class MazeUtil
    {
        /// <summary>
        /// 使用一个障碍墙的二维数组来初始化迷宫地图
        /// </summary>
        /// <param name="wallArray">数组元素的值为1时,代表障碍墙,否则是可通过的</param>
        public MazeUtil(int[,] wallArray)
        {
            if (wallArray == null || wallArray.Length == 0)
            {
                throw new Exception("初始化数组不能为空");
            }
            Width = wallArray.GetLength(0);
            Height = wallArray.GetLength(1);
            //初始化地图
            MazeArray = new MazeGrid[Width, Height];
            for (int i = 0; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    MazeArray[i, j] = new MazeGrid(i, j, wallArray[i, j] == 1);
                }
            }
            CurrentGrid = MazeArray[0, 0];
            TargetGrid = MazeArray[Width - 1, Height - 1];
        }
        /// <summary>
        /// 迷宫的宽度,也就是二维数组的行数【注意:行数对应纵坐标Y】
        /// </summary>
        public int Width { get; set; }
        /// <summary>
        /// 迷宫的高度,也就是二维数组的列数【注意:列数对应横坐标X】
        /// </summary>
        public int Height { get; set; }
        /// <summary>
        /// 迷宫行列式,由 Width*Height 个网格组成
        /// </summary>
        public MazeGrid[,] MazeArray { get; set; }

        /// <summary>
        /// 当前网格,起点默认为左上角,即 MazeGrid[0,0]
        /// </summary>
        public MazeGrid CurrentGrid { get; set; }

        /// <summary>
        /// 终点:目标网格,默认为右下角,即 MazeGrid[Width-1,Height-1]
        /// </summary>
        public MazeGrid TargetGrid { get; set; }

        /// <summary>
        /// 栈,用于存储移动的路径:找到一个 未访问的 并且 不是障碍,就Push()入栈
        /// </summary>
        public Stack<MazeGrid> stack = new Stack<MazeGrid>();

        /// <summary>
        /// 以此遍历当前网格的上、右、下、左四个方向。
        /// 如果遇到障碍 或者 已访问过,就尝试其他方向。否则就把 无障碍 并且 未访问的网格作为新的网格
        /// </summary>
        /// <param name="mazeGrid"></param>
        public void MoveNext(MazeGrid mazeGrid)
        {
            Direction direction = Direction.All;
            //按照上、右、下、左【顺时针】顺序以此遍历,当遍历完左Left后,则全部遍历完成,此时置方向为All
            switch (mazeGrid.Direction)
            {
                case Direction.None://当是None时,默认向上Up遍历
                    mazeGrid.Direction = Direction.Up;
                    direction = Direction.Up;
                    break;
                case Direction.Up://当是Up时,接着向右Right遍历
                    mazeGrid.Direction = Direction.Right;
                    direction = Direction.Right;
                    break;
                case Direction.Right://当是Right时,接着向下Down遍历
                    mazeGrid.Direction = Direction.Down;
                    direction = Direction.Down;
                    break;
                case Direction.Down://当是Down时,接着向左Left遍历
                    mazeGrid.Direction = Direction.Left;
                    direction = Direction.Left;
                    break;
                case Direction.Left://当是Left时,说明四个方向全部遍历完了,置为All
                    mazeGrid.Direction = Direction.All;
                    direction = Direction.All;
                    break;
            }

            //对上、右、下、左四个方向进行处理【None 和 All不做处理】
            switch (direction)
            {
                case Direction.Up:
                    if (mazeGrid.RowIndex - 1 >= 0)
                    {
                        MazeGrid upGrid = MazeArray[mazeGrid.RowIndex - 1, mazeGrid.ColumnIndex];
                        if (!upGrid.IsWall && !upGrid.IsVisited)
                        {
                            //如果不是障碍 并且 没有访问过
                            CurrentGrid = upGrid;
                        }
                        else
                        {
                            //尝试其他方向
                            MoveNext(CurrentGrid);
                        }
                    }
                    break;
                case Direction.Right:
                    if (mazeGrid.ColumnIndex + 1 < Height)
                    {
                        MazeGrid rightGrid = MazeArray[mazeGrid.RowIndex, mazeGrid.ColumnIndex + 1];
                        if (!rightGrid.IsWall && !rightGrid.IsVisited)
                        {
                            //如果不是障碍 并且 没有访问过
                            CurrentGrid = rightGrid;
                        }
                        else
                        {
                            //尝试其他方向
                            MoveNext(CurrentGrid);
                        }
                    }
                    break;
                case Direction.Down:
                    if (mazeGrid.RowIndex + 1 < Width)
                    {
                        MazeGrid downGrid = MazeArray[mazeGrid.RowIndex + 1, mazeGrid.ColumnIndex];
                        if (!downGrid.IsWall && !downGrid.IsVisited)
                        {
                            //如果不是障碍 并且 没有访问过
                            CurrentGrid = downGrid;
                        }
                        else
                        {
                            //尝试其他方向
                            MoveNext(CurrentGrid);
                        }
                    }
                    break;
                case Direction.Left:
                    if (mazeGrid.ColumnIndex - 1 >= 0)
                    {
                        MazeGrid leftGrid = MazeArray[mazeGrid.RowIndex, mazeGrid.ColumnIndex - 1];
                        if (!leftGrid.IsWall && !leftGrid.IsVisited)
                        {
                            //如果不是障碍 并且 没有访问过
                            CurrentGrid = leftGrid;
                        }
                        else
                        {
                            //尝试其他方向
                            MoveNext(CurrentGrid);
                        }
                    }
                    break;
            }
        }

        /// <summary>
        /// 查找路径,返回起点到终点是否是可连通的
        /// </summary>
        /// <returns>true:可以到达终点,false:无法到达终点</returns>
        public bool FindPath()
        {
            //如果当前网格没有移动到目标网格。
            bool existPath = true;
            //这里如果遇到无法到达目标网格的障碍地图时,需要终止
            while (CurrentGrid != TargetGrid)
            {
                if (CurrentGrid.IsVisited)
                {
                    //如果当前网格全部访问完成,则出栈
                    if (CurrentGrid.Direction == Direction.All)
                    {
                        if (stack.Count > 0)
                        {
                            stack.Pop();//移除最后一次添加的
                        }
                        if (stack.Count > 0)
                        {
                            //获取倒数第二次添加的
                            CurrentGrid = stack.Peek();
                        }
                        else
                        {
                            Console.WriteLine("无路可走,请检查迷宫障碍设置...");
                            existPath = false;
                            break;
                        }
                    }
                    else
                    {
                        //没有遍历完,继续遍历
                        MoveNext(CurrentGrid);
                    }
                }
                else
                {
                    //如果未访问,则设置为已访问,同时添加入栈
                    CurrentGrid.IsVisited = true;
                    stack.Push(MazeArray[CurrentGrid.RowIndex, CurrentGrid.ColumnIndex]);     
                }
            }
            //将目标网格添加到顶部
            if (stack.Count > 0)
            {
                stack.Push(TargetGrid);
            }
            return existPath;
        }

        /// <summary>
        /// 打印路径
        /// </summary>
        public void PrintPath()
        {
            if (stack.Count == 0)
            {
                Console.WriteLine("无法到达目的网格,请检查迷宫地图设置...");
                return;
            }
            //因第一个插入的元素是入口,栈是先进后出,入口反而成为最后元素。这里进行反转
            IEnumerable<MazeGrid> grids = stack.Reverse();
            foreach (MazeGrid item in grids)
            {
                Console.WriteLine(item);
            }
        }
    }
}
二、新建Windows窗体应用程序MazeTest,添加对MazeDemo控制台程序的引用。将MazeTest设为启动项目。然后将默认的Form1窗体重命名为FormMaze。窗体设置宽度为1054, 高度为606。操作面板panel1的位置Location

窗体设计如下图:

为窗体的重绘Paint绑定事件方法FormMaze_Paint(),Init按钮绑定事件btnInit_Click(),上、下、左、右绑定事件btnDirection_Click。同时重写键盘事件ProcessCmdKey,对上下左右方向键进行相应处理。

三、FormMaze.cs整体代码如下(忽略设计器自动生成的代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MazeDemo;

namespace MazeTest
{
    public partial class FormMaze : Form
    {
        /// <summary>
        /// 初始化设置障碍墙
        /// </summary>
        static int[,] wallArray = new int[5, 6] { { 0, 0, 1, 0, 0, 0 }, { 0, 1, 0, 1, 0, 0 }, { 0, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 } };
        MazeUtil mazeUtil = new MazeUtil(wallArray);
        public FormMaze()
        {
            InitializeComponent();

            //使用双缓冲来减少图形闪烁(当绘制图片时出现闪烁时,使用双缓冲)
            this.DoubleBuffered = true;//设置本窗体启用双缓冲
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); //禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true); //双缓冲
        }

        /// <summary>
        /// 处理windows消息:禁掉清除背景消息
        /// 主要是处理部分控件使用双缓冲也会闪烁的现象
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0014) // 禁掉清除背景消息
                return;
            base.WndProc(ref m);
        }

        /// <summary>
        /// 重写键盘事件,对上下左右方向键进行相应处理
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Up:
                    btnDirection_Click(btnUp, null);
                    break;
                case Keys.Right:
                    btnDirection_Click(btnRight, null);
                    break;
                case Keys.Down:
                    btnDirection_Click(btnDown, null);
                    break;
                case Keys.Left:
                    btnDirection_Click(btnLeft, null);
                    break;
            }
            return false;//如果要调用KeyDown,这里一定要返回false才行,否则只响应重写方法里的按键.
            //这里调用一下父类方向,相当于调用普通的KeyDown事件.如果按空格会弹出两个对话框
            //return base.ProcessCmdKey(ref msg, keyData);
            //return true;//这里return true 否则控件焦点会跟着方向键改变
        }
        private void FormMaze_Load(object sender, EventArgs e)
        {
            this.AutoScroll = true;
            rtxbDisplay.ReadOnly = true;
        }

        /// <summary>
        /// 上下左右方向移动事件【四个方向按钮都绑定该事件】
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDirection_Click(object sender, EventArgs e)
        {
            Button button = sender as Button;
            //MessageBox.Show(mazeUtil.CurrentGrid+",行数:"+ mazeUtil.Width+",列数:"+ mazeUtil.Height);
            switch (button.Name)
            {
                case "btnUp":
                    if (mazeUtil.CurrentGrid.RowIndex - 1 < 0)
                    {
                        //使用系统声音报警
                        System.Media.SystemSounds.Beep.Play();
                        //Asterisk:星号,引起注意,重要的声音
                        //Beep:操作无效的声音
                        //Exclamation:感叹声 打开某个文件的声音
                        //Hand:手动处理的声音
                        //Question
                    }
                    else
                    {
                        MazeGrid nextGrid = mazeUtil.MazeArray[mazeUtil.CurrentGrid.RowIndex - 1, mazeUtil.CurrentGrid.ColumnIndex];
                        if (nextGrid.IsWall)
                        {
                            //障碍,报警
                            System.Media.SystemSounds.Asterisk.Play();
                        }
                        else
                        {
                            mazeUtil.CurrentGrid = nextGrid;
                            this.Invalidate();//触发paint事件
                            //update,repaint,invalid
                        }
                    }
                    break;
                case "btnRight":
                    if (mazeUtil.CurrentGrid.ColumnIndex + 1 >= mazeUtil.Height)
                    {
                        //使用系统声音报警
                        System.Media.SystemSounds.Beep.Play();
                    }
                    else
                    {
                        MazeGrid nextGrid = mazeUtil.MazeArray[mazeUtil.CurrentGrid.RowIndex, mazeUtil.CurrentGrid.ColumnIndex + 1];
                        if (nextGrid.IsWall)
                        {
                            //障碍,报警
                            System.Media.SystemSounds.Asterisk.Play();
                        }
                        else
                        {
                            mazeUtil.CurrentGrid = nextGrid;
                            this.Invalidate();//触发paint事件
                        }
                    }
                    break;
                case "btnDown":
                    if (mazeUtil.CurrentGrid.RowIndex + 1 >= mazeUtil.Width)
                    {
                        //使用系统声音报警
                        System.Media.SystemSounds.Beep.Play();
                    }
                    else
                    {
                        MazeGrid nextGrid = mazeUtil.MazeArray[mazeUtil.CurrentGrid.RowIndex + 1, mazeUtil.CurrentGrid.ColumnIndex];
                        if (nextGrid.IsWall)
                        {
                            //障碍,报警
                            System.Media.SystemSounds.Asterisk.Play();
                        }
                        else
                        {
                            mazeUtil.CurrentGrid = nextGrid;
                            this.Invalidate();//触发paint事件
                        }
                    }
                    break;
                case "btnLeft":
                    if (mazeUtil.CurrentGrid.ColumnIndex - 1 < 0)
                    {
                        //使用系统声音报警
                        System.Media.SystemSounds.Beep.Play();
                    }
                    else
                    {
                        MazeGrid nextGrid = mazeUtil.MazeArray[mazeUtil.CurrentGrid.RowIndex, mazeUtil.CurrentGrid.ColumnIndex - 1];
                        if (nextGrid.IsWall)
                        {
                            //障碍,报警
                            System.Media.SystemSounds.Asterisk.Play();
                        }
                        else
                        {
                            mazeUtil.CurrentGrid = nextGrid;
                            this.Invalidate();//触发paint事件
                        }
                    }
                    break;
            }
            if (mazeUtil.CurrentGrid == mazeUtil.TargetGrid)
            {
                DisplayContent("已到达迷宫终点,真棒!");
                mazeUtil.CurrentGrid = mazeUtil.MazeArray[0, 0];
                MessageBox.Show("已到达迷宫终点,真棒!", "成功");
            }
        }

        private void btnInit_Click(object sender, EventArgs e)
        {
            int rowCount;//行数
            int columnCount;//列数
            if (!CheckInputCount(txbRowCount, "行数", out rowCount))
            {
                return;
            }
            if (!CheckInputCount(txbColumnCount, "列数", out columnCount))
            {
                return;
            }
            wallArray = new int[rowCount, columnCount];
            DisplayContent("正在生成随机地图,请稍候...");

            //异步生成地图
            GenerateConnectableMap(rowCount, columnCount);
            //重绘迷宫,新的开始
            mazeUtil.CurrentGrid = mazeUtil.MazeArray[0, 0];
            mazeUtil.stack.Clear();
            this.Invalidate();
        }

        /// <summary>
        /// 生成可连通的地图【从起点可以到达终点】。因行数、列数较大时。寻找出可连通地图的耗时较长。
        /// 会造成界面假死,这里增加异步处理耗时任务
        /// </summary>
        /// <param name="rowCount"></param>
        /// <param name="columnCount"></param>
        public void GenerateConnectableMap(int rowCount, int columnCount)
        {
            TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
            Task<bool> task = tcs.Task;
            //这里进行耗时操作
            System.Threading.ThreadPool.QueueUserWorkItem(waitCallback => 
            {
                //这里执行耗时任务:寻找到一个可连通的地图
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start();
                bool existPath = false;
                do
                {
                    //注意:起始点、终点一定不是墙。定义 随机0或1的随机数
                    for (int i = 0; i < rowCount; i++)
                    {
                        for (int j = 0; j < columnCount; j++)
                        {
                            if ((i == 0 && j == 0) || (i == rowCount - 1 && j == columnCount - 1))
                            {
                                //起点、终点一定为0,不考虑随机数。其他点随机
                                continue;
                            }
                            wallArray[i, j] = new Random(Guid.NewGuid().GetHashCode()).Next(0, 2);
                        }
                    }
                    mazeUtil = new MazeUtil(wallArray);
                    existPath = mazeUtil.FindPath();
                    //如果起点、终点不是连通的,则重新随机设计地图
                } while (!existPath);
                stopwatch.Stop();
                DisplayContent($"生成随机地图成功,用时【{stopwatch.ElapsedMilliseconds}】ms.新的一局开始");
                //一旦对 TaskCompletionSource 调用 SetResult 方法,相关联的 Task 便会结束,返回 Task 的结果值
                tcs.SetResult(existPath);
            });
            task.Wait(10000);
            DisplayContent($"耗时任务结果:【{task.Result}】.");
        }

        /// <summary>
        /// 显示文本框内容
        /// </summary>
        /// <param name="message"></param>
        private void DisplayContent(string message)
        {
            this.BeginInvoke(new Action(() => 
            {
                if (rtxbDisplay.TextLength > 10240)
                {
                    rtxbDisplay.Clear();
                }
                rtxbDisplay.AppendText(message + "\n");
                rtxbDisplay.ScrollToCaret();
            }));
        }

        /// <summary>
        /// 检查输入
        /// </summary>
        /// <param name="txb"></param>
        /// <param name="commentStr"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        private bool CheckInputCount(TextBox txb, string commentStr, out int count)
        {
            if (!int.TryParse(txb.Text, out count))
            {
                MessageBox.Show($"[{commentStr}]请输入正整数", "错误");
                txb.Focus();
                return false;
            }
            if (count <= 0 || count >= 100)
            {
                MessageBox.Show($"[{commentStr}]范围是【1~99】,请重新输入", "错误");
                txb.Focus();
                return false;
            }
            return true;
        }

        /// <summary>
        /// 窗体的重绘事件,调用Invalidate()会触发重绘事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMaze_Paint(object sender, PaintEventArgs e)
        {
            int sideLength = 50;//正方形【迷宫的一个网格MazeGrid】的边长。
            float fontSize = 13;//打印的起点、终点文字的字体大小
            //以边长为50为例:因当前窗体的高度为606,去除窗体顶部和底部的高度【约56】,只能正常显示11行。因Panel控件的横坐标为705,因此只能显示14列。
            if (mazeUtil.Width <= 11 && mazeUtil.Height <= 14)
            {
                sideLength = 50;
                fontSize = 13;
            }
            else if (mazeUtil.Width <= 22 && mazeUtil.Height <= 28)
            {
                //如果行数在22行之内,列数在28列之内,则将网格的边长设置25
                sideLength = 25;
                fontSize = 8;
            }
            else
            {
                //如果行数、列数过大(行数大于22,列数大于28)。则应该将界面变大,并增加滚动条
                sideLength = 25;
                fontSize = 8;
                if (mazeUtil.Width > 22)
                {
                    this.Height = this.Height + (mazeUtil.Width - 22) * sideLength;
                }
                if (mazeUtil.Height > 28)
                {
                    this.Width = this.Width + (mazeUtil.Height - 28) * sideLength;
                    //Panel操作面板要整体向右移动,即X坐标增加
                    panel1.Location = new Point(panel1.Location.X + (mazeUtil.Height - 28) * sideLength, panel1.Location.Y);
                }
            }
            Graphics graphics = e.Graphics;
            for (int i = 0; i < mazeUtil.Width; i++)
            {
                for (int j = 0; j < mazeUtil.Height; j++)
                {
                    //注意:第一行是Y坐标没变,X坐标在变化。因此i是纵坐标 j是横坐标
                    Rectangle rect = new Rectangle(sideLength * j, sideLength * i, sideLength, sideLength);
                    graphics.DrawRectangle(new Pen(Color.Red), rect);
                    if (mazeUtil.MazeArray[i, j].IsWall)
                    {
                        graphics.FillRectangle(new SolidBrush(Color.Black), rect);
                    }
                    //如果不是起点,也不是终点,并且是当前移动到节点
                    else if ((i != 0 || j != 0) && (i != mazeUtil.Width - 1 || j != mazeUtil.Height - 1)
                        && mazeUtil.MazeArray[i, j] == mazeUtil.CurrentGrid)
                    {
                        graphics.FillRectangle(new SolidBrush(Color.Yellow), rect);
                    }
                }
            }
            //起点设置为蓝色
            Rectangle rectStart = new Rectangle(0, 0, sideLength, sideLength);
            graphics.FillRectangle(new SolidBrush(Color.Blue), rectStart);            
            AddTextAlignCenter(graphics, "起点", new Font("宋体", fontSize), rectStart);
            //终点设置为红色
            Rectangle rectEnd = new Rectangle(sideLength * (mazeUtil.Height - 1), sideLength * (mazeUtil.Width - 1), sideLength, sideLength);
            graphics.FillRectangle(new SolidBrush(Color.Red), rectEnd);
            AddTextAlignCenter(graphics, "终点", new Font("宋体", fontSize), rectEnd);
        }

        /// <summary>
        /// 将显示的文字放在矩形的中间
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="text"></param>
        /// <param name="font"></param>
        /// <param name="rect"></param>
        private void AddTextAlignCenter(Graphics graphics, string text, Font font, Rectangle rect)
        {
            SizeF sizeF = graphics.MeasureString(text, font);
            float destX = rect.X + (rect.Width - sizeF.Width) / 2;
            float destY = rect.Y + (rect.Height - sizeF.Height) / 2;
            graphics.DrawString(text, font, Brushes.Black, destX, destY);
        }        
    }
}

 

四:程序运行如下图


设置10行12列,点击初始化Init

可以点击按钮上下左右,也可以按键盘的方向键上下左右。到边界或障碍墙将会有警告提示音。

 

成功如图:

 


http://chatgpt.dhexx.cn/article/ipwetuZR.shtml

相关文章

迷宫游戏|自动寻径|随机生成迷宫地图|UI|闯关|地图反转

MazeGame 遵循开源协议 MIT 开发工具及运行环境 开发IDE环境 : Visual Studio 2019 代码管理工具: Git 开发语言:C 程序运行环境(开发环境为(Windows10)其他兼容性未知) 依赖库 EasyX 图形界面库 EasyX官网&#xff1a;EasyX Git仓库地址 Gitee:Gitee 仓库 Github:h…

Java程序:迷宫地图生成器

Java程序:迷宫地图生成器 1、运行效果 可以在【0,50】之间随意设置行数和列数,比如设置为25行25列的迷宫地图数组。 迷宫地图的每一个方格,如果是白色,单击就变成黑色,如果是黑色,单击就变成白色。黑色对应数组里的1,白色对应数组里的0。 因为没有采用路径搜索算法来设…

Java 开发实例(第3篇),绘制迷宫1 生成迷宫地图

开发环境&#xff1a; 操作系统Win10。 1.下载Java 15&#xff0c;提取码&#xff1a;soft 2.下载软件 Eclipse 2020-12&#xff0c;提取码&#xff1a;soft 下载本博客的实例工程代码&#xff0c;提取码&#xff1a;soft 前天2月9日在逛B站App时&#xff0c;意外看到一个很…

Python 打印迷宫地图小游戏

在实现玩转小迷宫这个游戏时&#xff0c;分别使用了input()输入函数、print()输出函数、if…elif…else语句、二维列表、while循环、for循环 下面对这些用法再一次重温 1.input()输入函数 在 Python 中&#xff0c;使用内置函数 input() 可以接收用户的键盘输入。input() 函数…

html5的canvas绘制迷宫地图

canvas标签一直是html5的亮点,用它可以实现很多东西。我想用它来绘画像迷宫那样的地图。借助到的工具有瓦片地图编辑器tiled(点击跳转到下载链接)。 如图:如果你想要画像这样的迷宫地图,如果不用canvas,可以通过dom操作拼接一个一个div,以达成这个效果。那样是不是很不合…

深度优先,Kruskal,Prim几种方式生成迷宫地图

小时候玩过一款3D版迷宫&#xff0c;那时还是功能机时代&#xff0c;黑白界面拼凑的伪3D效果还是给我带来了很多快乐。后来出现了智能机&#xff0c;却再也没找到过那样纯粹的迷宫游戏。总算自己找时间做一个出来。 本文主要介绍一下深度优先&#xff0c;Kruskal,Prim几种方式生…

二维数组随机生成地图迷宫_经验分享:三套简单的迷宫地图生成方案

文/兔四 概述:文章基于一种基础的地图,来讨论三套不同的地图生成方案。 文章不会出现跟代码相关的内容,会以较为通俗的语句和不少简单的示意图来表示迷宫的生成方案。其中不少方法来自于游戏界前辈,我根据自己的基础地图做了不少修正(毕竟迷宫和地图的形式多种多样,适合自…

算法自动生成迷宫地图

文章目录 前言一、什么是&#xff08;DFS&#xff09;深度优先算法&#xff1f;深度优先算法实现步骤1.引入库2.初始化参数3.Turtle画方格函数4.开始生成数组并调用Turtle画图 二、什么是&#xff08;BFS&#xff09;广度优先算法&#xff1f;广度优先算法实现步骤1.引入库2.初…

【工具篇】Unity迷宫地图生成器MazeSpawner随机迷宫信手拈来

目录 一.迷宫生成效果 二.使用流程 三.使用场景 四.源码地址 一.迷宫生成效果 二.使用流程 1.导入后结构目录如下,打开prefab文件夹找到MazeSpawner放进场景里面

C++实现随机生成迷宫地图自动完成寻径

#include<iostream> #include<stack> #include<vector> using namespace std;template<class T> class Maze { public:Maze( //默认参数值pair<int, int> initSize make_pair(15, 17),pair<string, string> initStyle m…

Python 制作迷宫游戏(一)——地图

Python 制作迷宫游戏&#xff08;一&#xff09;——地图 序 作为一个迷宫类的游戏&#xff0c;其最重要的是什么&#xff1f;当然是它的地图啦♪(∇*) 那么我们又该如何制作一张迷宫地图呢⊙(・◇・)&#xff1f; 很显然&#xff0c;我们不可能一张张自己画吧 网络上常见的迷…

三套简单的迷宫地图生成方案

地图基础 地图的形式很多&#xff0c;这里我使用的地图是以tile块为单位分割的地图&#xff0c;地图上的tile块形式很多&#xff0c;但主要分成三种&#xff1a; A&#xff1a;陆地&#xff0c;可以在上面分布一些角色啦物件啦&#xff1b; B&#xff1a;过渡&#xff0c;根据物…

SenticNet情感词典介绍

在进行情感分析时&#xff0c;一个好的情感词典能够让我们的工作事半功倍&#xff0c;较为出名的情感词典有SentiWordNet&#xff0c;General Inquirer等&#xff0c;这篇博客将介绍另外一个出色情感词典&#xff0c;SenticNet。 简介 当谈论SenticNet时&#xff0c;我们正在…

中文金融领域情感词典构建

2019年10月4日-6日 Python爬虫与文本分析工作坊 & 课题申报高级研修班 这篇文章是公众号关注者郝童鞋今早发给我的&#xff0c;在此谢谢郝童鞋。 文章基于简单算法和人工判断&#xff0c;使用多阶段剔除法&#xff0c;构建了 中文金融情感词典CFSD&#xff08;ChineseFinan…

《学术小白的学习之路 02》情感分析02 之基于大连理工情感词典的情感分析和情绪计算

本文主要是学习参考杨秀璋老师的博客,笔记总结。 原文链接 文章目录 书山有路勤为径&#xff0c;学海无涯苦作舟原文链接一.大连理工情感词典二、七种情绪的计算2.1 pandas读取数据2.2 导入大连理工大学中文情感词典2.3 统计七种情绪的分布情况2.4 增加中文分词词典和自定义的停…

中文情感词典的构建

首先&#xff0c;国外英文的情感分析已经取得了很好的效果&#xff0c;得益于英文单词自身分析的便捷性与英文大量的数据集 WordNet。但由于中文的多变性&#xff0c;语义的多重性与数据集的缺乏&#xff0c;使得国内的情感分析暂落后于国外。本文将记录博主在项目中构建情感词…

基于情感词典的网络文本情感倾向分类模型

目录 前言一、模型构建1.归类2.判定3.输出 二、代码实现三、结果展示 前言 文本情感倾向性分析&#xff08;也称为意见挖掘&#xff09;是指识别和提取原素材中的主观信息&#xff0c;并对带有感情色彩的文本进行分析处理和归纳推理的过程。主要用于实时社交媒体的内容&#xf…

使用SO-PMI算法构建行业/专业情感词典

文章目录 1. 情感词典内容2. 情感倾向点互信息算法&#xff08;SO-PMI&#xff09;算法点互信息算法 PMI情感倾向点互信息算法 SO-PMI 3. 构建情感词典1. 导入项目2. 构建情感种子词3. 使用TF-IDF方便构建情感种子词4. 构建专业词典的效果与使用方法5. 其他说明 1. 情感词典内容…

在微雕中使用的电脑设计

需求是我们要在铜器上复刻很小的凹印,可以选用的技术方案还是很多:激光雕刻,篆刻、钢印。 激光雕刻有利有弊,前期复制是最方便的,激光雕刻有专门的设计软件,可以很轻松的把自己的图案运用到机器上去。制作和时间的成本都非常的低,但是激光对金属的雕刻有一个大大的缺点…

闲人闲谈PS之四十二——顾问的“禁忌之地”—制造能力计划

惯例闲话&#xff1a;上个月有幸成为乐老师乐谈IT系列培训课程的讲师&#xff0c;分享主题是&#xff0c;PS在装备制造和工程行业的应用。虽然培训规模不是很大&#xff0c;但是闲人很有信心&#xff0c;至少在小范围之内&#xff0c;参与培训的听友人来说&#xff0c;PS一直以…