Skip to content

Commit 6380bc7

Browse files
author
Pedro Geadas
committed
Added strategy pattern to check the map
1 parent 4631c9f commit 6380bc7

File tree

7 files changed

+145
-75
lines changed

7 files changed

+145
-75
lines changed

src/com/ai/astar/AStar.java

Lines changed: 28 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
11
package com.ai.astar;
22

3+
import com.ai.astar.searchstrategy.DiagonalMapChecker;
4+
import com.ai.astar.searchstrategy.HorizontalVerticalChecker;
5+
import com.ai.astar.searchstrategy.MapChecker;
6+
import com.ai.astar.searchstrategy.NoOpChecker;
7+
38
import java.util.*;
49

5-
/**
6-
* A Star Algorithm
7-
*
8-
* @author Marcelo Surriabre
9-
* @version 2.1, 2017-02-23
10-
*/
1110
public class AStar {
1211
private static final int DEFAULT_HV_COST = 10; // Horizontal - Vertical Cost
1312
private static final int DEFAULT_DIAGONAL_COST = 14;
14-
private final int hvCost;
15-
private final int diagonalCost;
1613
private final Node[][] searchArea;
1714
private final PriorityQueue<Node> openList;
1815
private final Set<Node> closedSet;
1916
private final Node initialNode;
2017
private final Node finalNode;
18+
private final MapChecker diagonalsChecker;
19+
private final MapChecker hvChecker;
2120

22-
public AStar(int rows, int cols, Node initialNode, Node finalNode, int hvCost, int diagonalCost) {
23-
this.hvCost = hvCost;
24-
this.diagonalCost = diagonalCost;
21+
public AStar(int rows, int cols, Node initialNode, Node finalNode, boolean searchDiagonals) {
2522
this.initialNode = initialNode;
2623
this.finalNode = finalNode;
2724
this.searchArea = new Node[rows][cols];
2825
this.openList = new PriorityQueue<>(Comparator.comparingInt(Node::f));
2926
initNodes();
3027
this.closedSet = new HashSet<>();
31-
}
32-
33-
public AStar(int rows, int cols, Node initialNode, Node finalNode) {
34-
this(rows, cols, initialNode, finalNode, DEFAULT_HV_COST, DEFAULT_DIAGONAL_COST);
28+
if (searchDiagonals) {
29+
this.diagonalsChecker = new DiagonalMapChecker(searchArea, openList, closedSet, DEFAULT_DIAGONAL_COST);
30+
} else {
31+
this.diagonalsChecker = new NoOpChecker(null, null, null);
32+
}
33+
this.hvChecker = new HorizontalVerticalChecker(searchArea, openList, closedSet, DEFAULT_HV_COST);
3534
}
3635

3736
private void initNodes() {
@@ -58,15 +57,15 @@ public List<Node> findPath() {
5857
Node currentNode = openList.poll();
5958
closedSet.add(currentNode);
6059
if (isFinalNode(currentNode)) {
61-
return generatePath(currentNode);
60+
return bestPath(currentNode);
6261
} else {
6362
addAdjacentNodes(currentNode);
6463
}
6564
}
6665
return new ArrayList<>();
6766
}
6867

69-
private List<Node> generatePath(Node currentNode) {
68+
private List<Node> bestPath(Node currentNode) {
7069
List<Node> path = new ArrayList<>();
7170
path.add(currentNode);
7271
Node parent;
@@ -78,71 +77,26 @@ private List<Node> generatePath(Node currentNode) {
7877
}
7978

8079
private void addAdjacentNodes(Node currentNode) {
81-
addAdjacentUpperRow(currentNode);
82-
addAdjacentMiddleRow(currentNode);
83-
addAdjacentLowerRow(currentNode);
84-
}
85-
86-
private void addAdjacentLowerRow(Node currentNode) {
8780
int row = currentNode.row();
8881
int col = currentNode.col();
89-
int lowerRow = row + 1;
90-
if (lowerRow >= searchArea.length) {
91-
return;
92-
}
93-
if (col - 1 >= 0) {
94-
checkNode(currentNode, col - 1, lowerRow, diagonalCost); // Comment this line if diagonal movements are not allowed
95-
}
96-
if (col + 1 < searchArea[0].length) {
97-
checkNode(currentNode, col + 1, lowerRow, diagonalCost); // Comment this line if diagonal movements are not allowed
98-
}
99-
checkNode(currentNode, col, lowerRow, hvCost);
82+
addAdjacentUpperRow(currentNode, row, col);
83+
addAdjacentMiddleRow(currentNode, row, col);
84+
addAdjacentLowerRow(currentNode, row, col);
10085
}
10186

102-
private void addAdjacentMiddleRow(Node currentNode) {
103-
int row = currentNode.row();
104-
int col = currentNode.col();
105-
if (col - 1 >= 0) {
106-
checkNode(currentNode, col - 1, row, hvCost);
107-
}
108-
if (col + 1 < searchArea[0].length) {
109-
checkNode(currentNode, col + 1, row, hvCost);
110-
}
87+
private void addAdjacentLowerRow(Node currentNode, int row, int col) {
88+
diagonalsChecker.checkNode(currentNode, col, row + 1);
89+
hvChecker.checkNode(currentNode, col, row + 1);
11190
}
11291

113-
private void addAdjacentUpperRow(Node currentNode) {
114-
int row = currentNode.row();
115-
int col = currentNode.col();
116-
int upperRow = row - 1;
117-
if (upperRow < 0) {
118-
return;
119-
}
120-
if (col - 1 >= 0) {
121-
checkNode(currentNode, col - 1, upperRow, diagonalCost); // Comment this if diagonal movements are not allowed
122-
}
123-
if (col + 1 < searchArea[0].length) {
124-
checkNode(currentNode, col + 1, upperRow, diagonalCost); // Comment this if diagonal movements are not allowed
125-
}
126-
checkNode(currentNode, col, upperRow, hvCost);
92+
private void addAdjacentMiddleRow(Node currentNode, int row, int col) {
93+
hvChecker.checkNode(currentNode, col - 1, row);
94+
hvChecker.checkNode(currentNode, col + 1, row);
12795
}
12896

129-
private void checkNode(Node currentNode, int col, int row, int cost) {
130-
Node adjacentNode = searchArea[row][col];
131-
if (adjacentNode.isBlocked() || closedSet.contains(adjacentNode)) {
132-
return;
133-
}
134-
if (!openList.contains(adjacentNode)) {
135-
adjacentNode.setNodeData(currentNode, cost);
136-
openList.add(adjacentNode);
137-
} else {
138-
boolean changed = adjacentNode.checkBetterPath(currentNode, cost);
139-
if (changed) {
140-
// Remove and Add the changed node, so that the PriorityQueue can sort again its
141-
// contents with the modified "finalCost" value of the modified node
142-
openList.remove(adjacentNode);
143-
openList.add(adjacentNode);
144-
}
145-
}
97+
private void addAdjacentUpperRow(Node currentNode, int row, int col) {
98+
diagonalsChecker.checkNode(currentNode, col, row - 1);
99+
hvChecker.checkNode(currentNode, col, row - 1);
146100
}
147101

148102
private boolean isFinalNode(Node currentNode) {

src/com/ai/astar/AStarTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public static void main(String[] args) {
99
Node finalNode = new Node(2, 5);
1010
int rows = 6;
1111
int cols = 7;
12-
AStar aStar = new AStar(rows, cols, initialNode, finalNode);
12+
AStar aStar = new AStar(rows, cols, initialNode, finalNode, false);
1313
int[][] blocksArray = new int[][]{{1, 3}, {2, 3}, {3, 3}};
1414
aStar.initBlocks(blocksArray);
1515
List<Node> path = aStar.findPath();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.ai.astar.searchstrategy;
2+
3+
import com.ai.astar.Node;
4+
5+
import java.util.PriorityQueue;
6+
import java.util.Set;
7+
8+
public class DiagonalMapChecker extends MapChecker {
9+
10+
private final int diagonalCost;
11+
12+
public DiagonalMapChecker(Node[][] searchArea, PriorityQueue<Node> openList, Set<Node> closedSet, int diagonalCost) {
13+
super(searchArea, openList, closedSet);
14+
this.diagonalCost = diagonalCost;
15+
}
16+
17+
@Override
18+
public void checkNode(Node currentNode, int col, int row) {
19+
check(currentNode, col - 1, row, diagonalCost);
20+
check(currentNode, col + 1, row, diagonalCost);
21+
}
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.ai.astar.searchstrategy;
2+
3+
import com.ai.astar.Node;
4+
5+
import java.util.PriorityQueue;
6+
import java.util.Set;
7+
8+
public class HorizontalVerticalChecker extends MapChecker {
9+
10+
private final int hvCost;
11+
12+
public HorizontalVerticalChecker(Node[][] searchArea, PriorityQueue<Node> openList, Set<Node> closedSet, int hvCost) {
13+
super(searchArea, openList, closedSet);
14+
this.hvCost = hvCost;
15+
}
16+
17+
@Override
18+
public void checkNode(Node currentNode, int col, int row) {
19+
check(currentNode, col, row, hvCost);
20+
}
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.ai.astar.searchstrategy;
2+
3+
import com.ai.astar.Node;
4+
5+
public interface MapCheck {
6+
7+
void checkNode(Node currentNode, int col, int row);
8+
9+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.ai.astar.searchstrategy;
2+
3+
import com.ai.astar.Node;
4+
5+
import java.util.PriorityQueue;
6+
import java.util.Set;
7+
8+
public abstract class MapChecker implements MapCheck {
9+
protected final Node[][] searchArea;
10+
protected final PriorityQueue<Node> openList;
11+
protected final Set<Node> closedSet;
12+
protected final int columns;
13+
14+
protected MapChecker(Node[][] searchArea, PriorityQueue<Node> openList, Set<Node> closedSet) {
15+
this.searchArea = searchArea;
16+
this.openList = openList;
17+
this.closedSet = closedSet;
18+
this.columns = searchArea == null ? 0 : searchArea[0].length;
19+
}
20+
21+
void check(Node currentNode, int col, int row, int cost) {
22+
if (row < 0 || row >= searchArea.length) {
23+
return;
24+
}
25+
if (col < 0 || col >= columns) {
26+
return;
27+
}
28+
Node adjacentNode = searchArea[row][col];
29+
if (adjacentNode.isBlocked() || closedSet.contains(adjacentNode)) {
30+
return;
31+
}
32+
if (!openList.contains(adjacentNode)) {
33+
adjacentNode.setNodeData(currentNode, cost);
34+
openList.add(adjacentNode);
35+
} else {
36+
boolean changed = adjacentNode.checkBetterPath(currentNode, cost);
37+
if (changed) {
38+
// Remove and Add the changed node, so that the PriorityQueue can sort again its
39+
// contents with the modified "finalCost" value of the modified node
40+
openList.remove(adjacentNode);
41+
openList.add(adjacentNode);
42+
}
43+
}
44+
}
45+
46+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.ai.astar.searchstrategy;
2+
3+
import com.ai.astar.Node;
4+
5+
import java.util.PriorityQueue;
6+
import java.util.Set;
7+
8+
public class NoOpChecker extends MapChecker {
9+
10+
public NoOpChecker(Node[][] searchArea, PriorityQueue<Node> openList, Set<Node> closedSet) {
11+
super(searchArea, openList, closedSet);
12+
}
13+
14+
@Override
15+
public void checkNode(Node currentNode, int col, int row) {
16+
// nothing to do
17+
}
18+
}

0 commit comments

Comments
 (0)