How to rewrite these 3 methods to be reusable? [cl

2019-09-17 01:01发布

问题:

I'm making a tankgame. In my PlayPanel class I wrote this code, as you can see it is mostly the same but it's used for 3 different ArrayLists.

I would really like to know how to write this method once only in order to reuse it for all the ArrayLists because it seems so untidy.

//obstacles
for (int i = 0 ; i<obstacles.size() ; i++) {
    if (obstacles.get(i).dood)
        obstacles.remove(i);
}
//bullets
for (int i = 0; i< bullets.size(); i++) {
    bullets.get(i).redraw();
    //de positie van elke kogel wordt geupdate.
    if(bullets.get(i).OutOfScreen()) {
        bullets.remove(i);//uit scherm -> verwijdert en verplaatst
    }
}

for (int i = 0; i< enemyBullets.size(); i++) {
    enemyBullets.get(i).redraw();
    if(enemyBullets.get(i).OutOfScreen()) {
        enemyBullets.remove(i);
    }
}

I thought about writing this, but it doesn't seem right:

public void remove(ArrayList object) {
    for (int i = 0; i< object.size(); i++) {
        object.get(i).redraw();
        if(object.get(i).OutOfScreen()) {
            object.remove(i);
        }
    }
}

Also, I don't really know how to call this method to use it for one of the ArrayLists.

回答1:

If you use Java 8, you can filter the list with by passing a Predicate.

public class Helper {
    //removePredicate can be any function that returns a boolean that will help
    //to filter the data
    static <T> void remove(List<T> list, Predicate<? super T> removePredicate) {
        List<T> filteredList = list.stream()
            .filter(removePredicate)
            .collect(Collectors.toList());
        list.clear();
        list.addAll(filteredList);
    }
}

Here's an example of how to use method above for List<Bullet>:

//sample implementation for Bullet class
class Bullet {
    int value;
    public Bullet(int value) { this.value = value; }
    public boolean outOfScreen() {
        return value > 10;
    }
    @Override public String toString() {
        return String.format("Bullet: {%d}", value);
    }
}

//somewhere you need to execute this code...
//initialize your List
List<Bullet> bulletList = new ArrayList<>(Arrays.asList(
    new Bullet(15), new Bullet(1), new Bullet(20), new Bullet(6)));
//show the contents of the list
System.out.println(bulletList);
//remove the elements by using whatever you want/need
//see how you can pass any way to filter the elements of the list
Helper.remove(bulletList, b -> !b.outOfScreen());
//show the contents of the list again to show how it was filtered
System.out.println(bulletList);

The benefit of using this approach is that you don't need class inheritance or something like that.



回答2:

The second and third loop can be combined in a single piece of code as shown as follows.

  1. You have a parent class (Abstract or Interface) called ParentBullets.
  2. Bullets and EnemyBullets are child classes of ParentBullets class.

Now via Polymorphism you can do the following

public void loop(List<? extends ParentBullets> bullets){
for (int i = 0; i< bullets.size(); i++) {
    bullets.get(i).redraw();
    //de positie van elke kogel wordt geupdate.
    if(bullets.get(i).OutOfScreen()) {
        bullets.remove(i);//uit scherm -> verwijdert en verplaatst
    }
}
}

Now you can have bullets and enemybullets as a collection is an ArrayList and you can call the above method like:

loop(bullets); or loop(enemyBullets);



回答3:

Your method remove won't work, since you are giving as an argument an ArrayList of Objects. They don't have methods redraw and OutOfScreen. What you could do is define an interface, say GameObject, containing these methods, and make Bullet implement it. Change signature of remove to

public void remove(ArrayList<? extends GameObject> object) {
    //rest as before
}

Then you can call for example remove(bullets) or remove(enemyBullets).