迷宫生成


title: MazeGeneration
tags: default
date: 2019-09-11 10:13:31


迷宫生成

N*N的网格,按照预设的路线,生成仅有此唯一解的迷宫。迷宫可上下左右四个方向移动,每个网格都有颜色,必须按照红-黄-蓝-绿(颜色种类可预设)的顺序走。

网格节点

  • 节点的颜色(Type)

  • 节点的行列名字(Name), "Mesh_2_1"第2行第1列节点

  • 是否被访问过(IsVisited)

  • 父节点(MeshNode)

    class MeshNode
    {
        public int Type { get; set; }
        public string Name { get; set; }
        public MeshNode PreNode { get; set; }
        public bool IsVisited { get; set; }
        public MeshNode(int type, string name)
        {
            Type = type;
            Name = name;
            PreNode = null;
            IsVisited = false;
        }
    }
    

算法实现

  • 构建一个N*N的迷宫,随机生成每个网格的Type.

  • 修改在预设路径上网格节点的Type.

  • 从预设路径的开始节点进行深度优先搜索.

    1.判断是否到终点,是则跳出

    2.对此节点获取临近节点,筛选临近节点中可以走的节点,没有可以走的就跳出

    3.通过筛选的节点,IsVisited设置为true, preNode设置为步骤2的节点,然后进行dfs,跳出dfs后IsVisited设置为false

  • 每次搜索到终点时,终点与起点是一条单向链表。将此路径保存起来.

  • 所有的路径收集完成后,是一个网格节点的集合。筛选出不在预设路径中的点.

  • 修改每个节点的Type.

  • 重复进行搜索所有的路径。如果只有一条路径,则跳出。如果还有则继续修改节点Type,重复搜索.

完整代码

using System;
using System.Collections.Generic;
using System.Linq;

class MeshNode
{
    public int Type { get; set; }
    public string Name { get; set; }
    public MeshNode PreNode { get; set; }
    public bool IsVisited { get; set; }
    public MeshNode(int type, string name)
    {
        Type = type;
        Name = name;
        PreNode = null;
        IsVisited = false;
    }
}

class MazeTools
{
    public int MazeSize { get; set; }
    public int TypesCount { get; set; }
    public List<MeshNode> MazeNodes = new List<MeshNode>();

    public MeshNode startMeshNode { get; set; }
    public MeshNode endMeshNode { get; set; }

    public List<string> AllRouters = new List<string>();


    public void initMeshData()
    {
        var size = MazeSize;
        var typesCount = TypesCount;
        Random random = new Random();
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                var node = new MeshNode(random.Next(typesCount), "mesh_" + i + "_" + j);
                MazeNodes.Add(node);
            }
        }
        modifyPresetMesh();

    }
    public List<MeshNode> getPresetMeshNodes()
    {
        string[] array = { "mesh_1_0", "mesh_1_1", "mesh_1_2", "mesh_1_3", "mesh_1_4", "mesh_2_4", "mesh_3_4", "mesh_3_3", "mesh_3_2", "mesh_3_1"};
        List<MeshNode> nodes = new List<MeshNode>();
        for (int i = 0; i < array.Count(); i++){
            nodes.Add(new MeshNode( i%TypesCount,array[i]));
        }
        return nodes;
    }
    public void modifyPresetMesh()
    {
        var mazeNodes = MazeNodes;
        var presetMeshNode = getPresetMeshNodes();
        foreach (var node in presetMeshNode)
        {
            var mazeNode = mazeNodes.Find(delegate (MeshNode meshnode)
            {
                return node.Name == meshnode.Name;
            });
            if (mazeNode != null)
            {
                mazeNode.Type = node.Type;
            }
        }
        Console.WriteLine("modifyPresetMesh ok!");
        startMeshNode = presetMeshNode.First();
        endMeshNode = presetMeshNode.Last();
    }

    public MeshNode getMeshNodeByName(string name)
    {
        return MazeNodes.Find(delegate (MeshNode meshnode)
        {
            return meshnode.Name == name;
        });
    }
    public List<MeshNode> getNeighbors(MeshNode node)
    {
        var name = node.Name;
        var arr = name.Split('_');
        int row = int.Parse(arr[1]);
        int col = int.Parse(arr[2]);
        var leftNode = getMeshNodeByName("mesh_" + row + '_' + (col - 1));
        var rightNode = getMeshNodeByName("mesh_" + row + '_' + (col + 1));
        var upNode = getMeshNodeByName("mesh_" + (row - 1) + '_' + col);
        var downNode = getMeshNodeByName("mesh_" + (row + 1) + '_' + col);
        var nodes = new List<MeshNode>();
        nodes.Add(leftNode);
        nodes.Add(rightNode);
        nodes.Add(upNode);
        nodes.Add(downNode);
        nodes = nodes.Where(n => n != null).ToList();
        return nodes;
    }
    public void getAllRoutes()
    {
        var node = startMeshNode;
        node.IsVisited = true;
        dfs(node);
        node.IsVisited = false;
        if (AllRouters.Count != 1)
        {
            Console.WriteLine("存在{0}条路径可以到达终点,正在尝试修正!", AllRouters.Count);
            reviseRoutes();
            resetData();
            getAllRoutes();
        }
        else
        {
            Console.WriteLine("done!");
        }
    }

    public void resetData()
    {
        MazeNodes.ForEach(node =>
        {
            node.IsVisited = false;
        });
        AllRouters.Clear();
    }

    public void reviseRoutes()
    {
        var routes = AllRouters;
        var presetMeshnodes = getPresetMeshNodes();
        var array = new List<string>();
        routes.ForEach(route =>
        {
            var arr = route.Split('+');
            var list =
            arr
            .Where(name =>
            {
                return null == presetMeshnodes.Find(delegate (MeshNode n)
                {
                    return n.Name == name;
                });
            })
            .ToList();
            array.AddRange(list);
        });
        array
        .Distinct()
        .ToList()
        .ForEach(name =>
        {
            var node = getMeshNodeByName(name);
            Random random = new Random();
            var newType = random.Next(TypesCount);
            var oldType = node.Type;
            newType = newType != oldType ? newType : getNextType(node);
            node.Type = newType;
            Console.WriteLine("修正节点{0}Type: from {1} to {2}", node.Name, oldType, newType);
        });
        Console.WriteLine("修正节点完成,准备进行测试...");
    }

    public int getNextType(MeshNode node)
    {
        var type = node.Type;
        return (type + 1) % TypesCount;
    }

    public void addPath(MeshNode node)
    {
        string route = node.Name;
        while (node.PreNode != null)
        {
            route = route + '+' + node.PreNode.Name;
            node = node.PreNode;
        }
        AllRouters.Add(route);
    }

    public void dfs(MeshNode node)
    {
        if (node.Name == endMeshNode.Name)
        {
            addPath(node);
            return;
        }
        var nextType = getNextType(node);
        var neighbors = getNeighbors(node);
        neighbors
        .Where(neigh => !neigh.IsVisited)
        .Where(neigh => neigh.Type == nextType)
        .ToList()
        .ForEach(neigh =>
        {
            neigh.IsVisited = true;
            neigh.PreNode = node;
            dfs(neigh);
            neigh.IsVisited = false;
        });


    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值