Исключение в потоке «основной» java.lang.IndexOutOfBoundsException: индекс: 0, размер: 0

1

Я пытаюсь написать программу, которая может решить проблему с 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());

     }

}
  • 2
    Вы выбираете емкость до 16, а не размер. Вместимость не то же самое, что размер.
  • 2
    Как примечание, вы, вероятно, не должны делать фактическое решение в конструкторе. Конструкторы используются для подготовки / инициализации некоторых переменных. Вы можете рассмотреть возможность перемещения логической части к какому-либо методу «решения».
Показать ещё 1 комментарий
Теги:
arraylist

3 ответа

3

Что я не понимаю, так это то, как размер 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 элементов, вам придется добавлять эти элементы по одному.

1

Размер коллекции и емкость - это две разные концепции.

  • емкость представляет собой максимальный размер элементов, которые коллекция может хранить без перераспределения.
  • size представляет текущее количество элементов в коллекции.

IndexOutOfBoundsException говорит, что вы пытаетесь получить доступ к элементу с индексом, который не существует в коллекции.

  • 0
    @Jesper Разве первый цикл for в классе решателя не гарантирует, что значение i никогда не будет> = к размеру?
  • 0
    Исключение выдается на строку removeTemp = queue.remove (removeIndex);
Показать ещё 3 комментария
0

пожалуйста, используйте приведенный ниже код в Solver.java

if (! queue.isEmpty()) removeTemp = queue.remove(removeIndex); иначе перерыв;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню