如何解决矩阵中两个单元格之间的最短路径
我有一个二维数组,用于表示游戏中角色的位置,我将其称为网格。网格是一个 5x5 大小的网格。并非网格上的所有图块/位置都是角色可以穿越的可行位置。在示例图像中,您可以看到其中三个位置是水而不是陆地,表示角色无法访问的位置。
在遍历网格时,仅使用四个基本方向(上、下、左、右)我希望角色找到到达目的地的最短可行路径。例如,如果它从 [1,2] 开始并需要到达位置 [3,2],我希望它移动:向上 -> 向右 -> 向右 -> 向下。
以下是我目前用于确定可行解决方案的方法;它有一些不太正确的地方,但我无法弄清楚我的逻辑哪里出错了:
DartPad Example 用于交互式功能代码。
import 'dart:collection';
class Point {
int x;
int y;
Point({required this.y,required this.x});
}
void main() {
print('Finding a viable solution for the shortest path...');
var grid = [
['?','?','?'],['?',// Character is at position grid[2][1]
['?',// Destination is position grid[2][3]
['?',];
var characterPosition = Point(y: 2,x: 1);
var characterDestination = Point(y: 2,x: 3);
pathfinder pathfinder = pathfinder(grid,characterPosition,characterDestination);
if (pathfinder.solutionExists) {
print('...solution exists!');
for (Point point in pathfinder.solution) {
print('(${point.y},${point.x})');
}
}
else {
print('...No solution exists.');
}
}
class pathfinder {
late Queue<Point> solution;
late bool solutionExists;
pathfinder(grid,characterDestination) {
// Applying BFS on matrix cells.
Queue<Point> queue = Queue<Point>();
queue.add(new Point(y: characterPosition.y,x: characterPosition.x));
List<List<bool>> visited = List.generate(
grid.length,(index) => List.generate(
grid[0].length,(index) => false,growable: false,),);
visited[characterPosition.y][characterPosition.x] =
true;
while (queue.isNotEmpty) {
Point point = queue.removeLast();
// Destination found
if (point.x == characterDestination.x &&
point.y == characterDestination.y) {
this.solutionExists = true;
this.solution = queue;
return;
}
// moving up
if (_isValid(x: point.x,y: point.y - 1,grid: grid,visited: visited)) {
queue.add(new Point(y: point.y - 1,x: point.x));
visited[point.y - 1][point.x] = true;
}
// moving down
if (_isValid(x: point.x,y: point.y + 1,visited: visited)) {
queue.add(new Point(y: point.y + 1,x: point.x));
visited[point.y + 1][point.x] = true;
}
// moving left
if (_isValid(x: point.x - 1,y: point.y,visited: visited)) {
queue.add(new Point(y: point.y,x: point.x - 1));
visited[point.y][point.x - 1] = true;
}
// moving right
if (_isValid(x: point.x + 1,x: point.x + 1));
visited[point.y][point.x + 1] = true;
}
}
this.solutionExists = false;
this.solution = queue;
return;
}
bool _isValid({required int x,required int y,required List<List<String>> grid,required List<List<bool>> visited}) {
if (x >= 0 &&
y >= 0 &&
x < grid[0].length &&
y < grid.length &&
grid[y][x] != '?' &&
visited[y][x] == false) {
return true;
}
return false;
}
}
如果你运行这个(使用 DartPad),你可以看到输出是:
Finding a viable solution for the shortest path...
...solution exists!
(1,1)
(3,3)
(1,4)
这个输出与我的预期不太一样,这意味着我显然搞砸了一些事情。我无法弄清楚我应该怎么做才能正确实现此路径查找算法,因此将不胜感激任何见解、建议或帮助!提前谢谢你!!
解决方法
逻辑是“广度优先搜索”。 List cameFrom 将每个节点元素设置为它来自的节点元素。图片:
现在重建整个路径,从目的地到起始节点。
DartPad 上的 Dart 解决方案。
Dart 不是我的母语,所以请随时更改方法...
import 'dart:collection';
// *****************************************************************************
// ***** class Point
class Point {
int x;
int y;
Point({required this.y,required this.x});
}
// *****************************************************************************
// ***** class PathFinder
class PathFinder {
List<List<String>> grid;
int gridWidth = 0;
int gridHeight = 0;
late Queue<Point> solution;
late bool solutionExists;
// ---------------------------------------------------------------------------
// ----- constructor
PathFinder(this.grid,characterPosition,characterDestination) {
// integers for easier manipulation
Queue<int> frontier = Queue<int>();
List<int> cameFrom = List.generate(
this.grid[0].length * this.grid.length,(int index) => -1,growable: false,);
this.gridWidth = this.grid[0].length;
this.gridHeight = this.grid.length;
frontier.add(this._convert2dto1d(characterPosition));
// +++++ Breadth First Search Logic begin
while (frontier.isNotEmpty) {
int current = frontier.removeFirst();
Queue<Point> neighbors = this._neighbors(_convert1dto2d(current));
for (Point node in neighbors) {
int node1d = this._convert2dto1d(node);
if (cameFrom[node1d] == -1) {
frontier.add(node1d);
cameFrom[node1d] = current;
}
}
}
// +++++ Breadth First Search Logic end
this.solutionExists = true;
// +++++ copy solution to 2d Queue<Point> begin
this.solution = Queue<Point>();
Point endNode = characterDestination;
this.solution.add(endNode);
while (
endNode.x != characterPosition.x || endNode.y != characterPosition.y) {
int endNode1d = this._convert2dto1d(endNode);
if (cameFrom[endNode1d] == -1) {
this.solutionExists = false;
break;
}
endNode = this._convert1dto2d(cameFrom[endNode1d]);
this.solution.addFirst(endNode);
}
// +++++ copy solution to 2d Queue<Point> end
return;
}
// ---------------------------------------------------------------------------
// ----- _convert2dto1d
// ----- Convert point to integer for easier manipulation
int _convert2dto1d(Point node) {
return node.y * this.gridWidth + node.x;
}
// ---------------------------------------------------------------------------
// ----- _convert1dto2d
// ----- Convert integer back to point
Point _convert1dto2d(int node1d) {
if (this.gridWidth == 0) {
return new Point(y: -1,x: -1);
}
int y = node1d ~/ this.gridWidth;
int x = node1d - y * this.gridWidth;
return new Point(y: y,x: x);
}
// ---------------------------------------------------------------------------
// ----- _neighbors
Queue<Point> _neighbors(Point node) {
Queue<Point> neighbors = Queue<Point>();
for (int dx = -1; dx <= 1; dx += 2) {
Point neighborNode = new Point(y: node.y,x: node.x + dx);
if (_isValidNode(neighborNode)) {
neighbors.add(neighborNode);
}
}
for (int dy = -1; dy <= 1; dy += 2) {
Point neighborNode = new Point(y: node.y + dy,x: node.x);
if (_isValidNode(neighborNode)) {
neighbors.add(neighborNode);
}
}
return neighbors;
}
// ---------------------------------------------------------------------------
// ----- _isValidNode
bool _isValidNode(Point node) {
if (node.x >= 0 &&
node.y >= 0 &&
node.x < this.gridWidth &&
node.y < this.gridHeight &&
this.grid[node.y][node.x] != '?') {
return true;
}
return false;
}
}
// *****************************************************************************
// ***** main
void main() {
print('Finding a viable solution for the shortest path...');
var grid = [
['?','?','?'],['?',// Character is at position grid[2][1]
['?',// Destination is position grid[2][3]
['?',];
var characterPosition = Point(y: 2,x: 1);
var characterDestination = Point(y: 2,x: 3);
PathFinder pathFinder =
PathFinder(grid,characterDestination);
if (pathFinder.solutionExists) {
print('...Solution exists!');
for (Point point in pathFinder.solution) {
print('(${point.y},${point.x})');
}
} else {
print('...No solution exists.');
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。