-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPuzzleSearch.java
164 lines (148 loc) · 5.18 KB
/
PuzzleSearch.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import java.util.ArrayList;
import java.util.Stack;
import java.util.HashSet;
import java.util.Iterator;
/**
* PuzzleSearch holds methods for searching for solutions to the puzzle.
*
* @author Ewen Cluley
* @version v1 (06/05/2010)
*/
public class PuzzleSearch
{
private Puzzle start;
private Puzzle goal;
/**
* PuzzleSearch is used to try different puzzle state objects
*/
public PuzzleSearch(Puzzle start)
{
goal = new Puzzle();
goal.fillGoal();
this.start = start;
}
/**
*Depth first search to find the goal puzzle state.
*/
public Puzzle depthFirstSearch()
{
Stack<Puzzle> toDo = new Stack<Puzzle>();
ArrayList<Puzzle> alreadySeen = new ArrayList<Puzzle>();
toDo.push(start);
while(!toDo.isEmpty()){
Puzzle current = toDo.pop();
if(current.equals(goal)){
return current;
} else {
ArrayList<Puzzle> daughtersList = current.getDaughters();
for(Puzzle p:daughtersList){
if(!toDo.contains(p) && !alreadySeen.contains(p)){
toDo.push(p);
}
}
alreadySeen.add(current);
}
}
return null;
}
/**
*Breadth first search to find the goal puzzle state.
*/
public Puzzle breadthFirstSearch()
{
ArrayList<Puzzle> toDo = new ArrayList<Puzzle>();
ArrayList<Puzzle> alreadySeen = new ArrayList<Puzzle>();
toDo.add(start);
while(!toDo.isEmpty()){
Puzzle current = toDo.remove(0);
if(current.equals(goal)){
return current;
} else {
ArrayList<Puzzle> daughtersList = current.getDaughters();
for(Puzzle p:daughtersList){
if(!toDo.contains(p) && !alreadySeen.contains(p)){
toDo.add(p);
}
}
alreadySeen.add(current);
}
}
return null;
}
/**
*A* search to find the goal puzzle state.
*/
public Puzzle aStarSearch()
{
int moves = 0;
ArrayList<Puzzle> toDo = new ArrayList<Puzzle>();
HashSet<Puzzle> alreadySeen = new HashSet<Puzzle>();
toDo.add(start);
while(!toDo.isEmpty()){
Puzzle current = toDo.remove(0);
if(current.equals(goal)){
return current;
} else {
ArrayList<Puzzle> daughtersList = current.getDaughters();
daughtersList = sortDaughters(daughtersList, alreadySeen, toDo); //sorts the daughters list
if(toDo.isEmpty()){
toDo.addAll(daughtersList); //if the toDo list has nothing in it, add the daughters list in its entirity
} else {
toDo = mergeIntoToDo(toDo, daughtersList); // if got things in it, merge the daughters into it.
}
alreadySeen.add(current);
}
}
return null;
}
/**
* Sorts thew daughters list and removes and which are int he toDo and alreadySeen lists
* @param daughtersIn the ArrayList of daughters to be sorted
* @param alreadySeen the ArrayLsit of states which have already been seen by the search algorithm
* @param toDo the ArrayList of states for the algorithm to check next.
*/
private ArrayList<Puzzle> sortDaughters(ArrayList<Puzzle> daughtersIn, HashSet<Puzzle> alreadySeen, ArrayList<Puzzle> toDo)
{
ArrayList<Puzzle> daughtersOut = new ArrayList<Puzzle>();
daughtersOut.add(daughtersIn.get(0));
for(Puzzle lookingAt:daughtersIn){
for(int i =0; i<daughtersOut.size(); i++){
if(lookingAt.getCost() < daughtersOut.get(i).getCost()){
if(!alreadySeen.contains(lookingAt)){
daughtersOut.add(i, lookingAt);
i = daughtersOut.size();
}
}
}
}
return daughtersOut;
}
/**
* Mereges an ArrayList of daughter states into the toDo list.
*/
private ArrayList<Puzzle> mergeIntoToDo(ArrayList<Puzzle> toDo, ArrayList<Puzzle> daughters) //both array list's must be sorted!
{
ArrayList<Puzzle> output = new ArrayList<Puzzle>();
int daughtersI =0;
int toDoI = 0;
while(toDoI < toDo.size() && daughtersI < daughters.size()){
if(toDo.get(toDoI).getCost() <= daughters.get(daughtersI).getCost()){
output.add(toDo.get(toDoI));
toDoI ++;
}
else{
output.add(daughters.get(daughtersI));
daughtersI ++;
}
}
while(toDoI < toDo.size()){
output.add(toDo.get(toDoI));
toDoI ++;
}
while(daughtersI < daughters.size()){
output.add(daughters.get(daughtersI));
daughtersI ++;
}
return output;
}
}