У меня есть 2D ArrayList
который был заполнен элементами (объектами, которые содержат изображения и т.д.), Поэтому 2D-массив был заполнен. После вызова функций удаления мой массив выглядит как изображение с левой стороны; с правой стороны вы можете увидеть желаемый результат. Может кто-нибудь, пожалуйста, дайте мне идею, как реорганизовать мой массив, как вы можете видеть на картинке?
Идея заключалась в том, чтобы идти снизу вверх. Если я нахожу пробел (разрыв означает, что я устанавливаю фон элемента imageIcon
null
, соответственно, для параметра imageIcon
установлено значение null
), я переключу его на предыдущий элемент. И поскольку я переключил его, я должен сделать это для всей колонки. Проблема в том, что когда они имеют 2 или более пробелов, а также этот алгоритм ничего не делает.
for (int i = 0; i < 10; i++) {
for (int j = 7; j > 0; j--) {
Item currentItem = this.elements.get(j).get(i).getItem();
if (currentItem.getBack().getIcon() == null) {
int count = j;
while (count > 1) {
Position temp = this.elements.get(count).get(i);
Position zero = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
zero = previous;
previous = temp;
count--;
}
}
}
}
Размер массива данных ограничен 10x8 из-за моей панели игровых панелей. Элементы массива не различаются, они имеют только разные фоны (тип компонента JLabel
). Элементы должны "падать сверху вниз".
PS: Я создаю клон Bejeweled
Из того, что вы показали на снимках, вы хотите, чтобы элементы столбцов были "опущены вниз"? Если это так, вы, вероятно, должны использовать обычный 2D-массив вместо ArrayList
, с массивом для каждого из ваших столбцов и предположить, что нижняя часть индексируется 0
- почему? потому что ArrayList
не имеет фиксированного размера, а ваш оператор проблемы показывает, что контейнер должен иметь фиксированный размер. Тогда решение будет (грубо говоря, потому что вы указали только часть своего кода, а не SSCCE):
//Item[][] items;
for( Item[] arr : items )
for( int i = arr.length - 2; i >= 0; i-- )
if ( arr[i] == null ) // or arr[i].getBack().getIcon() == null or whatever
for( int j = i; j < arr.length - 1; j++ )
arr[j] = arr[j+1];
Это сырой пузырьковый вид, подходящий для небольших массивов. Возможны и другие решения (поскольку это проблема сортировки сама по себе), вы можете найти qsort для этого), но этот, возможно, самый простой.
Примечание. Вы можете реализовать одно и то же решение для ArrayList
s, но я решительно выступаю против него. Использование вложенного массива ArrayList
для имитации многоуровневых массивов редко является хорошей идеей - в любом случае они будут создавать массивы, но вы получите большие накладные расходы, делая код более медленным и менее читаемым - в любом случае вы можете это сделать, заменив []
с get()
/set()
и т.д.
Для справки:
//ArrayList<ArrayList<Item>> items;
//int columnHeight;
for( ArrayList<Item> arr : items )
for( int i = columnHeight - 2; i >= 0; i-- )
if ( arr.get(i) == null ) //or arr.get(i).getIcon()==null or whatever
for( int j = i; j < columnHeight - 1; j++ )
arr.set(j, arr.get(j+1));
или просто путем предоставления компаратора:
//ArrayList<ArrayList<Item>> items;
//int columnHeight;
for( ArrayList<Item> arr : items )
Collections.sort(arr, new Comparator<Item>() {
@Override
public int compare(Item i1, Item i2) {
return ...; // place the sorting rule here
}
});
Дополнительные сведения см. В документах для Collections.sort() & Comparator.
Кроме того, если это действительно клон Bejeweled - вы можете подумать о том, чтобы "сбросить", выполнив итерацию, сбросив все драгоценности с пустым полем под одним шагом, подсчитав количество упавших драгоценностей и повторив эту итерацию до количества капель == 0. То, что я использовал в моем клоне во времена прошлого.
Как уже упоминалось @vaxquis, лучше переписать свой код более элегантным способом.
for (int i = 0; i < 10; i++) {
// Perfoming bubble sort for each column
boolean swapped = true;
for(int j = 6; j > 0 && swapped; j--) {
swapped = false;
for (int k = 0; k < j; k++) {
Item currentItem = this.elements.get(k).get(i).getItem();
Item nextItem = this.elements.get(k+1).get(i).getItem();
if (currentItem.getBack().getIcon() != nextItem.getBack().getIcon()) {
swap(currentItem, nextItem); // implement this yourself
swapped = true;
}
}
}
}
Помимо проблем с алгоритмом, рассмотренных другими ответами, основная проблема заключается в том, что вы никогда ничего не меняете в массивах. Следующий код просто перемещает некоторые значения между локальными переменными:
Position temp = this.elements.get(count).get(i);
Position zero = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
zero = previous;
previous = temp;
Вероятно, у вас есть метод setItem()
чтобы вернуть объект в объект Position
? Тогда будет своп:
Position current = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
Item temp = current.getItem();
current.setItem(previous.getItem();
previous.setItem(temp);