【问题标题】:Optimizing code for calculating the best move for Animal Java优化用于计算 Animal Java 最佳移动的代码
【发布时间】:2017-06-05 23:55:14
【问题描述】:
/**
 * 
 * @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;
}

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

羊吃草,避开狼 狼猎羊,没有敌人

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

【问题讨论】:

  • 我发帖后发现了一个改进,距离我在开始时做了一个变量,而不是为每个循环单独一个变量(双倍距离)。

标签: java optimization


【解决方案1】:

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

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

然后,Wolf 实体将有一个 doStuff() 的实现,它可以做狼的东西,而Plant 实体将有它自己的 doStuff() 的实现,它可以做植物的东西。

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

【讨论】:

    猜你喜欢
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2017-05-11
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多