Cuộc chiến bóng nước


12

Trò chơi vua đồi này là một trò chơi chiến lược, trong đó bạn phải ném xung quanh một quả bóng nước và tránh bị nước bắn tung tóe. Mục tiêu là để có được nhiều điểm nhất. Bạn sẽ được cung cấp một bản đồ của lĩnh vực và vị trí của quả bóng nước. Bạn có thể quay lại rằng bạn muốn đánh bóng nước (nếu bạn đủ gần) theo một hướng nhất định hoặc bạn muốn di chuyển theo một hướng nhất định.

Cụ thể: Bong bóng nước sẽ bắt đầu ở (0, 0)mức cao 30 đơn vị và thả. Nếu quả bóng nước chạm đất, người chơi sẽ được chọn ngẫu nhiên để mất 4 điểm, với trọng lượng lớn hơn dành cho những người ở gần quả bóng hơn. Ngoài ra, người chơi đánh bóng cuối cùng sẽ kiếm được 3 điểm. Do đó, nếu bạn đánh bóng bay thẳng xuống, rất có thể bạn sẽ mất 1 điểm.

Bạn sẽ viết một lớp học mở rộng Player. Bạn được yêu cầu thực hiện các hàm tạo. Hàm tạo sẽ như sau:

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

Những số này là doubles. Số đầu tiên đại diện cho tốc độ của người chơi, số thứ hai đại diện cho sức mạnh và số thứ ba đại diện cho may mắn. Các số phải thêm tối đa 10 hoặc ít hơn và không có số nào có thể nhỏ hơn hoặc bằng 0.

Thứ hai, bạn phải thực hiện movephương pháp. Đây là một movephương pháp ví dụ :

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

Có một số điều quan trọng ở đây. Đầu tiên, lưu ý rằng trường được thông qua là a Map<Player, Point2D>. Trường là vô hạn - không có giới hạn về việc bạn có thể đi bao xa. Nó không phải là một mảng 2 chiều hay bất cứ thứ gì tương tự. Ngoài ra, điều này có nghĩa là bạn sẽ có tọa độ không nguyên làm vị trí của mình. Điều này là hoàn toàn ổn.

Một hậu quả khác là người chơi và khinh khí cầu có thể chồng lên nhau. Trong thực tế, hai người chơi có thể ở cùng một vị trí!

Bong bóng có vận tốc và hướng nhất định. Nói chung, nó sẽ giảm với tốc độ 3 đơn vị / bước. Nó cũng di chuyển theo một xhướng và yhướng. Khi bạn quay lại a Hit, bạn chuyển các hướng x, y và z mà bạn đang đẩy bóng bay. Bạn không thể đánh một quả bóng có chiều cao lớn hơn 10 hoặc có khoảng cách từ bạn (chỉ trên hai chiều) lớn hơn 4. Ngoài ra, nếu đúng là x^2 + y^2 + z^2 > s^2nơi slà sức mạnh của bạn, và x, yzlà hướng mà bạn nhấn , hành động của bạn bị loại bỏ. Lực đánh của bạn được khuếch đại bởi một số ngẫu nhiên giữa 0luck(có nghĩa là nó có thể đi xuống nếu vận may của bạn thấp).

Tương tự, bạn có thể trả về a Movementvới xytọa độ mà bạn đang di chuyển (lưu ý rằng bạn không thể nhảy lên không trung). Nếu tốc độ của bạn x^2 + y^2 > s^2ở đâu s, hành động của bạn sẽ bị loại bỏ.

Nếu quả bóng nước chạm đất thì một người chơi ngẫu nhiên được chọn, với trọng lượng lớn hơn được trao cho những người gần nhất - nhưng ít trọng lượng hơn cho những người gặp nhiều may mắn hơn. Người chơi được chọn mất 4 điểm.

Trình điều khiển: https://github.com/prakol16/water-balloon-wars/tree/master

Trò chơi kéo dài 1000 bước. Cuối cùng, sẽ có một tập tin được gọi là log.out. Sao chép và dán dữ liệu vào fiddle này để xem trò chơi: https://jsfiddle.net/prankol57/s2x776dt/embedded/result/

Hoặc thậm chí tốt hơn, xem nó dưới dạng 3D: http : //www.brianmacffy.com/waterballoonwars (nhờ BMac)

Người chơi có tổng điểm cao nhất sau 100 (có thể nhiều hơn, nhưng không ít hơn) các trò chơi sẽ thắng.

Nếu bạn muốn gửi giải pháp, bạn có thể muốn đọc các chi tiết thực sự cụ thể tại https://github.com/prakol16/water-balloon-wars/tree/master .

Chỉnh sửa 3/8 :

Đây là những điểm số cuối cùng cho đến bây giờ (1000 lần lặp, không bao gồm người chơi 1 và 2). Nếu bạn chỉnh sửa bài đăng của mình, bạn có thể nhận xét và tôi sẽ làm lại điểm số:

{
    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
}

Người chiến thắng Weaklingvới trung bình 39 điểm. Vị trí thứ 2 là Repellervới 21 điểm.


1
Điều gì xảy ra khi bạn đánh bóng bay? Làm thế nào để nó di chuyển? Điều gì nếu nhiều người đánh nó?
Keith Randall

Hoạt hình với jsfiddle thực sự rất hay!
CommonGuy 27/2/2015

Nhân tiện, bạn nên làm cho các phương thức trong lớp Người chơi cuối cùng, nếu không, các bài nộp có thể ghi đè lên chúng.
CommonGuy 27/2/2015

