简体   繁体   English

在2D ArrayList中移动元素

[英]Shift elements in 2D ArrayList

I have 2D ArrayList which was filled with elements (objects which contain images etc.) so the 2D array was full. 我有2D ArrayList ,其中充满了元素(包含图像等的对象),因此2D数组已满。 After calling removing functions my array looks like the picture on the left side; 调用remove函数后,我的数组看起来像左侧的图片; on the right side you can see the desired result. 在右侧,您可以看到所需的结果。 Could someone please give me the idea how to reorganize my array as you can see on the picture? 有人可以给我一个想法,如您在图片上看到的那样如何重组我的阵列吗?

理想的结果

The idea was to go from to bottom to top. 这个想法是从下到上。 If I find the gap (the gap means that I set the background of element to null , respectively, imageIcon is set to null ) I will switch it for the previous element. 如果我发现的间隙(该间隙指我设置元件的背景null分别imageIcon被设置为null ),我将其切换为前一个元素。 And because I have switched it I have to do it for the whole column. 而且因为我已经切换了它,所以我必须在整个专栏中都这样做。 Problem is, when they are 2 or more gaps and also, this algorithm does nothing. 问题是,当它们之间有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--;

                }

            }
        }
    }

The arrayed data size is limited to 10x8 because of my gameboard panel. 由于我的游戏面板,排列的数据大小限制为10x8。 The items in array are not distinguishable, they only have different backgrounds (type of JLabel component). 数组中的项是不可区分的,它们只有不同的背景( JLabel组件的类型)。 The items have to "fall from top to down". 这些项目必须“从上到下下降”。

PS: I am creating a clone of Bejeweled PS:我正在创建“宝石迷阵”的副本

Shot1

Shot2

From what you have shown in the pictures, you want the column's elements to be "dropped to bottom"? 根据您在图片中显示的内容,您希望将列的元素“放到底部”吗? If that is the case, you should probably use a regular 2D array instead of ArrayList , with an array for each of your columns , and assume the bottom is indexed 0 - why? 如果是这种情况,您可能应该使用常规的2D数组而不是ArrayList ,每个都使用一个数组,并假定底部的索引为0为什么? because ArrayList doesn't have fixed size, and your problem statement shows you want the container to be of fixed size. 因为ArrayList大小不固定,并且您的问题语句表明您希望容器的大小固定。 The solution would then be (roughly, because you shown only a part of your code, not a SSCCE): 那么解决方案将是(大致来说,因为您只显示了代码的一部分,而不是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];

This is a crude bubble sort, suitable for small arrays. 这是一种粗气泡分类,适用于小型阵列。 There are other solutions possible (as this is a sorting problem by itself - you may look up qsort for this), but this one is arguably the simplest. 还有其他可能的解决方案(因为这本身就是一个排序问题-您可能会为此查找qsort),但是可以说这是最简单的解决方案。

Note: You may implement the very same solution for ArrayList s, yet I strongly advocate against it. 注意:您可以为ArrayList实现完全相同的解决方案,但我强烈建议不要这样做。 Using nested ArrayList s to mimic multi-dim arrays is seldom a good idea - it'll create the arrays anyway, but you'll get a large overhead, making the code both slower and less readable - anyway you can do so by replacing [] s with get() / set() etc. 很少使用嵌套的ArrayList来模仿多维度数组-它会创建数组,但会产生大量开销,使代码变慢且可读性差-无论如何,您都可以通过替换[] s与get() / set()等。

For the sake of reference: 为了参考:

//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));

or simply, by providing a comparator: 或者简单地通过提供比较器:

//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
    }
  });

For more info, see docs for Collections.sort() & Comparator . 有关更多信息,请参阅Collections.sort()Comparator的文档。

Also, if this is indeed for Bejewelled clone - you may consider doing the "dropping" by doing an iteration dropping all jewels with an empty field beneath by one step, counting the amount of dropped jewels, and repeating this iteration till the amount of drops == 0. That's the algo I used in my clone in the days of the past. 另外,如果这确实适用于“宝石迷阵”克隆,则可以考虑通过以下方式进行“掉落”:将所有空旷区域下方的珠宝向下迭代一步,计算掉下的珠宝数量,然后重复此迭代直到掉下数量==0。这就是过去我在克隆中使用的算法。

As @vaxquis has already mentioned, it's better to rewrite your code in some more elegant way. 正如@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;
            }

        }
    }
}

Besides the algorithm issues addressed by the other answers, your main problem is that you never change anything in the arrays. 除了其他答案解决的算法问题之外,您的主要问题是您永远不会更改数组中的任何内容。 The following code just moves some values between local variables: 以下代码仅在局部变量之间移动一些值:

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;

You probably have a setItem() method to set things back into a Position object? 您可能有一个setItem()方法来将内容设置回Position对象? Then a swap would be: 那么交换将是:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM