Newer
Older
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
import java.util.*;
public class FirefighterBoard implements Board<List<ModelElement>> {
private final int columnCount;
private final int rowCount;
private final int initialFireCount;
private final int initialFirefighterCount;
List<Position> firefighterPositions;
Set<Position> firePositions;
List<Position> firefighterNewPositions;
int step = 0;
public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) {
this.columnCount = columnCount;
this.rowCount = rowCount;
this.initialFireCount = initialFireCount;
this.initialFirefighterCount = initialFirefighterCount;
initializeElements();
}
public void initializeElements() {
firefighterPositions = new ArrayList<>();
firePositions = new HashSet<>();
for (int index = 0; index < initialFireCount; index++)
firePositions.add(randomPosition());
for (int index = 0; index < initialFirefighterCount; index++)
firefighterPositions.add(randomPosition());
}
private Position randomPosition() {
return new Position((int) (Math.random() * rowCount), (int) (Math.random() * columnCount));
}
@Override
public List<ModelElement> getState(Position position) {
List<ModelElement> result = new ArrayList<>();
for(Position firefighterPosition : firefighterPositions)
if (firefighterPosition.equals(position))
result.add(ModelElement.FIREFIGHTER);
if(firePositions.contains(position))
result.add(ModelElement.FIRE);
return result;
}
@Override
public int rowCount() {
return rowCount;
}
@Override
public int columnCount() {
return columnCount;
}
public List<Position> updateToNextGeneration() {
List<Position> result = activateFirefighters();
result.addAll(activateFires());
step++;
return result;
}
private List<Position> activateFires() {
List<Position> result = new ArrayList<>();
if (step % 2 == 0) {
List<Position> newFirePositions = new ArrayList<>();
for (Position fire : firePositions) {
newFirePositions.addAll(neighbors(fire));
}
firePositions.addAll(newFirePositions);
result.addAll(newFirePositions);
}
return result;
}
@Override
public int stepNumber() {
return step;
}
private List<Position> activateFirefighters() {
List<Position> result = new ArrayList<>();
firefighterNewPositions = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions) {
Position newFirefighterPosition = neighborClosestToFire(firefighterPosition);
result.add(firefighterPosition);
firefighterNewPositions.add(newFirefighterPosition);
extinguish(newFirefighterPosition);
List<Position> neighborFirePositions = neighbors(newFirefighterPosition).stream().filter(firePositions::contains).toList();
for(Position firePosition : neighborFirePositions)
extinguish(firePosition);
}
firefighterPositions = firefighterNewPositions;
return result;
}
@Override
public void reset() {
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
initializeElements();
}
private void extinguish(Position position) {
firePositions.remove(position);
}
private List<Position> neighbors(Position position) {
List<Position> list = new ArrayList<>();
if (position.row() > 0) list.add(new Position(position.row() - 1, position.column()));
if (position.column() > 0) list.add(new Position(position.row(), position.column() - 1));
if (position.row() < rowCount - 1) list.add(new Position(position.row() + 1, position.column()));
if (position.column() < columnCount - 1) list.add(new Position(position.row(), position.column() + 1));
return list;
}
private Position neighborClosestToFire(Position position) {
Set<Position> seen = new HashSet<>();
HashMap<Position, Position> firstMove = new HashMap<>();
Queue<Position> toVisit = new LinkedList<>(neighbors(position));
for (Position initialMove : toVisit)
firstMove.put(initialMove, initialMove);
while (!toVisit.isEmpty()) {
Position current = toVisit.poll();
if (firePositions.contains(current))
return firstMove.get(current);
for (Position adjacent : neighbors(current)) {
if (seen.contains(adjacent)) continue;
toVisit.add(adjacent);
seen.add(adjacent);
firstMove.put(adjacent, firstMove.get(current));
}
}
return position;
}
}