随机地图算法(优化地牢算法) - Go语言中文社区

随机地图算法(优化地牢算法)


1.前言

如果在阅读此篇文章的时候,不了解地牢算法的建议去看一下,这里不介绍地牢算法了,只是谈论一下地牢算法不好的地方,如何去扩展和优化地牢算法,下面是地牢算法的链接:https://www.cnblogs.com/sufferingStriver/p/8834862.html

2.地牢算法缺点

看过地牢算法以后,现在提出几个需求,比如必须要生成有n个房间的一个地图,但是地牢算法会在计算的时候将不满足条件的房间去掉,还有比如有一个要求有一些房间必须只有一个入口,地牢算法在这个时候是没有办法搞定这种需求,因为最小生成树是没有办法解决这种特殊的点,所以需要想办法拓展一下。

3.优化和拓展算法

这里需要优化分散房间位置的算法,最先想到的方法就是一个随机区域之内随机放n个房间,如果和之前设置的房间位置碰撞了就重新随机,这样的话怎么去判断随机区域大小,如果随机区域直接最大,之前不管多少房间这样一定不会重叠的,但是这样指定不行,房间密度会太散了,一个房间到另外一个房间可能太远了,这样指定不行,所以怎么样可以判断最佳的随机区域大小?第一个想法就是所有房间宽加起来就是随机区域的最大宽,所有高加起来是就是随机区域的最大高,如图所示:

 

但是这样的随机区域就是最佳吗?这个最坏情况也是一定可以放下所有房间的,可以看出来这个区域也太大了,这样需要想办法优化这个随机区域大小,于是经过一番思考,可以这样优化随机区域的大小,就是找到n房间中最大宽度值和最大高度值,上面的图最大高度是3房间,最大宽度是2房间,如下图所示:

房间1放在(MaxWidth,MaxHeight),房间2,3放在(2*MaxWidth,2*MaxHeight),房间4,5,6放在(3*MaxWidth,3*MaxHeight),房间7,8,9,10放在(4*MaxWidth,4*MaxHeight),房间11,12,13,14,15放在(5*MaxWidth,5*MaxHeight),这样就算出现最坏情况,也没有问题的,慢慢增加随机区域,为什么一定可以容下所有房间?大家可以自己思考一下,代码如下:

    bool SetRandomRoom(int i, int MaxWidth, int MaxHeight,uint Count)
    {
        int x = Random.Range(0, MaxWidth);
        int y = Random.Range(0, MaxHeight);

        Rooms[i].SetLocation(x, y);
        if(Count == 0x0fff)//栈溢出保护
            return false;

        for (int j = 0; j < i - 1; j++)
        {
            if (isOverLap(Rooms[i], Rooms[j]))//如果重叠
            {
                SetRandomRoom(i, MaxWidth, MaxHeight, Count+1);
                break;
            }
        }
        return true;
    }

    void SetMapPoint()
    {
        int i,j,k = 0,k1=1,MaxHeight=0,MaxWidth=0,MaxWidthCell=0,MaxHeightCell=0;
        for (i = 0; i < Rooms.Count; i++)//打散房间
        {
            for (j = i + 1; j < Rooms.Count; j++)
            {
                if (Random.Range(0, 2) == 1)
                    SwapRoomInfo(i, j);                
            }
            if (MaxWidthCell < Room[i].Rect.Width)
                MaxWidthCell = Room[i].Rect.Width;
            if (MaxHeightCell < Room[i].Rect.Height)
                MaxHeightCell = Room[i].Rect.Height;
        }

        for (i = 0; i < Room.Count; i++)
        {
            if (k == i)//控制房间密度
            {
                k = k + k1;
                k1 = k1 + 1;
                MaxWidth = MaxWidth + MaxWidthCell;
                MaxHeightCell = MaxHeight + MaxHeightCell;
            }
            if (SetRandomRoom(i, MaxWidth, MaxHeight, 0) == false)
            {
                //TODO 防止意外(回滚所有随机)
                k = 0;k1 = 1;
                MaxWidth = MaxHeight = 0;
                i = 0;
            }
        }          
    }

这样就可以把房间位置散开,而且比较密集。之后最小生成树连接这些点,然后如何去添加只有单个入口的房间呢,需要在这个最小生成树里用贪心算法去添加这些点,随机这些特殊点(确保这些和之前的房间和路线碰撞),然后连接这些特殊点,但是这里有一个问题,因为随机函数的问题,可能多次随机都有无法找到连接的路线,这样的话尝试了一定次数之后,这样我们需要遍历随机范围将将剩余的特殊点都连接进去

4.终结

如果有更好的方法或者疑问,大家可以留言讨论一下,如果需要demo工程的小伙伴,请大家留言一下~,笔者会抽空用unity写一个demo出来提供下载。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_37920739/article/details/100183861
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-18 06:55:07
  • 阅读 ( 1173 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