产生类迷宫的最长路径算法


10

我有一个由房间组成的基于网格的简单地图,像这样(A =入口,B =出口):

   0 1 2 3
  #########
0#B######
  #########
1#####
  #########
2###
  ###
3###
  #########
4#####
  #########
5 ### A#
  ####
6 ####
  #########

而且我一直努力尝试制定一种合适的算法来在房间之间创建门的路径,这样玩家必须先找到大部分地图,然后才能找到出口。

换句话说,我试图找到从A到B最长路径

(我知道可以为非循环图解决此问题;但是,在这种情况下,可能存在循环。)

编辑:另一个示例,其中使用洪水填充来连接房间,而出口被选为距离入口最远的房间:

   0 1 2 3
  #########
0#B##
  ##-#####
1#| ##
  #####
2 #####
  ###-#-###
3#| ###
  #-#######
4 #A | #
  ###
5###
  ###
6###
  #########

请注意,出口的路径根本不是最长的路径。


如果您强迫玩家采取最长的路径,那实际上是在构建一条直线,看起来很复杂。这是不好的。
o0'。

这还不错(例如,这是铁路射击游戏类型的基础),但是您需要知道自己正在这样做,并设计游戏的其余部分以使其良好运行。

当关卡大多是线性的时,控制游戏的节奏也更容易。例如,可以在特别困难的怪物房间之后增加恢复室。如果没有一条主要道路,挑战和奖励的分配将是随机的。
找不到用户2010年

Answers:


11

我认为您正在以错误的方式进行操作。具有循环的图形中的最大路径在技术上是不确定的,因为如果循环位于起点和终点之间,则它是无限的。可能有一些聪明的方法可以扩展/限制最大路径的定义,但是我认为这不是最好的方法。

您并不是要为实际的长途路径建模(例如,机器人试图在地图上探索尽可能多的区域)。您只是想让玩家探索许多房间。

因此,让玩家有机会找到与目前探索的地图所占比例成比例的出口。假设在一个关卡上有X个房间,并且玩家角色探索了Y。下一次角色进入房间时,以f(Y,X)的概率将出口放置在那里。f的一个简单例子可能是(Y * Y)/(X * X)-例如,对于10个房间,最后一个房间的出口有100%的机会,在最后一个房间的下一个出口有81%的机会-仅有一个1%的机率在第一个房间。

您可以调整方程式,但是要使游戏感觉正确,甚至可以赋予玩家一些能力,使游戏更有可能产生。关键是,在角色实际进入房间之前不要生成出口。这种方法也不受玩家了解地下城生成算法的影响。即使玩家有奇怪的动作模式,例如骑士在NetHack中的跳跃或传送,他们也将不得不探索更多房间以找到出口。

如果必须静态生成出口,则可以对虚拟角色使用相同的想法。想象一下,从角色的位置开始填充,每次迭代移动一次单元。最后要填充的房间是出口所属的房间(实际上,最后要填充的单元是离玩家最远的单元)。但是,在这种情况下,玩家可以获得有关出口的更多信息-如果他们在左边,则最有可能在右边-并且如果他们可以传送,则实际上可以比正常的随机行走更快地到达那里。

最后,我刚刚完成了一个类似roguelike的活动,在该活动中,玩家角色在地图的另一侧产生了出口,然后随机游荡。地牢中的某些物品使它在地图上可见,但以更快地饿为代价。我没有做任何分析,但是绝对感觉就像我必须探索更多的地图才能找到它,并且它赋予了关卡独特的感觉。


只要玩家不注意,动态生成似乎是一个不错的主意。否则我认为他们会觉得很受骗。不过,我喜欢洪水填满的想法。
找不到用户2010年

2
好吧,从某种意义上说,您的整个建议都在欺骗玩家。不要怪我完善数学不需要世界模型。;)但是您可以使用设计技巧使它变得更可口-例如,出口被放在先验位置,但是使用它所需的关键是通过我描述的方法生成的,或者被放置在仅在探索X后才产生的怪物上房间/杀死X个怪物,或打开门需要翻转X开关,每个房间中一个,等等...

我尝试了一种洪水填充方法。它很好地连接了每个房间并产生了较短的分支,但是即使出口是最后访问的节点(或者在我的实现中是最远的节点),它实际上也不会产生到出口的最长路径。(将示例添加到我的问题中)
找不到用户

我全都喜欢基于按键/开关的迷宫。用树来实现这种事情似乎更容易,因为如果您有两个分支,则可以检测到哪个分支通向出口,将其阻塞,然后将钥匙放在另一个分支中。
找不到用户2010年

但是我确实承认我认为这是一个“从A到B”的寻路问题是错误的。我意识到找到退出是算法的结果而不是目标,这更有意义。
找不到用户2010年

6

一种可能的替代方法是使用Prim / Kruskal创建一个(最大?)生成树(以消除周期),并在生成树上应用传统的最长路径算法。

但是,我担心生成树算法会倾向于创建死胡同的分支,从而迫使玩家不断回溯。

编辑:使用基于Kruskal的算法并将出口放置在最长分支的末尾的结果:

   0 1 2 3
  #########
0 #A | #
  ######-#
1###
  ####
2 ####
  ####
3 ####
  ###-#####
4#| #
  #-#####-#
5#####
  #-#######
6##B#
  ##-#
7#| #
  #########

1
我也想建议Primm :-),+1,我认为回溯也是很多游戏的重要组成部分...检查暗黑破坏神2
Mr.Gando 2010年

2

这里有一些玩弄的东西:

Connect each room with a door to another room.
N = 0.75*TotalNumberOfRooms
Until (pathSize > N) {
  Use A* pathing to get a path from A to B. (G being size of room, or # of monsters)
  if (pathSize < N) remove a connection/door
  if (noPath) choose a different door/connection
  if (room.doors < 1) choose a different door/connection
}

我会沿着路径随机移除门,否则您最终在出口处只有1个门,而在开始时却有成千上万个门。

我认为这O(n^2)对于大型地图来说不是很好。


原则上是一个非常优雅的解决方案。下次,在尝试复杂的技术之前,我应该尝试考虑这样的事情。
找不到用户2010年

好吧,也许优雅,但这将成为处理器生猪。O(n ^ 2)在大型地图上无法很好地缩放。
Stephen Furlani 2010年


1

我相信您已经有了不错的答案,但这是我为问题提供的0.02美元的理论解决方案。

您想要的不是最长的路径,而是最长的最短路径。考虑到考虑到到达房间的最短路径,您需要最远的房间。这听起来可能令人困惑,但是它很容易计算。

  1. 从您的起居室开始。标记每个邻居1。它们与起始房间的距离为1。
  2. 对于标记为1的每个房间,请访问其每个未标记的邻居并标记为2。它们与起点的距离为2。
  3. 继续直到您覆盖了所有房间。人数最多的房间距离起点最远。

计算实际的最长路径(不会花很长时间说10个房间)将无法正常工作,因为您无法使播放器采取最长的路径。因此,最好将入口和出口放在彼此相距最远的两个房间中。要找到此位置,请计算随机房间中最远的房间。然后,从那个房间找到最远的房间。这称为查找图的直径,请谷歌搜索。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.