水气球大战


12

该“山上之王”游戏是一种策略游戏,您必须在其中扔水气球,并避免被水溅到。目标是获得最多的积分。您将得到一张野外图和水气球的位置。您可以返回要在某个方向上击打水气球(如果距离足够近)或要在某个方向上移动。

具体来说:水气球将从(0, 0)30个单位的高度开始下降。如果水气球撞到地面,将随机选择一名选手输掉4点,并向靠近气球的人分配更多的重量。此外,最后一次击中气球的玩家将获得3分。因此,如果您直接向下击气球,您很可能会损失1分。

您将编写一个扩展类Player。您需要实现构造函数。构造函数如下所示:

public Player1() {
    super(/* Some numbers */ 3, 3, 4)
}

这些数字是doubles。第一个数字代表玩家的速度,第二个数字代表力量,第三个数字代表运气。这些数字的总和不得超过10,并且任何数字都不得小于等于零。

其次,您必须实现该move方法。这是一个示例move方法:

@Override
protected Action move(Map<Player, Point2D> map, Balloon b) {
    // Get my own location
    Point2D myself = map.get(this);
    // If I'm close enough to the balloon
    // then hit the balloon
    if (myself.distanceSq(b.getLocation()) <= 16) {
        double d = (r.nextDouble() - 0.5) * 3;
        // Random y direction, z direction is what's left 
        return new Hit(0, d, Math.sqrt(9 - d*d));
    } else {
        double diffX = b.getLocation().getX() - myself.getX(),
                diffY = b.getLocation().getY() - myself.getY();
        // Move towards the balloon
        return new Movement(Math.signum(diffX)*3/Math.sqrt(2), Math.signum(diffY)*3/Math.sqrt(2));
    }
}

这里有很多重要的事情。首先,请注意,该字段以形式传递Map<Player, Point2D>。字段是无限的-您可以走多远没有限制。它不是二维数组或类似的东西。此外,这意味着您将使用非整数坐标作为您的位置。完全可以

另一个结果是玩家和气球可能重叠。实际上,两个玩家可能在完全相同的位置!

气球具有一定的速度和方向。通常,它将以3个单位/步的速率下降。它还沿一个x方向和y方向移动。返回a时Hit,您将沿推气球的x,y和z方向传递。你不能打气球的高度大于10或者其距离您(仅在两个维度)大于4.此外,如果这是真的,x^2 + y^2 + z^2 > s^2哪里s是你的力量,和xyz是你打方向,您的操作将被丢弃。击打的力会被介于0和之间的随机数放大luck(这意味着如果运气不好,击打力可能会下降)。

同样,您可以返回Movement带有x和的y坐标(请注意,您不能跳跃)。如果您的速度x^2 + y^2 > s^2在哪里,s则您的操作将被丢弃。

如果水气球撞到地面,则将选择一个随机玩家,将更多的体重分配给最亲近的玩家,但减少那些拥有更多运气的玩家的体重。被选中的玩家将失去4分。

管制员:https : //github.com/prakol16/water-balloon-wars/tree/master

游戏持续1000步。最后,将有一个名为的文件log.out。将数据复制并粘贴到该小提琴中以查看游戏:https : //jsfiddle.net/prankol57/s2x776dt/embedded/result/

甚至更好的是,以3D方式查看:http : //www.brianmacintosh.com/waterballoonwars(感谢BMac)

在100(可能更多,但不是更少)游戏之后,得分总和最高的玩家获胜。

如果您想提交解决方案,则可能需要阅读https://github.com/prakol16/water-balloon-wars/tree/master上的特定细节。

编辑3/8

这些是目前的最终成绩(1000次迭代,不包括玩家1和2)。如果您编辑帖子,则可以发表评论,我将重做分数:

{
    class players.BackAndForth=-75.343,
    class players.Hydrophobe=-0.800,
    class players.KeepAway=-53.064,
    class players.Weakling=39.432,
    class players.Repeller=21.238,
    class players.LuckyLoser=-30.055,
    class players.AngryPenguin=-49.310
}

获胜者Weakling平均得到39分。第二名是Repeller21分。


1
当您击中气球时会发生什么?它如何移动?如果有多个人击中该怎么办?
基思·兰德尔

带有jsfiddle的动画非常好!
CommonGuy 2015年

顺便说一句,您应该将Player类中的方法设为final,否则提交可以覆盖它们。
CommonGuy 2015年

2
你倒speedstrength在播放器的构造函数。
Thrax

@ dirX,KeithRandall dirY,和dirZ((根据您的运气放大)只是添加到气球的速度中。如果有多个人击中它(不太可能),那么可能会获得3分的玩家将被认为是幸运的(请参阅详细信息)
soktinpk

Answers:


7

仿真器

我希望这可以,因为它实际上不是条目。我真的很喜欢视觉模拟器的想法,我想创建自己的视觉模拟器,使一次查看所有内容(完整的3D)变得容易一些。

2/28 9:06 AM PST:使用以下控件进行更新,颜色

3/4 8:47 AM PST:使用滑块进行更新,以提高仿真速度,并使得无需重新刷新页面即可开始新游戏(使用Ctrl-F5重新加载缓存的脚本)

在线ThreeJS Visualizer

在此处输入图片说明


3
+1000太神奇了。谢谢
soktinpk

您不是说Ctrl + F5而不是Shift + F5吗?
Timtech

看起来两者都可以在Chrome中使用。
BMac

7

来来回回

该机器人试图靠近并击中气球,直到其高度过低并试图逃脱。

package players;

import java.awt.geom.Point2D;
import java.util.Map;

import balloon.Action;
import balloon.Balloon;
import balloon.Player;
import balloon.Action.Hit;
import balloon.Action.Movement;

public class BackAndForth extends Player {

    static int round = 0;
    static int speed = 3;
    static int strength = 1;
    static boolean hit = false;
    static double previousHeight = 30.0;

    public BackAndForth() {
        super(speed, strength, 10 - speed - strength);
    }

    @Override
    protected Action move(Map<Player, Point2D> map, Balloon b) {

        round++;

        Point2D me = map.get(this);
        Point2D balloon = b.getLocation();

        double distanceX = balloon.getX() - me.getX();
        double distanceY = balloon.getY() - me.getY();
        double distance = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));

        double maxX = speed * distanceX / distance;
        double maxY = speed * distanceY / distance;

        if (previousHeight < b.getHeight())
            hit = false;

        if (hit || b.getHeight() < 3) {
            previousHeight = b.getHeight();
            return new Movement(-maxX, -maxY);
        } else {
            if (distance < 4 && b.getHeight() < 10) {
                hit = true;
                return new Hit(0, 0, strength);
            } else {
                if (Math.pow(distance, 2) <= Math.pow(speed, 2)) {
                    return new Movement(distanceX, distanceY);
                } else {
                    return new Movement(maxX, maxY);
                }
            }
        }

    }

}

看来您的机器人执行了非法动作,因此在执行操作时不执行任何操作。
Moogie'3

@soktinpk我更正了我的提交,现在应该做得更好。也感谢Moogie!
Thrax 2015年

我仍然发现您的机器人正在要求超越一切的可能。我已对您的帖子进行了修改以供审核。基本上,您将气球的位置用作运动。
Moogie 2015年

@Moogie对,非常感谢!
Thrax

乐意效劳。您的机器人非常擅长获得积极的成绩。做得好!
Moogie 2015年

5

愤怒的企鹅

这只企鹅很生气,因为他无法飞上气球,因此他试图将气球撞到站在他周围的人的脸上。

package players;

import java.awt.geom.Point2D;
import java.util.Map;
import java.util.Map.Entry;

import balloon.Action;
import balloon.Action.Hit;
import balloon.Action.Movement;
import balloon.Balloon;
import balloon.Player;

public class AngryPenguin extends Player {
    private static final double HIT_Z = 3;
    public AngryPenguin() {
        super(4, 4, 2);
    }

    @Override
    protected Action move(Map<Player, Point2D> map, Balloon balloon) {
        Point2D myself = map.get(this);

        double distanceX = balloon.getLocation().getX() - myself.getX();
        double distanceY = balloon.getLocation().getY() - myself.getY();
        double distance = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));

        if (balloon.getHeight() < 2) {
            double[] xy = shrink(distanceX, distanceY, Math.pow(getSpeed(),2));
            return new Movement(-xy[0], -xy[1]);
        } else if (distance <= 4 && balloon.getHeight() <= 10) {
            double lowestDistance = Double.MAX_VALUE;
            Point2D nearestPlayerLoc = null;
            for (Entry<Player, Point2D> e : map.entrySet()) {
                if (e.getKey() != this) {
                    double d = e.getValue().distanceSq(myself);
                    if (d < lowestDistance) {
                        lowestDistance = d;
                        nearestPlayerLoc = e.getValue();
                    }
                }
            }
            double dX = nearestPlayerLoc.getX() - myself.getX();
            double dY = nearestPlayerLoc.getY() - myself.getY();
            double d = Math.pow(getStrength() - HIT_Z, 2);
            double[] xy = shrink(dX, dY, d);
            return new Hit(xy[0], xy[1], -HIT_Z);
        } else {
            double[] xy = shrink(distanceX, distanceY, Math.pow(Math.min(getSpeed(), distance), 2));
            return new Movement(xy[0], xy[1]);          
        }
    }

    private double[] shrink(double x, double y, double totalPow) {
        double[] xy = new double[2];
        double ratio = y == 0 ? 0 : 
                       x == 0 ? 1 : Math.abs(x) / Math.abs(y);
        if (ratio > 1)
            ratio = 1/ratio;
        xy[1] = totalPow * ratio;
        xy[0] = totalPow - xy[1];
        xy[0] = x < 0 ? -Math.sqrt(xy[0]) : Math.sqrt(xy[0]);
        xy[1] = y < 0 ? -Math.sqrt(xy[1]) : Math.sqrt(xy[1]);
        return xy;
    }

}

