-
Notifications
You must be signed in to change notification settings - Fork 0
/
Board.java
207 lines (176 loc) · 5.63 KB
/
Board.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import java.util.LinkedList;
public class Board {
private int N;
private int[][] blocks;
private int emptyI = -1;
private int emptyJ = -1;
// construct a board from an N-by-N array of blocks
// (where blocks[i][j] = block in row i, column j)
public Board(int[][] blocks) {
N = blocks.length;
this.blocks = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
this.blocks[i][j] = blocks[i][j];
if (blocks[i][j] == 0) {
emptyI = i;
emptyJ = j;
}
}
}
}
// board dimension N
public int dimension() {
return N;
}
// number of blocks out of place
public int hamming() {
int result = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int val = blocks[i][j];
if (val == 0) continue;
if (val != rowColumnToExpectedValue(i, j)) result += 1;
}
}
return result;
}
// sum of Manhattan distances between blocks and goal
public int manhattan() {
int result = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int val = blocks[i][j];
if (val == 0) continue;
if (val != rowColumnToExpectedValue(i, j)) {
int[] rowColumn = valueToRowColumn(val);
result += Math.abs(rowColumn[0] - i);
result += Math.abs(rowColumn[1] - j);
}
}
}
return result;
}
// is this board the goal board?
public boolean isGoal() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int val = blocks[i][j];
if (val == 0) continue;
if (val != rowColumnToExpectedValue(i, j))return false;
}
}
return true;
}
// a board obtained by exchanging two adjacent blocks in the same row
public Board twin() {
Board board = new Board(blocks);
int i, j, i2, j2;
if (emptyI == 0) {
i = 1;
i2 = 1;
} else {
i = emptyI - 1;
i2 = i;
}
j = emptyJ;
if (j == 0) {
j2 = 1;
} else {
j2 = j - 1;
}
int tmp = board.blocks[i][j];
board.blocks[i][j] = board.blocks[i2][j2];
board.blocks[i2][j2] = tmp;
return board;
}
// does this board equal y?
public boolean equals(Object y) {
if (y == this) return true;
if (y == null) return false;
if (getClass() != y.getClass()) return false;
Board other = (Board) y;
if (N != other.N) return false;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (blocks[i][j] != other.blocks[i][j]) return false;
}
}
return true;
}
// all neighboring boards
public Iterable<Board> neighbors() {
LinkedList<Board> boards = new LinkedList<>();
int[][] newBlocks;
// top adjacent block
if (emptyI - 1 >= 0) {
newBlocks = blocksCopy(blocks);
newBlocks[emptyI][emptyJ] = newBlocks[emptyI - 1][emptyJ];
newBlocks[emptyI - 1][emptyJ] = 0;
boards.add(new Board(newBlocks));
}
// bottom adjacent block
if (emptyI + 1 < N) {
newBlocks = blocksCopy(blocks);
newBlocks[emptyI][emptyJ] = newBlocks[emptyI + 1][emptyJ];
newBlocks[emptyI + 1][emptyJ] = 0;
boards.add(new Board(newBlocks));
}
// left adjacent block
if (emptyJ - 1 >= 0) {
newBlocks = blocksCopy(blocks);
newBlocks[emptyI][emptyJ] = newBlocks[emptyI][emptyJ - 1];
newBlocks[emptyI][emptyJ - 1] = 0;
boards.add(new Board(newBlocks));
}
// right adjacent block
if (emptyJ + 1 < N) {
newBlocks = blocksCopy(blocks);
newBlocks[emptyI][emptyJ] = newBlocks[emptyI][emptyJ + 1];
newBlocks[emptyI][emptyJ + 1] = 0;
boards.add(new Board(newBlocks));
}
return boards;
}
// string representation of the board (in the output format specified below)
public String toString() {
StringBuilder s = new StringBuilder();
s.append(N).append("\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s.append(String.format("%2d ", blocks[i][j]));
}
s.append("\n");
}
return s.toString();
}
// expected value for row, column (i, j) indexes
private int rowColumnToExpectedValue(int i, int j) {
return i * N + j + 1;
}
// row, column (i, j) indexes for value
private int[] valueToRowColumn(int val) {
val -= 1;
assert val > -1;
int[] rowColumn = new int[2];
rowColumn[0] = val / N;
rowColumn[1] = val - (rowColumn[0] * N);
return rowColumn;
}
private int[][] blocksCopy(int[][] blocks) {
int[][] newBlocks = new int[N][N];
for (int i = 0; i < N; i++) {
System.arraycopy(blocks[i], 0, newBlocks[i], 0, N);
}
return newBlocks;
}
public static void main(String[] args) {
int[][] blocks2 = new int[][] {
{3, 0, 4},
{2, 5, 8},
{7, 1, 6}
};
Board board2 = new Board(blocks2);
System.out.println(board2.twin());
}
}