Java路径发现益智游戏

Java路径发现益智游戏,java,algorithm,Java,Algorithm,我需要一些建议,我可能需要采取的方法来解决一个游戏问题,这是一个难题(NxN),这个难题由正数组成,并存储在一个二维数组中。出于过于简单的原因,我将列出一个简单的例子 2 1 2 2 1 3 2 1 1 0 2 1 3 1 2 0 所以起点是(0,0)=>2,目标位置是(3,3)=>0 阵列位置中的数字告诉您移动的距离。(0,0)=>2可以移动到(0,2)或(2,0)等位置(允许向左、向右、向上或向下移动) 所以你最终得到了这样一个解,例如(0,2)=>(2,2)=>(2,0)=>(3,0)=

我需要一些建议,我可能需要采取的方法来解决一个游戏问题,这是一个难题(NxN),这个难题由正数组成,并存储在一个二维数组中。出于过于简单的原因,我将列出一个简单的例子

2 1 2 2
1 3 2 1
1 0 2 1
3 1 2 0
所以起点是(0,0)=>2,目标位置是(3,3)=>0 阵列位置中的数字告诉您移动的距离。(0,0)=>2可以移动到(0,2)或(2,0)等位置(允许向左、向右、向上或向下移动) 所以你最终得到了这样一个解,例如(0,2)=>(2,2)=>(2,0)=>(3,0)=>(3,3)


所以我的问题是我应该研究什么样的算法,你们中是否有人做过类似的事情

这里有很多解决方案:

如果存在,前两个将为您提供最佳解决方案。如果启发式选择得当,A*通常比Dijkstra快。广度优先还将为您提供最佳实现。深度优先可能会为您提供此问题的非最优解决方案

A*和Djisktra之间的主要区别在于A*定义了一个启发式,即一个函数,该函数试图估计一个移动是否优于另一个移动

深度优先和广度优先的主要区别在于它们探索解决方案空间的顺序。广度优先将首先寻找长度为1的所有解决方案,然后是长度为2的所有解决方案,以此类推,而深度优先将全面探索整个路径,直到它无法进一步或找到解决方案为止

A*和Dijkstra通常以命令式风格实现,可能比其他两个更复杂,尤其是A*。广度优先也很自然地用祈使式表达。深度优先通常以递归方式表示,如果您的解决方案可能超过数千个移动的长度,这可能会成为一个问题(取决于堆栈的大小,您通常只能进行7-10k递归调用,然后才能获得
StackOverflowerError

总而言之:

  • A*通常是下面列出的算法中效率最高的
  • A*是最难实现的
  • Dijkstra是a*的特例,具有类似的性能,但可能效率较低
  • 广度优先易于实施,并且能够适应长期解决方案
  • 深度优先很容易实现,但如果递归实现,它会受到最长路径长度的限制
  • 除深度优先外,所有这些算法都保证了最优解
代码示例:


我在我的一个存储库中找到了这个。可能会有所帮助。

我在Object Pascal(Delphi)中实现了一些网格搜索算法(最佳优先、广度优先、深度优先),如果这是一个经典的网格搜索,您可以很容易地适应Java:

您可以在此处尝试GridSearchDemo应用程序,以了解在具有起始点和目标点以及各种网格单元中的障碍物的网格中搜索时这些算法的行为(您可以设置它们):

一般来说,我更喜欢A*算法,它是最佳优先算法()的一个示例


在你的例子中,这实际上不是一个网格,而是一个图形,因为你似乎有到其他单元格的跳转链接(或者至少这是你在问题中解释数字的方式,尽管你一开始称它为“多远”)

我用java编写了一个程序来解决这个问题。它使用带有启发式函数Manhatten和hamming的*-算法。这取决于此人是否使用汉明距离或曼哈顿距离,但曼哈顿距离更好

以下是我的java代码:


顺便说一句,这不是一个简单的方法,许多问题都无法解决。

对于这样一个小数组,我想可以通过递归强制执行它。@luckydog32问题提到了这是一个简单的示例,目的是为了澄清您如何实现*?我不知道如何定义一个有效的启发式函数。是的,只是在这里列出了一些选项,我并没有把更多的想法放在其中。离目标很近这一事实并不能保证我们真的能到达那里,但它可能仍然有助于加速通常,a*的启发式是到目标的直线距离(忽略任何障碍物),特别是,如果这是一个导航问题是的,你可以应用*并且我已经用manhatten distance和hamming做了。@Dici:我想知道BFS在这里是如何工作的,因为它通常在距离不变的情况下使用,但在OP情况下不是。DFS解决方案几乎类似于暴力。