优化用于计算Animal Java最佳移动的代码

时间:2017-06-05 15:45:07

标签: java optimization

/**
 * 
 * @param listOfEntities - The list to be checked
 * @param entity - The entity to base the searching off of.
 * @return - the Point of the highest scoring goal
 * 
 * TODO: Make this code better, it relies too much on instanceof and is not OOP.
 *       
 */
protected Point getBestMove(List<Point> listOfEntities,Entity entity) {
    //Store the position of the highest valued prey.
    Point highestScore = null;

    // Check if the entity passed in is a Sheep, if it is
    // then loop through the map within the line of sight
    // of this animal and then score individually.
    // Based on the result move in a direction that is benifitial.
    if (entity instanceof Sheep) {
        // The scoring map using a Point, Double system.
        Map<Point, Double> bestMoveMap = new HashMap<>();

        //Loop through for every entity position in listOfEntities
        for(Point currentEntity : listOfEntities) {
            //Put this current entity with a basevalue of 2400.
            bestMoveMap.put(currentEntity, 2400.0);

            // Loop X and Y within line of sight (- since we want both directions)
            for (int xPos = - lineOfSight; xPos <= lineOfSight; xPos++) {
                for (int yPos = - lineOfSight; yPos <= lineOfSight; yPos++) {
                    // Get the starting point of this entity
                    double points = bestMoveMap.get(currentEntity);

                    // Get the distance between this entity and the goal entity.
                    Point goalPoint = new Point(currentEntity.x + xPos,currentEntity.y + yPos);

                    // Store all entities in a list within range.
                    List<Entity> entities = pasture.getGrid().get(goalPoint);

                    //If list is not empty or null
                    if(entities != null && entities.isEmpty() == false) {
                        //Loop through all the entities
                        for(Entity e : entities) {
                            //If it is a wolf.
                            if(e instanceof Wolf) {
                                //Score depending on distance using a formula.
                                double distanceToWolf = goalPoint.distance(currentEntity);

                                // Calculate using a formula where we factor in the distance to the wolf.
                                points = points + (1000 / (1 + distanceToWolf));

                                // Put this entity with the position.
                                bestMoveMap.put(currentEntity, points);
                            }
                            // If it is a plant.
                            if(e instanceof Plant) {
                                //Score depending on distance using a formula.
                                double distanceToPlant = goalPoint.distance(currentEntity);

                                points = points - (100 / (1 + distanceToPlant));
                                bestMoveMap.put(currentEntity, points);
                            }
                        }
                    }
                }            
            }}

        //Minimum score.
        Map.Entry<Point, Double> minScore = null;

        // Get the highest scored value and set minScore aswell as highestScore.
        // Since Java 8 you could do this:
        // Collections.max(bestMoveMap.entrySet(), Map.Entry.comparingByValue()).getKey();
        for (Map.Entry<Point, Double> entry : bestMoveMap.entrySet()){
            if (minScore == null || minScore.getValue() > entry.getValue()){
                // Set highestScore to that and minScore to that entry.
                minScore = entry;
                highestScore= minScore.getKey();
            }
        }
    }
    // If the entity is a Wolf
    if(entity instanceof Wolf){
        Map<Point, Double> bestMoveMap = new HashMap<>();
        for(Point thisPoint : listOfEntities){
            bestMoveMap.put(thisPoint, 2000.0);

            for (int x = -lineOfSight; x <= lineOfSight; x++) {
                for (int y = -lineOfSight; y <= lineOfSight; y++) {
                    Point p = new Point(thisPoint.x + x,thisPoint.y + y);
                    List<Entity> l =pasture.getGrid().get(p);
                    if(l!=null){
                        for(Entity e:l){

                            //Only interested in Sheeps
                            if(e instanceof Sheep){
                                double distanceToSheep=p.distance(thisPoint);
                                double points=bestMoveMap.get(thisPoint);
                                points = points -(10000/(0.1+distanceToSheep));
                                bestMoveMap.put(thisPoint, points);
                            }
                        }
                    }
                }
            }
        }
        // Set highestScore to the best Point.
        Map.Entry<Point, Double> min = null;
        for(Map.Entry<Point, Double> entry : bestMoveMap.entrySet()) {
            if (min == null || min.getValue() > entry.getValue()) {
                min = entry;
                highestScore= min.getKey();
            }
        }
    }

    // Return the highest score, the Point that scored the highest
    return highestScore;
}

我在上面找到了这个代码,它为动物找到了最好的新Point。基本思路是:

羊吃草,避免狼群 狼群捕杀绵羊并且没有敌人

这很长,我想知道是否有任何方法可以缩短或改善它?我觉得好像&#34; instanceof&#34;是一个坏习惯,但我不知道该怎么做,否则或用什么来取代它。特别是因为代码在许多方面非常相似。也许我可以用某种方式结合它?

1 个答案:

答案 0 :(得分:0)

避免instanceof的方法是将功能移到类中并使用继承和多态。

因此,您可以调用if( e instanceof Wolf ) { do wolfy stuff... } else if( e instanceof Plant ) { do plant stuff... }而不是e.doStuff()

然后,Wolf实体将具有doStuff()的实现,它可以执行wolfy,而Plant实体将拥有自己的doStuff()实现,它可以生成植物。

当然,基类Entity会声明public abstract doStuff();,以便WolfPlant可以覆盖它。