Java迷宫最短路径二维int数组
我目前陷入一个项目中。 我的目标是使用 Dijkstra 算法。
我知道我从点 (0,0) 开始,查看起点旁边的两个节点,然后首先移动到最小的节点,然后查看周围的节点。我的迷宫是随机的,但为了方便开始,可以说以下是我的迷宫。
我将从 (0,0) 开始,并希望在 (9,9) 结束,这些数字是危险级别,我们的目标是最安全的路径,而不是最短的路径。
我需要推动才能理解如何设置它。 我知道我需要一个列表或一条路径来保持我所在的位置和我想要查看的位置。但我不知道如何在java中做到这一点。
import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class solver {
/**
* @param args
*/
public static int[][]maze;
public static int[][]openlist;
public static int[][]closed;
public static int[][]copy;
public static int danger;
public static int size=100;
static int Max=9;
static int Min=0;
public static List path = new ArrayList();
public static void main(String[] args) {
// TODO Auto-generated method stub
maze = new int[size][size];
openlist = new int[size][size];
closed = new int[size][size];
copy = new int[size][size];
filler(maze);
copy=dijstkra();
printer(maze);
//printer(copy);
EDSfAO(maze,0,0);
printer(openlist);
printer(copy);
}
private static Boolean notwall(int i, int j){
if((i>maze.length-1)||(j>maze.length-1)||(i<0)||(j<0))
{return false;}
return true;}
private static int[][] dijstkra(){
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
copy[i][j]=100000000;
}}
copy[0][0]=0;
return copy;
}
private static void EDSfAO(int[][] maze,int i,int j){
int min=100000000;
int holdx = 0;
int holdy = 0;
openlist[i][j]=1;
danger=copy[i][j];
if(i==maze.length-1&&j==maze.length-1){
printer(copy);
for(holdx=0;holdx<path.size();holdx++){
System.out.print(path.get(holdx));
}
}
else{
if(notwall(i+1,j)&&openlist[i+1][j]!=1){
copy[i+1][j]=danger+maze[i+1][j];
} if(notwall(i,j+1)&&openlist[i][j+1]!=1){
copy[i][j+1]=danger+maze[i][j+1];
} if(notwall(i,j-1)&&openlist[i][j-1]!=1){
copy[i][j-1]=danger+maze[i][j-1];
} if(notwall(i-1,j)&&openlist[i-1][j]!=1){
copy[i-1][j]=danger+maze[i-1][j];
}
for(int x=0;x<maze.length;x++){
for(int y=0;y<maze.length;y++){
if(openlist[x][y]!=1){
if(min>copy[x][y]){
min=copy[x][y];
holdx=x;
holdy=y;
}
}
}}
moveToPosition(holdx,holdy);
}
}
private static void moveToPosition(int x, int y) {
openlist[x][y]=1;
path.add("("+x+","+y+")");
openlist[x][y]=1;
EDSfAO(maze,x,y);
}
private static void printer(int[][] maze) {
// TODO Auto-generated method stub
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
System.out.print("["+maze[i][j]+"]");
}
System.out.println();
}
}
public static void filler(int[][] maze){
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
//If i=0 AND j=0 then maze[0][0]= 0(start) OR i= maze.length-1 AND j= maze.length-1 then maze[maze.length][maze.length]=0
if((i==0 && j==0) || (i==maze.length-1 && j==maze.length-1)){
maze[i][j]=0;
}else{
maze[i][j]=Min + (int)(Math.random() * ((Max - Min) + 1));
}
}
}
}
}
迷宫没有墙壁相连,所有的盒子都是房间。 我一直在努力解决这个问题,而且我确实需要推动。 我看过很多关于 dijstkra 算法的视频,但我现在真的迷失了。
我添加了一个数组,我通过将节点设为 100000000 来保持其中的危险,但起始节点 (0,0) 为 0。
有人可以帮助我完成后续步骤吗?我知道这是作业,但我已经没时间了,真的需要一些指点。
更新:
好的,我已经可以正常工作了。它打印它所采用的路径,但如果它找到更好的路径,它会打印两者,有人可以帮助我解决这个问题。
如果我使用 100X100 元素,它也会崩溃,有人能告诉我为什么吗? 这是最后一个真正的“编程作业”。正如您所料,这将涉及图表(有一些变化);但当然,也会涉及一些问题的解决。 说明
想象一个“地下城游戏”,其中所有房间都布置在正方形环境中的完美网格中。每个房间都有一个生物,会造成一定程度的危险,范围从 0(无害)到 9(谨慎的做法是避免)。目标是找到一条从头到尾穿过地牢的路径,从而最大限度地减少总体危险。
每个房间,除非在边界处,仅存在于上、下、左、右方向(无对角线)。入口在左上角 (0,0),出口在右下角 (n-1, n-1)。
以房间坐标路径的形式列出从开始到结束必须遍历的所有“房间”。
例如:
(0,0) (1,0) (2,0) (2,1) (2,2) (2,3) (3,3) (4,3) (4,4)
总危险 = 11 输入
输入文件将由 100 行 100 个数字(0-9)组成。 (是的,10,000 间房间已经很多了,但幸运的是,我们勇敢的旅行者每次出门都会带上去年节日礼物交换中收到的便携式计算机和一套适用于各种场合的电子数据集;它可能是重新赠送的。 )*
*对于此作业,您必须生成自己的测试数据。这就是我不参加这种聚会的原因... 输出
程序应将输出写入文件(采用上面所示的格式,包括“总危险”输出)。 谢谢。
UPDATE2:我在编码中发现了一个错误,
if(min>copy[x][y]){
min=copy[x][y];
holdx=x;
holdy=y;
}
这将使它测试给定点上的每条路径,我的最短路径比其他路径大,我该如何解决这个问题?
我缺少什么? 更新我完成了这篇文章,感谢您提供的帮助很少。
I am currently stuck on a project.
My aim is to use Dijkstra's algorithm.
I understand that I start at point (0,0) I look at the two nodes next to the start point and then I move to the smallest first and look at the surrounding nodes. My maze is random but to make it easy to start lets say the following is my maze.
I will start at (0,0) and want to end at (9,9) the numbers are the DANGER level and we aim for the safest path not really the shortest.
I need a push to understand how to set this up.
I know I need a list or a path to keep where I am and where I want to look. but I don't know how to do that in java.
import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class solver {
/**
* @param args
*/
public static int[][]maze;
public static int[][]openlist;
public static int[][]closed;
public static int[][]copy;
public static int danger;
public static int size=100;
static int Max=9;
static int Min=0;
public static List path = new ArrayList();
public static void main(String[] args) {
// TODO Auto-generated method stub
maze = new int[size][size];
openlist = new int[size][size];
closed = new int[size][size];
copy = new int[size][size];
filler(maze);
copy=dijstkra();
printer(maze);
//printer(copy);
EDSfAO(maze,0,0);
printer(openlist);
printer(copy);
}
private static Boolean notwall(int i, int j){
if((i>maze.length-1)||(j>maze.length-1)||(i<0)||(j<0))
{return false;}
return true;}
private static int[][] dijstkra(){
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
copy[i][j]=100000000;
}}
copy[0][0]=0;
return copy;
}
private static void EDSfAO(int[][] maze,int i,int j){
int min=100000000;
int holdx = 0;
int holdy = 0;
openlist[i][j]=1;
danger=copy[i][j];
if(i==maze.length-1&&j==maze.length-1){
printer(copy);
for(holdx=0;holdx<path.size();holdx++){
System.out.print(path.get(holdx));
}
}
else{
if(notwall(i+1,j)&&openlist[i+1][j]!=1){
copy[i+1][j]=danger+maze[i+1][j];
} if(notwall(i,j+1)&&openlist[i][j+1]!=1){
copy[i][j+1]=danger+maze[i][j+1];
} if(notwall(i,j-1)&&openlist[i][j-1]!=1){
copy[i][j-1]=danger+maze[i][j-1];
} if(notwall(i-1,j)&&openlist[i-1][j]!=1){
copy[i-1][j]=danger+maze[i-1][j];
}
for(int x=0;x<maze.length;x++){
for(int y=0;y<maze.length;y++){
if(openlist[x][y]!=1){
if(min>copy[x][y]){
min=copy[x][y];
holdx=x;
holdy=y;
}
}
}}
moveToPosition(holdx,holdy);
}
}
private static void moveToPosition(int x, int y) {
openlist[x][y]=1;
path.add("("+x+","+y+")");
openlist[x][y]=1;
EDSfAO(maze,x,y);
}
private static void printer(int[][] maze) {
// TODO Auto-generated method stub
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
System.out.print("["+maze[i][j]+"]");
}
System.out.println();
}
}
public static void filler(int[][] maze){
for(int i=0;i<maze.length;i++){
for(int j=0;j<maze.length;j++){
//If i=0 AND j=0 then maze[0][0]= 0(start) OR i= maze.length-1 AND j= maze.length-1 then maze[maze.length][maze.length]=0
if((i==0 && j==0) || (i==maze.length-1 && j==maze.length-1)){
maze[i][j]=0;
}else{
maze[i][j]=Min + (int)(Math.random() * ((Max - Min) + 1));
}
}
}
}
}
The maze is connected with no walls all the boxes are rooms.
I have been trying to work on this for time and I could really use a push.
I have watched a lot of videos about dijstkra's algorithm I am just currently really lost.
I added a array that i keep the danger in it starts by making ever node 100000000 but the starting node (0,0) is 0.
CAN someone help me with the next steps I understand it's homework but I am running out of time and really need some pointers.
UPDATE:
OK so I have it workingish. It prints the path it takes but if it finds a better path it prints both can someone help me fix this.
Also it breaks if i do 100X100 element can someone tell me why?
This is the last of the real "programming assignments". As you may expect, this will involve graphs (with a twist); but of course, there will be some problem solving involved as well.
Instruction
Imagine a “dungeon game” where all the rooms are laid out in a perfect grid with in a square environment. Each room has a creature posing some degree of danger ranging from 0 (harmless) to 9 (avoidance would be prudent). The object is to find a path through the dungeon from start to end which minimizes the overall amount of danger.
Each room, unless at boundary, only has exists in the up, down, left, right directions (no diagonals). The entrance is at the upper-left (0,0) and the exit is at the lower right (n-1, n-1).
List all of the “rooms” which must be traversed, in the form of a path of room coordinates, from the start to finish.
For example:
(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(3,3)
(4,3)
(4,4)
Total danger = 11
Input
The input file will consist of 100 rows of 100 digits, 0-9. (Yes, 10,000 is be a lot of rooms, but luckily, our intrepid traveler never leaves home without a portable computer and a collection of Electronic Data-Sets for All Occasions received in last year's holiday gift exchange; it was probably re-gifted.)*
*For this assignment, you'll have to generate your own test data. This is why I don't go to these kinds of parties...
Output
The program should write the output to a file (in the format illustrated above, including the "total danger" output).
Thanks.
UPDATE2: i found an error in my coding I have
if(min>copy[x][y]){
min=copy[x][y];
holdx=x;
holdy=y;
}
This will make it test every path that is there at a given point my shortest path is bigger then the other path how do I fix this?
What I am I missing?
UPDATE I finished this thanks for the VERY LITTLE help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一旦您了解了如何使用 Dijkstra 算法,您就可以使用包含指示您之前位置的数字对的
ArrayList
:然后您可以编写一个
Point
类来简单地包装两个 < code>int 基元、x
和y
。因此,当您移动时,您可以使用:
至于学习如何实际使用算法,我认为这在某种程度上是您家庭作业的重点,我们不想破坏您的乐趣!
维基百科关于算法的文章相当有用,尽管我感觉你的课堂笔记也会有所帮助。
维基百科上的 Dijkstra 算法
Once you understand how to use Dijkstra's algorithm, you can use an
ArrayList
containing pairs of numbers that indicate your previous positions:You can then write a
Point
class that simply wraps twoint
primitives,x
andy
.So when you move, you can use:
As for learning how to actually employ the algorithm, I think that's somewhat the point of your homework, and we don't want to spoil your fun!
The Wikipedia article on the algorithm is fairly useful, though I have a feeling your class notes will also help.
Dijkstra's algorithm on Wikipedia
我刚刚查看了关于 Dijkstra 算法 的维基百科文章。
一开始就天真地接近它。哎呀,把它当作“程序员的阅读理解”吧。在这种情况下,技巧是将二维数组映射到一组图节点。每个节点都需要“一个暂定距离值”。好吧,你的节点是由它们的 i,j 值定义的。做一些事情,这样你就可以在给定 i 和 j 的情况下获取/设置 tentative_distance_value 。
您需要标记节点是否被访问。同样的想法。
您需要一个“当前节点”。相同的想法,但更简单。
从技术上讲,您不需要维护运行算法的路径。如果你不这样做,你就必须弄清楚如何根据算法的结果构建它,但这当然是可能的。
I just looked at the wikipedia article on Dijkstra's Algorithm.
Just approach it naively at first. Heck, treat it as "programmer's reading comprehension." In this case, the trick is mapping your 2 dimensional array to a set of graph nodes. Every node needs "a tentative distance value". Ok, your nodes are defined by their i,j value. Make something so you can get/set a tentative_distance_value given an i and j.
You need to mark if a node is visited. Same idea.
You need a "current node." Same idea, but simpler.
Technically, you don't need to maintain a path to run the algorithm. You'll have to figure out how to construct it from the results of the algorithm if you don't, but it's certainly possible.
您的解决方案可以基于 Cormen、Leiserson、Rivest 和 Stein 所著的“算法简介”第二版中找到的算法。在第 24 章中,他们分析了“单源最短路径”算法,在 24.3 中,您有 Dijkstra。
我将在这里使用伪代码。您可以将下面的最小优先级队列替换为其他数据结构,例如 Java 中的映射。它不会很快,但会起作用,这可能是令人满意的第一次尝试。如果您愿意的话,我还有一个最小优先级队列的 Java 实现。
假设您有一个由二维数组表示的迷宫,如代码中所示:int[M][N] maze。第一个索引是行索引,第二个索引是列索引,从零开始。因此,行从 0 到 M-1,列从 0 到 N-1。值 maze[row][column] 表示与(行,列)处的房间相关的危险。我们需要一种方便的表示方法来获取迷宫中两个房间之间的权重,并了解哪些房间与特定房间相邻。
这个想法是压平数组并将每一行并排放置:row1、row2、...、rowM。然后我们可以给每个房间一个索引i。为了能够使用这个想法,我们需要在不同类型的坐标之间进行转换:(行,列)->我和我-> (行、列)。
假设 SIZE 是 M*N,即迷宫中的房间总数。
现在我们可以用危险值制作一个代表迷宫的邻接矩阵:int[SIZE][SIZE] adjacency_matrix,第一个索引是FROM,第二个索引是TO。在单元格中,我们找到从一个房间到另一个房间的成本或重量。请注意,给定一个特定的房间,只有几个房间与该房间相邻。从该房间无法到达迷宫中的其他房间。按照惯例,我们将使用最大的整数来表示,并使用常量 INFINITY。其他值代表危险,范围从 0 到 9。矩阵将是稀疏的,并且有一些技术可以对其进行优化。
当我们有一个房间位于 (r, c) 时,与它相邻的房间是什么?我们希望有一个索引向量可以直接在我们的算法中使用。如果我们不考虑迷宫边界,我们有:(r-1, c-1), (r-1, c), (r-1, c+1), (r, c-1) 、(r,c+1)、(r+1,c-1)、(r+1,c)和(r+1,c+1)。然后我们可以将 Convert_to_index 应用于每个,检查它们是否在 0..SIZE-1 范围内,并用它初始化矩阵。因此,例如,从 (r, c) 到 (r-1, c-1) 具有迷宫[r-1, c-1] 的成本或危险,并且从 (r-1, c-1) 到(r, c) 的成本为 maze[r, c]。但从 (r, c) 到另一个遥远的房间的成本为 10,它是不可到达的,反之亦然。
接下来,我们需要最短路径估计的向量估计(参见书第 585 页)和前驱向量(参见书第 584 页)。
从起始点到起始点的成本为 0。
初始化属于 MST(最小生成树)的顶点集
最小优先级队列 q 已初始化
作业已完成。我们在
前辈
中找到了我们的路径,在估计
中找到了成本。这可能有点过分了,A* 可能会更好。但我想使用 Dijkstra 是你作业的要求。如果你想探索 A*,我建议你看看 A* 初学者寻路 和 阿米特的 A* 页面。
You can base your solution on algorithms found in "Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein, 2nd Edition. In chapter 24 they analyze "single-source shortest paths" algorithm and in 24.3 you have Dijkstra.
I will use pseudo-code here. You could replace the min-priority queue below with another data structure like a map in Java. It won't be fast but it will work and that could be a satisfactory first try. I also have a Java implementation of a min-priority queue if you want.
Say you have the maze represented by a 2D array like in your code: int[M][N] maze. The first index is the row index and the second is the column index, zero-based. Thus going from 0 to M-1 for the rows and from 0 to N-1 for the columns. The value maze[row][column] represent the danger associated with the room at (row, column). We need a convenient representation to get the weight between two rooms in the maze and to know which rooms are adjacent to a specific room.
The idea is to flatten the array and put every row side by side: row1, row2, ..., rowM. Then we can give an index i to each room. To be able to use this idea we need to convert between different type of coordinates: (row, column) -> i and i -> (row, column).
Say SIZE is M*N, the total number of rooms in the maze.
Now we can make an adjacency matrix representing the maze with the danger values: int[SIZE][SIZE] adjacency_matrix, the first index is the FROM, the second is the TO. In a cell we find the cost or weight to go from one room to another. Note that given a specific room, there are only a few room that are adjacent to that room. The other rooms in the maze are not reachable from that room. By convention, we will use the biggest integer to indicate that and use the constant INFINITY. The other values represent danger and range from 0 to 9. The matrix will be sparse and there are techniques to optimize that.
When we have a room located at (r, c), what are the rooms adjacent to it ? We want to have a vector of indices to be used directly in our algorithm. If we don't take the maze borders into account, we have: (r-1, c-1), (r-1, c), (r-1, c+1), (r, c-1), (r, c+1), (r+1, c-1), (r+1, c) and (r+1,c+1). We could then apply convert_to_index to each of them, check they are in the range 0..SIZE-1 and initialize the matrix with that. Thus, e.g., going from (r, c) to (r-1, c-1) has a cost or danger of maze[r-1, c-1] and going from (r-1, c-1) to (r, c) has a cost of maze[r, c]. But going from (r, c) to another distant room has a cost of 10, it is unreachable and the inverse is true.
Next we need a vector estimates of shortest-path estimates (Cfr. book page 585) and a predecessors vector (Cfr. book page 584).
Going from the start to the start costs 0.
Initialize set of vertices that belong to the MST (minimum spanning tree)
The min-priority queue q is initialized
Job is done. We have our path in
predecessors
with the costs inestimates
.This might be overkill and A* might be better. But I guess that using Dijkstra was a requirement of your homework. If you want to explore A*, I suggest you take a look at A* Pathfinding for Beginners and Amit’s A* Pages.
我继续实现了 ccoakley 提到的算法。在下面找到部分代码,以帮助您找到正确的方向:
编辑:添加了缺失的位
I went ahead and implemented the algorithm as mentioned by ccoakley. Find below the partial code to help you in the right direction:
EDIT: added the missing bits