2
Bạn đảo ngược speedstrengthtrong trình xây dựng Player.
Thrax

@KeithRandall Các dirX, dirYdirZ(khuếch đại bởi vận may của mình) chỉ đơn giản là thêm vào vận tốc của quả bóng. Nếu nhiều người trúng nó (hơi khó xảy ra) thì người chơi có thể nhận được ba điểm sẽ được quyết định may mắn (xem chi tiết cụ thể)
soktinpk

Câu trả lời:


7

Giả lập

Tôi hy vọng điều này là ổn, vì nó không thực sự là một mục. Tôi thực sự thích ý tưởng về trình mô phỏng hình ảnh và tôi muốn tạo ra cái riêng của mình để có thể nhìn mọi thứ cùng một lúc (3D đầy đủ) dễ dàng hơn một chút.

28/11 9:06 AM PST : cập nhật với các điều khiển, màu sắc

3/4 8:47 AM PST : cập nhật với thanh trượt cho tốc độ mô phỏng và bắt đầu một trò chơi mới thực sự hoạt động mà không cần làm mới trang (sử dụng Ctrl-F5 để tải lại tập lệnh được lưu trong bộ nhớ cache)

Trình hiển thị trực tuyến ThreeJS

nhập mô tả hình ảnh ở đây


3
+1000 Điều đó thật tuyệt vời. Cảm ơn bạn
soktinpk

Ý bạn là Ctrl + F5 chứ không phải Shift + F5?
TimTech

Có vẻ như cả hai đều hoạt động trong Chrome.
BMac

7

Qua lại

Bot này cố gắng lại gần và đánh bóng bay cho đến khi chiều cao của nó quá thấp và nó cố gắng thoát ra.

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

    }

}

có vẻ như bot của bạn thực hiện các động thái bất hợp pháp và do đó không làm gì khi nó làm.
Moogie

@soktinpk Tôi đã sửa bài nộp của mình, nó sẽ làm tốt hơn bây giờ. Cảm ơn Moogie quá!
Thrax

Tôi vẫn thấy rằng bot của bạn đang yêu cầu chuyển động vượt quá những gì có thể. Tôi đã đưa vào một chỉnh sửa bài viết của bạn để xem xét. Về cơ bản, bạn đang sử dụng vị trí của khinh khí cầu làm chuyển động.
Moogie 13/03/2015

@Moogie Đúng rồi, cảm ơn rất nhiều!
Thrax

Vui mừng được giúp đỡ. Bot của bạn là khá tốt để có được điểm số tích cực. làm tốt!
Moogie 13/03/2015

5

AngryPenguin

Chú chim cánh cụt này tức giận vì không thể bay lên khinh khí cầu, vì vậy nó cố gắng đánh quả bóng bay vào mặt những người đứng xung quanh mình.

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

}

Đây là một trong những để đánh bại.
Kevin Workman

5

Yếu

Bot này chỉ có thể chạm vào quả bóng bay vì nó rất yếu, thay vào đó nó chỉ dựa vào sự may mắn cao của nó. Do đó, nó hoạt động tương tự như LuckyLoser (từ đó bot này được truyền cảm hứng).

Anh ta dường như thực hiện tất cả các bot hiện tại bao gồm cả 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);
    }
}

EDIT: giảm tốc độ ủng hộ may mắn


3

Hydrophobe

Đây là một trong những bot đơn giản nhất có thể nhưng vì nó cạnh tranh nên tôi sẽ đăng nó.

Chiến lược: à ... con bot này ghét nước nên nó biến mất.

Vì bot sẽ bị văng rất hiếm khi nó sẽ ghi trung bình một chút dưới 0 điểm. Tổng điểm của tất cả các bot là -1 * [bóng chạm đất] vì vậy Hydrophobe có thể sẽ đạt điểm trên trung bình.

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

KeepAway

Người chơi này đuổi theo khinh khí cầu miễn là chiều cao của nó> 2. Ngay khi nó có thể chạm vào khinh khí cầu, nó sẽ đánh bóng bay ra xa người chơi gần nhất. Khi chiều cao của khinh khí cầu <2, người chơi này bỏ chạy.

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

}

Chỉnh sửa: Tôi đã chơi với Player1 và Player2. Người chơi này thắng trong trường hợp đó, nhưng thua khi tôi đưa họ ra ngoài. Booooo.


3

Người thua may mắn

Bot này dựa vào điểm may mắn cao của nó. Nếu nó không ở gần khinh khí cầu, nó chạy về phía khinh khí cầu. Khi ở gần khinh khí cầu, nếu có ít nhất 2 người chơi khác trong phạm vi của khinh khí cầu, anh ta sẽ phóng nó xuống đất. Nếu không, anh ta sẽ đánh nó thẳng lên.

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

EDIT: Đã sửa lỗi chuyển động thực sự khiến tôi bỏ chạy không về phía khinh khí cầu> _ <Bây giờ tôi chỉ chạy thẳng về phía khinh khí cầu nếu tôi không thể đánh nó.


3

Đại lý

Bot này chỉ có một động tác thực sự và đó là tiếp tục đẩy quả bóng bay ra khỏi chính nó. tức là đẩy lùi bóng bay.

Nó dường như hoạt động tốt so với các bot hiện tại (LuckyLoser, AngryPenguin, Hydrophobe, BackAndForth) gần như luôn luôn chiến thắng. Tuy nhiên, Hydrophobe, bằng cách không hành động, luôn sẵn sàng giành chiến thắng nếu các bot khác đều có được điểm số âm: 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);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.