我想用Java编写一个程序来解决给定状态下的“解锁我”游戏(假设给定了初始状态的方块和棋盘作为输入),我的目标是使用A*算法给出解锁红色方块所需的最小移动次数。
我在考虑为这个问题设计一个好的启发式方法,我想到了曼哈顿距离,我认为这是一个不错的选择,但我不确定是否有更好的方法。另一个问题是我不知道如何通过编程找到给定状态的可能下一个状态。我希望能在这个帖子中得到你的帮助,获得一些好的想法!
如果你不熟悉这个游戏,这里有一个链接:
回答:
这种特定的谜题对人来说很难,但对计算机来说通常不难。因此,如果你之前没有实现过类似的东西而不是使用A*,我建议使用广度优先搜索或深度优先搜索。
广度优先搜索(BFS):广度优先搜索的数据结构相对简单——你可以使用一个双端队列,从前端移除,从后端添加。你可能需要检查重复,这需要使用类似哈希表的东西来避免多次生成相同状态。
深度优先搜索(DFS):对于深度优先搜索,你将使用深度优先迭代加深。也就是说,你会限制DFS最多进行1次移动,然后最多2次移动,等等,直到找到解决方案。这仍然保证了最优解。你在DFS中唯一需要做的是避免生成回到父节点的移动,因为这会使搜索效率大大降低。
生成移动:要生成移动,你需要考虑谜题中的每个棋子以及它可能移动的四个方向(上/下/右/左)。如果棋子旁边的单元格都是空的,那么它就可以朝那个方向移动。移动通常在数据结构中定义为一个棋子加上一个方向。通常你可以编写一个函数,返回合法移动的列表,然后在搜索过程中应用这些移动。如果你知道上一个移动,那么你可以轻松避免应用相反的移动(因为它将是相同的棋子但相反的方向)。
启发式方法:如果你想使用A*,每个棋子的曼哈顿距离会很好。如果你想要比这更好的方法,你可以解决从谜题中移除2-3个棋子的谜题,并使用那个更简单谜题的解决方案距离作为完整谜题的启发式方法。但正如我上面所说,这些谜题通常非常简单,不需要强有力的启发式方法来解决它们。