-
Notifications
You must be signed in to change notification settings - Fork 42
/
BFSearch.java
149 lines (130 loc) · 3.72 KB
/
BFSearch.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* Defines a Bredth-First search to be performed on a qualifying puzzle.
* Currently supports 8puzzle and FWGC.
*
* @author Michael Langston && Gabe Ferrer
*/
public class BFSearch
{
/**
* Initialization function for 8puzzle BFSearch
*
* @param board
* - The starting state, represented as a linear array of length
* 9 forming 3 meta-rows.
*/
public static void search(int[] board, boolean d)
{
SearchNode root = new SearchNode(new EightPuzzleState(board));
Queue<SearchNode> queue = new LinkedList<SearchNode>();
queue.add(root);
performSearch(queue, d);
}
/**
* Initialization function for FWGC BFSearch
*/
public static void search(boolean d)
{
SearchNode root = new SearchNode(new FWGC_State());
Queue<SearchNode> queue = new LinkedList<SearchNode>();
queue.add(root);
performSearch(queue, d);
}
/*
* Helper method to check to see if a SearchNode has already been evaluated.
* Returns true if it has, false if it hasn't.
*/
private static boolean checkRepeats(SearchNode n)
{
boolean retValue = false;
SearchNode checkNode = n;
// While n's parent isn't null, check to see if it's equal to the node
// we're looking for.
while (n.getParent() != null && !retValue)
{
if (n.getParent().getCurState().equals(checkNode.getCurState()))
{
retValue = true;
}
n = n.getParent();
}
return retValue;
}
/**
* Performs a BFSearch using q as the search space
*
* @param q
* - A SearchNode queue to be populated and searched
*/
public static void performSearch(Queue<SearchNode> q, boolean d)
{
int searchCount = 1; // counter for number of iterations
while (!q.isEmpty()) // while the queue is not empty
{
SearchNode tempNode = (SearchNode) q.poll();
if (!tempNode.getCurState().isGoal()) // if tempNode is not the goal
// state
{
ArrayList<State> tempSuccessors = tempNode.getCurState()
.genSuccessors(); // generate tempNode's immediate
// successors
/*
* Loop through the successors, wrap them in a SearchNode, check
* if they've already been evaluated, and if not, add them to
* the queue
*/
for (int i = 0; i < tempSuccessors.size(); i++)
{
// second parameter here adds the cost of the new node to
// the current cost total in the SearchNode
SearchNode newNode = new SearchNode(tempNode,
tempSuccessors.get(i), tempNode.getCost()
+ tempSuccessors.get(i).findCost(), 0);
if (!checkRepeats(newNode))
{
q.add(newNode);
}
}
searchCount++;
}
else
// The goal state has been found. Print the path it took to get to
// it.
{
// Use a stack to track the path from the starting state to the
// goal state
Stack<SearchNode> solutionPath = new Stack<SearchNode>();
solutionPath.push(tempNode);
tempNode = tempNode.getParent();
while (tempNode.getParent() != null)
{
solutionPath.push(tempNode);
tempNode = tempNode.getParent();
}
solutionPath.push(tempNode);
// The size of the stack before looping through and emptying it.
int loopSize = solutionPath.size();
for (int i = 0; i < loopSize; i++)
{
tempNode = solutionPath.pop();
tempNode.getCurState().printState();
System.out.println();
System.out.println();
}
System.out.println("The cost was: " + tempNode.getCost());
if (d)
{
System.out.println("The number of nodes examined: "
+ searchCount);
}
System.exit(0);
}
}
// This should never happen with our current puzzles.
System.out.println("Error! No solution found!");
}
}