Я пытаюсь написать программу, которая может решить проблему с 8 головоломками. Я использую алгоритм A * для поиска решения. Я много раз пересматривал свой код, а также пытался внести некоторые изменения. Даже мои друзья пытались помочь мне найти ошибку, но они не смогли. Я все еще не понимаю, где я ошибся. Я использовал javadocs, чтобы увидеть, что я сделал что-то неправильно, даже это не решает мою проблему. Я создал три класса для решения этой проблемы.
import java.util.*;
public class Solver implements Iterable<State>
{
ArrayList<State> queue,solQueue;
public int sol[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 0 } };
int temp[][],i;
int moves;
int leastPriority,removeIndex;
State removeTemp;
public Solver(State initial)
{
queue = new ArrayList<State>();
solQueue = new ArrayList<State>();
queue.ensureCapacity(16);
solQueue.ensureCapacity(16);
temp = new int[3][3];
i=1;
leastPriority = 100;
removeTemp=initial;
queue.add(removeTemp);
Iterator<State> qu = queue.iterator();
while(removeTemp.m!=sol)
{
leastPriority = 100;
i=0;
queue.iterator();
for (State s : queue)
{
if((s.mh + s.count) <leastPriority)
{
leastPriority = (s.mh + s.count);
removeIndex = i;
}
if(qu.hasNext())
i++;
}
for(State s : removeTemp.neighbours() )
{
queue.add(s);
}
removeTemp=queue.remove(removeIndex);
solQueue.add(removeTemp);
}
this.moves();
this.solution();
}
public int moves()
{
System.out.print("Solution found out in "+ moves+" moves");
moves = removeTemp.count;
return moves;
}
public Iterable<State> solution()
{
for(State s : solQueue)
{
System.out.println(s.m);
System.out.println("");
}
return solQueue;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Iterator iterator() {
return null;
}
}
И JVM бросает исключение.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0,Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Solver.<init>(Solver.java:41)
at Main.main(Main.java:13)
Что я не понимаю, так это то, как размер ArrayList равен 1, если я явно укажу его на 16.
Класс состояния имеет эвристическую функцию, которая позволяет сделать алгоритм эффективным. Следующим является класс состояний.
import java.util.ArrayList;
import java.util.Iterator;
public class State implements Iterable<State>
{
public int sol[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 0 } };
int m[][], bi, bj, count, priority, si, sj;
int i,j,tempm[][];
int mh = 0;
boolean isInitialState, isRepeatedState;
State previousState, tempState;
ArrayList<State> neighbourStates;
public State(State s, int c, int[][] array)
{
neighbourStates = new ArrayList<State>();
neighbourStates.ensureCapacity(16);
tempState =this;
m = new int[3][3];
m=array;
if (s == null)
{
isInitialState = true;
count = 0;
previousState =null;
}
else
{
previousState = s;
count = c+1;
}
this.findZero();
this.manhattanHeuristic();
}
private void findZero()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
if(m[i][j]==0)
{
bi=i;
bj=j;
}
}
}
private void manhattanHeuristic() {
int n = 1;
mh = 0;
for (int i = 0; i < 3; i++)
Z: for (int j = 0; j < 3; j++) {
if ((i == bi) && (j == bj)) {
continue Z;
}
else if (m[i][j] == n) {
n++;
}
else {
this.getSolutionIndex();
mh = mh + Math.abs(i - si) + Math.abs(j - sj);
}
}
}
void getSolutionIndex() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (m[i][j] == 0) {
si = i;
sj = j;
}
}
}
public Iterable<State> neighbours()
{
tempm = m;
this.up();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.down();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.left();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
this.right();
if(!(equals(tempm)))
{
tempState = new State(this,count,tempm);
neighbourStates.add(tempState);
}
return neighbourStates;
}
public boolean equals(int s[][])
{
if((isInitialState==false)&&(previousState.m == s))
return true;
else
return false;
}
@Override
public Iterator<State> iterator() {
// TODO Auto-generated method stub
return null;
}
public void up()
{
if ((bi > 1) && (bi < 2) && (bj < 3)&& (bj > 1))
{
i = bi;
i = i + 1;
this.move(i,bj);
}
}
public void down()
{
if ((bi > 2) && (bi < 3) && (bj < 3) && (bj > 1))
{
i = bi;
i = i - 1;
this.move(i,bj);
}
}
public void left()
{
if ((bi > 1) && (bi < 3) && (bj < 2)&& (bj > 1)) {
j = bj;
j = j + 1;
this.move(bi, j);
}
}
public void right()
{
if ((bi > 1) && (bi < 3) && (bj < 3) && (bj > 2)) {
j = bj;
j = j - 1;
this.move(bi, j);
}
}
public void move(int x, int y) {
{
tempm = m;
}
if ((tempm[x + 1][y] == 0) || (tempm[x - 1][y] == 0) || (tempm[x][y + 1] == 0)|| (tempm[x][y - 1] == 0)) {
tempm[bi][bj] = tempm[x][y];
tempm[x][y] = 0;
bi = x;
bj = y;
}
}
}
И, наконец, класс с основной функцией.
import java.util.Scanner;
public class Main {
public static void main(String[] args)
{
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int[][] tiles = new int[3][3];
System.out.println("Enter the elements");
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
tiles[i][j] = sc.nextInt();
State initial = new State(null,0,tiles);
Solver solver = new Solver(initial);
solver.solution();
System.out.println("Minimum number of moves = " + solver.moves());
}
}
Что я не понимаю, так это то, как размер ArrayList равен 1, если я явно укажу его на 16.
Вы не задали размер ArrayList
до 16. Вы задали емкость:
queue.ensureCapacity(16);
solQueue.ensureCapacity(16);
Это не делает ArrayList
размером 16.
ArrayList
имеет массив для хранения своих данных. Когда вы добавляете больше элементов в ArrayList
и его внутренний массив заполнен, ему придется выделять больший массив и копировать содержимое того, что он в настоящее время удерживает, плюс новый элемент.
Емкость ArrayList
- это минимальный размер, который имеет внутренний массив. Вы можете использовать ensureCapacity
чтобы убедиться, что ArrayList
не нужно слишком часто изменять размер (изменение размера и копирование содержимого - дорогостоящая операция). Таким образом, ensureCapacity
- это призыв, который вы делаете, чтобы заставить его работать эффективно.
Это не означает, что ArrayList
имеет 16 элементов; он только гарантирует, что ArrayList
имеет место, по меньшей мере, для 16 элементов.
Если вы хотите, чтобы ArrayList
имел 16 элементов, вам придется добавлять эти элементы по одному.
Размер коллекции и емкость - это две разные концепции.
IndexOutOfBoundsException
говорит, что вы пытаетесь получить доступ к элементу с индексом, который не существует в коллекции.
пожалуйста, используйте приведенный ниже код в Solver.java
if (! queue.isEmpty()) removeTemp = queue.remove(removeIndex); иначе перерыв;