我有一个表示网格的矩阵,想找出对象可以移动到的所有可能位置.
一个对象只能水平或垂直移动.
假设下面的示例是我正在查看的网格,它表示为2d矩阵.对象是*,0是对象可以移动到的空白空间,1是对象不能跳过或继续前进的墙壁.
如果该对象只能水平或垂直移动,那么找到所有可能运动的最佳方法是什么?
我想打印一条消息,说:“该对象可以去9个地方.” 9是下面的示例,但是我希望它适用于以下网格的任何配置.所以我要做的就是给出*的当前坐标,这将给我它可以移动到的可能位置的数量.
需要注意的是,在计算中未考虑*的原始位置,因此对于下面的示例,该消息将显示9而不是10.
我有一个isaWall方法,可以告诉我该单元格是否为墙. isaWall方法在Cell类中.每个像元均由其坐标表示.我研究过使用BFS或DFS之类的算法,但是由于我不太熟悉算法,因此我不太了解如何在这种情况下实现它们.我曾考虑将Cells用作图的节点,但并不确定如何遍历图,因为从我在BFS和DFS网上看到的示例中,通常会有一个目标节点和源节点(源是*)的位置,但是在这种情况下,我实际上没有目的地节点.我真的很感谢您的帮助.
@H_502_18@00111110 01000010 100*1100 10001000 11111000
编辑:我检查了评论中推荐的网站,并尝试实现自己的版本.不幸的是,它没有用.我知道我必须扩展“边界”,并且我基本上只是将扩展代码翻译成Java,但仍然无法正常工作.该网站继续说明该过程,但就我而言,没有目标单元格可访问.我真的很感谢与我的案子有关的示例或更清晰的解释.
EDIT2:我还是很困惑,有人可以帮忙吗?
我不知道您的数据的确切结构,但是我假设您的地图是一个整数数组,并定义了一些基本功能(为简单起见,我将第一个单元格设置为2):
Map.java
@H_502_18@import java.awt.*; public class Map { public final int width; public final int height; private final Cell[][] cells; private final Move[] moves; private Point startPoint; public Map(int[][] mapData) { this.width = mapData[0].length; this.height = mapData.length; cells = new Cell[height][width]; // define valid movements moves = new Move[]{ new Move(1,0),new Move(-1,new Move(0,1),-1) }; generateCells(mapData); } public Point getStartPoint() { return startPoint; } public void setStartPoint(Point p) { if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point"); startPoint.setLocation(p); } public Cell getStartCell() { return getCellAtPoint(getStartPoint()); } public Cell getCellAtPoint(Point p) { if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point"); return cells[p.y][p.x]; } private void generateCells(int[][] mapData) { boolean foundStart = false; for (int i = 0; i < mapData.length; i++) { for (int j = 0; j < mapData[i].length; j++) { /* 0 = empty space 1 = wall 2 = starting point */ if (mapData[i][j] == 2) { if (foundStart) throw new IllegalArgumentException("Cannot have more than one start position"); foundStart = true; startPoint = new Point(j,i); } else if (mapData[i][j] != 0 && mapData[i][j] != 1) { throw new IllegalArgumentException("Map input data must contain only 0,1,2"); } cells[i][j] = new Cell(j,i,mapData[i][j] == 1); } } if (!foundStart) throw new IllegalArgumentException("No start point in map data"); // Add all cells adjacencies based on up,down,left,right movement generateAdj(); } private void generateAdj() { for (int i = 0; i < cells.length; i++) { for (int j = 0; j < cells[i].length; j++) { for (Move move : moves) { Point p2 = new Point(j + move.getX(),i + move.getY()); if (isValidLocation(p2)) { cells[i][j].addAdjCell(cells[p2.y][p2.x]); } } } } } private boolean isValidLocation(Point p) { if (p == null) throw new IllegalArgumentException("Point cannot be null"); return (p.x >= 0 && p.y >= 0) && (p.y < cells.length && p.x < cells[p.y].length); } private class Move { private int x; private int y; public Move(int x,int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } } }
单元格
@H_502_18@import java.util.LinkedList; public class Cell { public final int x; public final int y; public final boolean isWall; private final LinkedList<Cell> adjCells; public Cell(int x,int y,boolean isWall) { if (x < 0 || y < 0) throw new IllegalArgumentException("x,y must be greater than 0"); this.x = x; this.y = y; this.isWall = isWall; adjCells = new LinkedList<>(); } public void addAdjCell(Cell c) { if (c == null) throw new IllegalArgumentException("Cell cannot be null"); adjCells.add(c); } public LinkedList<Cell> getAdjCells() { return adjCells; } }
现在编写我们的DFS函数. DFS通过以下步骤递归地触摸每个可达单元一次:
>将当前单元格标记为已访问
>遍历每个相邻的单元格
>如果尚未访问该单元格,请DFS该单元格,并将与该单元格相邻的单元格数量添加到当前计数中
>返回与当前单元格1相邻的单元格数
您可以看到此here的可视化.使用我们已经编写的所有帮助程序功能,这非常简单:
MapHelper.java
@H_502_18@class MapHelper { public static int countReachableCells(Map map) { if (map == null) throw new IllegalArgumentException("Arguments cannot be null"); boolean[][] visited = new boolean[map.height][map.width]; // subtract one to exclude starting point return dfs(map.getStartCell(),visited) - 1; } private static int dfs(Cell currentCell,boolean[][] visited) { visited[currentCell.y][currentCell.x] = true; int touchedCells = 0; for (Cell adjCell : currentCell.getAdjCells()) { if (!adjCell.isWall && !visited[adjCell.y][adjCell.x]) { touchedCells += dfs(adjCell,visited); } } return ++touchedCells; } }
就是这样!让我知道您是否需要有关代码的任何说明.