Skip to content

Commit 3452090

Browse files
committed
refactoring and bugfix
1 parent 91cfb50 commit 3452090

File tree

8 files changed

+138
-108
lines changed

8 files changed

+138
-108
lines changed
Lines changed: 24 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,64 @@
11
package com.bernd.game;
22

33
import com.bernd.util.BoardUpdate;
4-
import java.util.ArrayList;
5-
import java.util.Collection;
6-
import java.util.LinkedHashMap;
7-
import java.util.List;
8-
import java.util.Map;
9-
import java.util.function.Function;
104

115
public class Board {
126

137
public static final int BLACK = 2;
148
public static final int WHITE = 4;
159

16-
public static StoneGroup getStoneGroup(
10+
private static StoneGroup getStoneGroup(
1711
int[][] board,
1812
int xx,
1913
int yy) {
2014
int color = board[yy][xx];
21-
if (color == 0) {
22-
return null;
23-
}
2415
int dim = board.length;
25-
int id = yy * dim + xx;
26-
List<Point> points = new ArrayList<>();
16+
BoardUpdate update = BoardUpdate.builder(dim, 16);
2717
int liberties = 0;
28-
boolean[] pointsChecked = new boolean[dim * dim];
29-
pointsChecked[id] = true;
18+
PointSet pointsChecked = PointSet.create(dim);
3019
PointQueue pointsToCheck = PointQueue.create(dim);
3120
pointsToCheck.offer(xx, yy);
3221
while (!pointsToCheck.isEmpty()) {
3322
int ptId = pointsToCheck.poll();
3423
int y = ptId / dim;
3524
int x = ptId % dim;
36-
id = Math.min(id, ptId);
37-
points.add(new Point(x, y));
25+
pointsChecked.add(x, y);
26+
update.add(x, y, 0);
3827
if (y > 0) {
3928
int bpt = board[y - 1][x];
40-
int bptId = (y - 1) * dim + x;
4129
if (bpt == 0) {
4230
liberties++;
43-
} else if (bpt == color && !pointsChecked[bptId]) {
44-
pointsChecked[bptId] = true;
31+
} else if (bpt == color && !pointsChecked.has(x, y - 1)) {
4532
pointsToCheck.offer(x, y - 1);
4633
}
4734
}
4835
if (y < dim - 1) {
4936
int bpt = board[y + 1][x];
50-
int bptId = (y + 1) * dim + x;
5137
if (bpt == 0) {
5238
liberties++;
53-
} else if (bpt == color && !pointsChecked[bptId]) {
54-
pointsChecked[bptId] = true;
39+
} else if (bpt == color && !pointsChecked.has(x, y + 1)) {
5540
pointsToCheck.offer(x, y + 1);
5641
}
5742
}
5843
if (x > 0) {
5944
int bpt = board[y][x - 1];
60-
int bptId = y * dim + x - 1;
6145
if (bpt == 0) {
6246
liberties++;
63-
} else if (bpt == color && !pointsChecked[bptId]) {
64-
pointsChecked[bptId] = true;
47+
} else if (bpt == color && !pointsChecked.has(x - 1, y)) {
6548
pointsToCheck.offer(x - 1, y);
6649
}
6750
}
6851
if (x < dim - 1) {
6952
int bpt = board[y][x + 1];
70-
int bptId = y * dim + x + 1;
7153
if (bpt == 0) {
7254
liberties++;
73-
} else if (bpt == color && !pointsChecked[bptId]) {
74-
pointsChecked[bptId] = true;
55+
} else if (bpt == color && !pointsChecked.has(x + 1, y)) {
7556
pointsToCheck.offer(x + 1, y);
7657
}
7758
}
7859
}
7960
return new StoneGroup(
80-
id,
81-
color,
82-
points,
61+
update,
8362
liberties);
8463
}
8564

@@ -93,66 +72,35 @@ public static int[][] removeDeadStonesAround(
9372
}
9473
int oppositeColor = color == WHITE ? BLACK : WHITE;
9574
int size = board.length;
96-
Map<Integer, StoneGroup> groups = new LinkedHashMap<>(8);
97-
75+
int[][] result = board;
9876
// Above
99-
if (y > 0) {
77+
if (y > 0 && board[y - 1][x] == oppositeColor) {
10078
StoneGroup group = getStoneGroup(board, x, y - 1);
101-
if (group != null && group.color() == oppositeColor && group.liberties() == 0) {
102-
groups.put(group.id(), group);
79+
if (group.liberties() == 0) {
80+
result = group.update().apply(result);
10381
}
10482
}
10583
// Below
106-
if (y < size - 1) {
84+
if (y < size - 1 && board[y + 1][x] == oppositeColor) {
10785
StoneGroup group = getStoneGroup(board, x, y + 1);
108-
if (group != null &&
109-
group.color() == oppositeColor &&
110-
group.liberties() == 0 &&
111-
!groups.containsKey(group.id())) {
112-
groups.put(group.id(), group);
86+
if (group.liberties() == 0) {
87+
result = group.update().apply(result);
11388
}
11489
}
11590
// Left
116-
if (x > 0) {
91+
if (x > 0 && board[y][x - 1] == oppositeColor) {
11792
StoneGroup group = getStoneGroup(board, x - 1, y);
118-
if (group != null &&
119-
group.color() == oppositeColor &&
120-
group.liberties() == 0 &&
121-
!groups.containsKey(group.id())) {
122-
groups.put(group.id(), group);
93+
if (group.liberties() == 0) {
94+
result = group.update().apply(result);
12395
}
12496
}
12597
// Right
126-
if (x < size - 1) {
98+
if (x < size - 1 && board[y][x + 1] == oppositeColor) {
12799
StoneGroup group = getStoneGroup(board, x + 1, y);
128-
if (group != null &&
129-
group.color() == oppositeColor &&
130-
group.liberties() == 0 &&
131-
!groups.containsKey(group.id())) {
132-
groups.put(group.id(), group);
133-
}
134-
}
135-
136-
if (groups.isEmpty()) {
137-
return board;
138-
}
139-
Function<int[][], int[][]> update = removeStonesIn(board.length, groups.values());
140-
return update.apply(board);
141-
}
142-
143-
private static Function<int[][], int[][]> removeStonesIn(
144-
int dim,
145-
Collection<StoneGroup> groups) {
146-
int size = 0;
147-
for (StoneGroup group : groups) {
148-
size += group.points().size();
149-
}
150-
BoardUpdate update = BoardUpdate.builder(dim, size);
151-
for (StoneGroup group : groups) {
152-
for (Point point : group.points()) {
153-
update.add(point, 0);
100+
if (group.liberties() == 0) {
101+
result = group.update().apply(result);
154102
}
155103
}
156-
return update;
104+
return result;
157105
}
158106
}

src/main/java/com/bernd/game/Count.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,27 @@ private static int getImpliedColor(
1010
return board[yy][xx];
1111
}
1212
int dim = board.length;
13+
PointSet pointsChecked = PointSet.create(dim);
1314
PointQueue pointsToCheck = PointQueue.create(dim);
1415
pointsToCheck.offer(xx, yy);
1516
while (!pointsToCheck.isEmpty()) {
1617
int ptId = pointsToCheck.poll();
1718
int y = ptId / dim;
1819
int x = ptId % dim;
20+
pointsChecked.add(x, y);
1921
if (board[y][x] != 0) {
2022
return board[y][x] + 1; // add territory flag
2123
}
22-
if (y > 0) {
24+
if (y > 0 && !pointsChecked.has(x, y - 1)) {
2325
pointsToCheck.offer(x, y - 1);
2426
}
25-
if (y < dim - 1) {
27+
if (y < dim - 1 && !pointsChecked.has(x, y + 1)) {
2628
pointsToCheck.offer(x, y + 1);
2729
}
28-
if (x > 0) {
30+
if (x > 0 && !pointsChecked.has(x - 1, y)) {
2931
pointsToCheck.offer(x - 1, y);
3032
}
31-
if (x < dim - 1) {
33+
if (x < dim - 1 && !pointsChecked.has(x + 1, y)) {
3234
pointsToCheck.offer(x + 1, y);
3335
}
3436
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bernd.game;
2+
3+
final class PointSet {
4+
5+
private final int dim;
6+
private final int[] points;
7+
8+
private PointSet(int dim, int[] points) {
9+
this.dim = dim;
10+
this.points = points;
11+
}
12+
13+
static PointSet create(int dim) {
14+
return new PointSet(dim, new int[1 + ((dim * dim) / 16)]);
15+
}
16+
17+
void add(int x, int y) {
18+
int ptId = y * dim + x;
19+
int base = ptId / 16;
20+
int off = ptId % 16;
21+
int shift = 1 << off;
22+
points[base] = points[base] | shift;
23+
}
24+
25+
boolean has(int x, int y) {
26+
int ptId = y * dim + x;
27+
int base = ptId / 16;
28+
int off = ptId % 16;
29+
int shift = 1 << off;
30+
return (points[base] & shift) != 0;
31+
}
32+
}

src/main/java/com/bernd/game/Remove.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,36 @@ private static List<Point> findGroup(
1616
}
1717
int dim = board.length;
1818
PointQueue pointsToCheck = PointQueue.create(dim);
19-
boolean[] pointsChecked = new boolean[dim * dim];
19+
PointSet pointsChecked = PointSet.create(dim);
2020
pointsToCheck.offer(xx, yy);
2121
List<Point> result = new ArrayList<>();
2222
while (!pointsToCheck.isEmpty()) {
2323
int ptId = pointsToCheck.poll();
2424
int y = ptId / dim;
2525
int x = ptId % dim;
26+
pointsChecked.add(x, y);
2627
result.add(new Point(x, y));
2728
if (y > 0) {
2829
int c = board[y - 1][x];
29-
int bptId = (y - 1) * dim + x;
30-
if (c == color && !pointsChecked[bptId]) {
31-
pointsChecked[bptId] = true;
30+
if (c == color && !pointsChecked.has(x, y - 1)) {
3231
pointsToCheck.offer(x, y - 1);
3332
}
3433
}
3534
if (y < dim - 1) {
3635
int c = board[y + 1][x];
37-
int bptId = (y + 1) * dim + x;
38-
if (c == color && !pointsChecked[bptId]) {
39-
pointsChecked[bptId] = true;
36+
if (c == color && !pointsChecked.has(x, y + 1)) {
4037
pointsToCheck.offer(x, y + 1);
4138
}
4239
}
4340
if (x > 0) {
4441
int c = board[y][x - 1];
45-
int bptId = y * dim + x - 1;
46-
if (c == color && !pointsChecked[bptId]) {
47-
pointsChecked[bptId] = true;
42+
if (c == color && !pointsChecked.has(x - 1, y)) {
4843
pointsToCheck.offer(x - 1, y);
4944
}
5045
}
5146
if (x < dim - 1) {
5247
int c = board[y][x + 1];
53-
int bptId = y * dim + x + 1;
54-
if (c == color && !pointsChecked[bptId]) {
55-
pointsChecked[bptId] = true;
48+
if (c == color && !pointsChecked.has(x + 1, y)) {
5649
pointsToCheck.offer(x + 1, y);
5750
}
5851
}
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.bernd.game;
22

3-
import java.util.List;
3+
import com.bernd.util.BoardUpdate;
44

55
public record StoneGroup(
6-
int id,
7-
int color,
8-
List<Point> points,
6+
BoardUpdate update,
97
int liberties
108
) {
119
}

src/main/java/com/bernd/util/BoardUpdate.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
public class BoardUpdate implements Function<int[][], int[][]> {
88

9+
private static final int SHIFT = 256;
910
private int pos;
1011
private final int dim;
11-
private final int[] updates;
12+
private int[] updates;
1213

1314
private BoardUpdate(
1415
int dim,
@@ -18,7 +19,7 @@ private BoardUpdate(
1819
}
1920

2021
public static BoardUpdate builder(int dim, int size) {
21-
return new BoardUpdate(dim, new int[2 * size]);
22+
return new BoardUpdate(dim, new int[size]);
2223
}
2324

2425
public static Function<int[][], int[][]> create(
@@ -29,24 +30,43 @@ public static Function<int[][], int[][]> create(
2930
}
3031

3132
public void add(int x, int y, int value) {
32-
int base = 2 * pos;
33-
updates[base] = dim * y + x;
34-
updates[base + 1] = value;
33+
if (pos >= updates.length) {
34+
updates = Arrays.copyOf(updates, 2 * dim * dim);
35+
}
36+
int ptId = dim * y + x;
37+
updates[pos] = SHIFT * ptId + value;
3538
pos++;
3639
}
3740

3841
public void add(Point point, int value) {
3942
add(point.x(), point.y(), value);
4043
}
4144

45+
public int x(int i) {
46+
int code = updates[i];
47+
int ptId = code / SHIFT;
48+
return ptId % dim;
49+
}
50+
51+
public int y(int i) {
52+
int code = updates[i];
53+
int ptId = code / SHIFT;
54+
return ptId / dim;
55+
}
56+
57+
public int size() {
58+
return pos;
59+
}
60+
4261
@Override
4362
public int[][] apply(int[][] board) {
4463
int[][] result = Arrays.copyOf(board, board.length);
45-
int size = updates.length / 2;
46-
for (int i = 0; i < size; i++) {
47-
int x = updates[2 * i] % dim;
48-
int y = updates[2 * i] / dim;
49-
int value = updates[2 * i + 1];
64+
for (int i = 0; i < pos; i++) {
65+
int code = updates[i];
66+
int value = code % SHIFT;
67+
int ptId = code / SHIFT;
68+
int x = ptId % dim;
69+
int y = ptId / dim;
5070
if (result[y] == board[y]) {
5171
result[y] = Arrays.copyOf(board[y], board[y].length);
5272
}

0 commit comments

Comments
 (0)