2015-03-22 5 views
1

Я пытаюсь написать программу, которая может решить проблему с 8 головоломками. Я использую алгоритм A * для поиска решения. Я много раз пересматривал свой код и также пытался внести некоторые изменения. Даже мои друзья пытались помочь мне найти ошибку, но они не смогли. Я все еще не понимаю, где я ошибся. Я использовал javadocs, чтобы увидеть, что я сделал что-то неправильно, даже это не решает мою проблему. Я создал три класса для решения этой проблемы.Исключение из потока «main» java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

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, а не размер. Емкость - это не то же самое, что размер. – Jesper

+1

Как побочное примечание, вы, вероятно, не должны выполнять фактическое решение в конструкторе. Конструкторы используются для подготовки/инициализации некоторых переменных. Вы можете подумать о переносе логической части на какой-то «решающий» метод. –

+0

@ Jesper Thanx для информации. – adi71094

ответ

1

Размер сбора и емкости 2 разные понятия.

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

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

+0

@Jesper Не первый цикл цикла в классе решателя гарантирует, что значение i никогда не будет> = до размера? – adi71094

+0

Исключение выбрано на строке removeTemp = queue.remove (removeIndex); – Crazyjavahacking

+0

Правда, но removeIndex = i, тогда как удалить индекс будет больше, чем i? – adi71094

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 элементов, вам нужно будет добавить эти элементы по одному.

0

пожалуйста, попробуйте следующий код в Solver.java

если removeTemp = queue.remove (removeIndex) (queue.isEmpty (!)); прочее break;

Смежные вопросы