这是要击败的。
凯文·沃克曼

5

虚弱

该机器人只能触摸气球,因为它是如此的脆弱,相反,它只是依靠自己的好运气。因此,它的性能类似于LuckyLoser(该机器人的灵感源于LuckyLoser)。

他似乎可以胜任包括Repeller在内的所有当前机器人。

package players;
import java.awt.geom.Point2D;
import java.util.Map;
import balloon.Action;
import balloon.Balloon;
import balloon.Player;
import balloon.Action.Hit;
import balloon.Action.Movement;

public class Weakling extends Player {

    static final private double STRENGTH = Double.MIN_VALUE;
    static final private double SPEED = 1.5;
    static final private double LUCK = 8.5;
    public Weakling() {
        super(SPEED,STRENGTH,LUCK);
    }

    protected Action move(Map<Player, Point2D> map, Balloon b) {
        Point2D start = map.get(this);
        Point2D balloon = b.getLocation();
        double distance = start.distance(balloon)+Double.MIN_VALUE;
        if(distance<=4 && b.getHeight()<=10){

            // just touch it :P
            return new Hit(0,0,0);
        }
        double x = start.getX()-balloon.getX();
        double y = start.getY()-balloon.getY();
        x /= distance;
        y /= distance;

        // move to directly underneath balloon
        x*=Math.min(SPEED, distance);
        y*=Math.min(SPEED, distance);
        return new Movement(-x, -y);
    }
}

编辑:降低速度以求好运


3

疏水物

这是可能的最简单的bot之一,但由于具有竞争力,我将发布它。

策略:好吧……这个机器人讨厌水,所以它就消失了。

由于该漫游器很少被飞溅,因此平均得分将低于0分。所有机器人的得分之和为-1 * [气球撞击地面],因此Hydrophobe的得分可能会高于平均水平。

package players;
import java.awt.geom.Point2D;
import java.util.Map;
import balloon.*;

public class Hydrophobe extends Player {
    public Hydrophobe() {super(8, 1, 1);}
    @Override
    protected Action move(Map<Player, Point2D> map, Balloon balloon) {
        return new Action.Movement(5.65,5.65);
    }
}

3

远离

只要其高度> 2,该玩家便会追逐该气球。只要它能击中气球,它就会立即将气球击中远离最近的玩家。当气球的高度小于2时,此播放器逃跑。

package players;

import java.awt.geom.Point2D;
import java.util.Map;

import balloon.Action;
import balloon.Balloon;
import balloon.Player;
import balloon.Action.Hit;
import balloon.Action.Movement;

public class KeepAway extends Player{

    public KeepAway() {
        super(5, 3, 2);
    }

    @Override
    protected Action move(Map<Player, Point2D> map, Balloon b) {

        Point2D myself = map.get(this);

        //if balloon is high up, run towards it
        if(b.getHeight() > 2){
            Point2D closest = getClosestPlayer(map);

            boolean canHit = b.getHeight() <= 10 && myself.distance(b.getLocation()) <= 4;

            //hit it when you can
            if(canHit){

                Point2D normHit = normalize(new Point2D.Double(myself.getX() - closest.getX(), myself.getY() - closest.getY()));
                Point2D forceHit = new Point2D.Double(normHit.getX() * getStrength(), normHit.getY() * getStrength());

                return new Hit(forceHit.getX(), forceHit.getY(), 0);
            }
            //if you can't hit it, keep running towards it
            else {

                Point2D normRun = normalize(new Point2D.Double(myself.getX() - b.getLocation().getX(), myself.getY() - b.getLocation().getY()));
                Point2D forceRun = new Point2D.Double(-normRun.getX() * getSpeed(), -normRun.getY() * getSpeed());
                return new Movement(forceRun.getX(), forceRun.getY());
            }
        }
        //if the balloon is low, run away
        else{
            Point2D normRun = normalize(new Point2D.Double(myself.getX() - b.getLocation().getX(), myself.getY() - b.getLocation().getY()));
            Point2D forceRun = new Point2D.Double(normRun.getX() * getSpeed(), normRun.getY() * getSpeed());
            return new Movement(forceRun.getX(), forceRun.getY());
        }

    }

