-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEightPuzzle.java
174 lines (156 loc) · 5.1 KB
/
EightPuzzle.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
package agenteIA;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Formatter;
import java.util.List;
import java.util.Random;
/**
* El problema del 8 puzzle
*/
public class EightPuzzle implements Problem<EightPuzzle.Board, Action>
{
/**
* Tablero del 8 puzzle
*/
public static class Board
{
/**
* Contiene el valor de la baldosa en la posicion dada.
* Las casillas del tablero se enumera de 0..8 como se muestra:
* <pre>
* 0 1 2
* 3 4 5
* 5 7 8
* </pre>
*/
private int[] tiles = new int[9];
/**
* Constructor de un tablero aleatorio.
*/
public Board()
{
tiles = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8};
Random random = new Random();
do {
for (int i = 0; i < tiles.length; i++) {
int j = random.nextInt(tiles.length);
int x = tiles[i];
tiles[i] = tiles[j];
tiles[j] = x;
}
} while (!isSolvable());
}
/**
* Crea un tablero con una configuracion dada
*/
public Board(int[] tiles)
{
System.arraycopy(tiles, 0, this.tiles, 0, tiles.length);
}
/**
* Devuelve si la configuracion dada es solucionable o no.
* Existe un conocido teorema que un 8-puzzle es solucionable
* si el numero de inversiones es par.
*/
public boolean isSolvable()
{
boolean solvable = true;
for (int i = 0; i < tiles.length; i++) {
if (tiles[i] == 0) continue;
for (int j = i + 1; j < tiles.length; j++) {
if (tiles[j] == 0) continue;
if (tiles[i] > tiles[j]) solvable = !solvable;
}
}
return solvable;
}
/**
* Devuelve la suma de la distancia manhattan de cada baldosa
*/
public int manhattan()
{
int result = 0;
for (int i = 0; i < 9; i++) {
result += Math.abs(tiles[i]/3-i/3)+Math.abs(tiles[i]%3-i%3);
}
return result;
}
/**
* Devuelve una sencilla representacion textual del tablero.
*/
@Override
public String toString()
{
return new Formatter().format("%d%d%d\n%d%d%d\n%d%d%d",
tiles[0], tiles[1], tiles[2],
tiles[3], tiles[4], tiles[5],
tiles[6], tiles[7], tiles[8])
.out().toString();
}
/**
* Redefine el equals del objeto
*/
@Override
public boolean equals(Object o)
{
return o instanceof Board && Arrays.equals(tiles, ((Board)o).tiles);
}
/**
* Redefine hashCode del objeto
*/
@Override
public int hashCode()
{
return Arrays.hashCode(tiles);
}
}
/**
* Devuelve las acciones permitidas para un estado del tablero dado
*/
@Override
public List<Action> actionsFor(Board board)
{
List<Action> legalActions = new ArrayList<Action>();
int blankPosition = 0;
while (board.tiles[blankPosition] != 0) blankPosition++;
if (blankPosition > 2) legalActions.add(Action.UP);
if (blankPosition % 3 != 0) legalActions.add(Action.LEFT);
if (blankPosition % 3 != 2) legalActions.add(Action.RIGHT);
if (blankPosition < 6) legalActions.add(Action.DOWN);
return legalActions;
}
/**
* Devuelve el tablero que se obtendría al aplicar la accion dada.
*/
@Override
public Board go(Board board, Action action)
{
int offset = 0;
switch (action) {
case UP: offset = -3; break;
case DOWN: offset = 3; break;
case RIGHT: offset = 1; break;
case LEFT: offset = -1; break;
}
int blankPosition = 0;
while (board.tiles[blankPosition] != 0) blankPosition++;
int newBlankPosition = blankPosition + offset;
Board result = new Board(board.tiles);
result.tiles[blankPosition] = board.tiles[newBlankPosition];
result.tiles[newBlankPosition] = 0;
return result;
}
/**
* Devuelve si la baldosa blanca esta el la parte superior izquierda
* y las baldosas del 1 al 8 aparecen en orden de izquierda a derecha
* y de arriba a abajo
*/
@Override
public boolean isGoal(Board board)
{
return Arrays.equals(board.tiles, new int[]{0,1,2,3,4,5,6,7,8});
}
public static void main(String[] args) {
EightPuzzle Ep = new EightPuzzle();
}
}