    private Point2D getClosestPlayer(Map<Player, Point2D> map){

        double minDistance = Double.MAX_VALUE;
        Point2D closestPoint = null;
        Point2D myPoint = map.get(this);

        for(Player p : map.keySet()){
            if(this != p){

                if(myPoint.distance(map.get(p)) < minDistance){
                    minDistance = myPoint.distance(map.get(p));
                    closestPoint = map.get(p);
                }
            }
        }

        return closestPoint;
    }

    private Point2D normalize(Point2D p){
        double d = p.distance(0, 0);

        if(d == 0){
            return new Point2D.Double(0, 0);
        }

        return new Point2D.Double(p.getX()/d, p.getY()/d);
    }

}

编辑:我正在与Player1和Player2一起玩。在这种情况下,该玩家获胜,但是当我将其淘汰时输了。Booooo。


3

幸运输家

该机器人依靠其高分获得。如果它不在气球附近,它将朝着气球运行。一旦靠近气球,如果气球范围内还有至少2个其他玩家,他会将其刺入地面。否则,他会直接把它敲掉。

package players;
import java.awt.geom.Point2D;
import java.util.Map;

import balloon.Action;
import balloon.Balloon;
import balloon.Player;
import balloon.Action.Hit;
import balloon.Action.Movement;

public class LuckyLoser extends Player {
    public LuckyLoser() {
        super(1,1,8);
    }

    protected Action move(Map<Player, Point2D> map, Balloon b) {
        Point2D start = map.get(this);
        Point2D bLocation = b.getLocation();
        double distance = start.distance(bLocation);
        if(distance<=4){
            boolean foundMe = false;
            int numPlayersInRange=0;
            for(Point2D point:map.values()){
                if( !foundMe && point.equals(start))
                {
                    foundMe=true;
                    continue;
                }
                if(point.distance(bLocation)<=4)
                    numPlayersInRange++;                
            }
            if(numPlayersInRange>1)
                return new Hit(0,0,-1);
            else
                return new Hit(0,0,1);
        }
        double x = start.getX()-bLocation.getX();
        double y = start.getY()-bLocation.getY();
        x /= distance;
        y /= distance;
        return new Movement(-x, -y);
    }
}

编辑:修正了运动错误,实际上使我逃离了气球而不是> _ <现在,如果我无法击中气球,我就直接奔向气球。


3

排斥者

这个机器人依靠的只有一个真正的动作,那就是继续将气球推离自己。即击退气球。

在目前的所有机器人(LuckyLoser,AngryPenguin,Hydrophobe,BackAndForth)中,它似乎总是表现出色。但是,如果其他机器人都设法获得负分,则无为而为的Hydrophobe随时准备取胜:P

package players;
import java.awt.geom.Point2D;
import java.util.Map;

import balloon.Action;
import balloon.Balloon;
import balloon.Player;
import balloon.Action.Hit;
import balloon.Action.Movement;

public class Repeller extends Player {

    static final private double STRENGTH = 3.5;
    static final private double SPEED = 2.5;
    static final private double LUCK = 4;
    public Repeller() {
        super(SPEED,STRENGTH,LUCK);
    }

    protected Action move(Map<Player, Point2D> map, Balloon b) {
        Point2D start = map.get(this);
        Point2D balloon = b.getLocation();
        double distance = start.distance(balloon)+Double.MIN_VALUE;
        if(distance<=4 && b.getHeight()<=10){
            double x = start.getX()-balloon.getX();
            double y = start.getY()-balloon.getY();
            x /= distance;
            y /= distance;
            x*=STRENGTH;
            y*=STRENGTH;

            // push the balloon away with all our strength
            return new Hit(-x,-y,0);
        }
        double x = start.getX()-balloon.getX();
        double y = start.getY()-balloon.getY();
        x /= distance;
        y /= distance;

        // if we are directly underneath then move away from balloon
        distance=distance<1?-1:distance;

        // if we are just off of directly underneath then stay put
        distance=distance<2?0:distance;

        // move to the desired location
        x*=Math.min(SPEED, distance);
        y*=Math.min(SPEED, distance);
        return new Movement(-x, -y);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.