UPDATE: isSuicidal () ถูกเพิ่มเข้ามาในคลาสเครื่องบินซึ่งช่วยให้คุณตรวจสอบว่าเครื่องบินอยู่ในเส้นทางที่ชนกับกำแพงได้หรือไม่ !!
UPDATE: updateCoolDown () แยกออกจาก simulateMove ()
ปรับปรุง: wrapper รายการที่ไม่ใช่ Java เขียนโดยSparrพร้อมสำหรับการทดสอบดูความคิดเห็น
อัป เดต Zove Games ได้เขียนโปรแกรมสร้างภาพ 3 มิติที่ยอดเยี่ยมสำหรับ KOTH นี่คือวิดีโอ youtube ที่น่ารังเกียจของ PredictAndAVoid Fighting PredictAndAVoid
ฟังก์ชั่น simulateMove () ของคลาสเครื่องบินได้รับการแก้ไขเล็กน้อยดังนั้นจึงไม่อัปเดตความเย็นอีกต่อไปให้ใช้ฟังก์ชั่น updateCoolDown () ใหม่หลังจากถ่ายภาพแล้ว ใหม่ isSuicidal () ผลตอบแทนจริงถ้าเครื่องบินถูกผูกไว้เพื่อจบลงตายใช้มันเพื่อตัดการเคลื่อนไหวของศัตรูและหลีกเลี่ยงการชนกำแพง ในการรับรหัสที่อัปเดตเพียงแค่แทนที่คลาส Controller และ Plane ด้วยรหัสที่อยู่ใน gitub repo
ลักษณะ
เป้าหมายของความท้าทายนี้คือการเขียนรหัสเครื่องบิน dogfightingสองลำที่จะเผชิญหน้ากับเครื่องบินสองลำโดยผู้เข้าแข่งขันคนอื่น ทุกเทิร์นที่คุณย้ายหนึ่งช่องว่างและมีโอกาสที่จะยิง เพียงเท่านี้ก็ง่ายเหมือนกัน
เกือบแล้ว ...
สนามกีฬาและการเคลื่อนไหวที่เป็นไปได้
สนามกีฬาเป็นกำแพงขนาด 14x14x14 อวกาศ เครื่องบินของผู้เข้าประกวด 1 เริ่มที่สถานที่ (0,5,0) และ (0,8,0) และของผู้เข้าประกวด 2 ที่ (13,5,13) และ (13,8,13) เครื่องบินทุกลำเริ่มต้นด้วยการบินในแนวนอนห่างจากผนังแนวตั้งที่อยู่ใกล้ที่สุด
ตอนนี้เนื่องจากคุณกำลังบินเครื่องบินและไม่ใช่เฮลิคอปเตอร์คุณไม่สามารถเปลี่ยนทิศทางได้ตามต้องการหรือหยุดเคลื่อนที่ดังนั้นเครื่องบินแต่ละลำจึงมีทิศทางและจะย้ายไพ่หนึ่งใบในทิศทางนั้นทุก ๆ ตา
The possible directions are: North(N), South(S), East(E), West(W), Up(U) and Down(D) and any logical combination of those six. Where the NS axis corresponds to the x axis, WE to y and DU to z. NW, SU and NED come to mind as possible examples of directions; UD is a great example of an invalid combination.
แน่นอนว่าคุณสามารถเปลี่ยนทิศทางของเครื่องบินได้ แต่มีข้อ จำกัด คุณสามารถเปลี่ยนทิศทางของคุณได้สูงสุด 45 องศาเท่านั้น ในการมองเห็นสิ่งนี้ให้จับลูกบาศก์รูบิคของคุณ (ฉันรู้ว่าคุณมี) และจินตนาการว่าลูกบาศก์เล็ก ๆ ชั้นนอกทั้ง 26 ก้อนเป็นทิศทางที่เป็นไปได้ (ทิศทางตัวอักษรตัวหนึ่งคือใบหน้าทิศทางของตัวอักษรสองตัวคือขอบ หากคุณกำลังมุ่งหน้าไปในทิศทางที่แสดงโดยคิวบ์เล็ก ๆ คุณสามารถเปลี่ยนทิศทางไปยังแต่ละคิวบ์ที่สัมผัสกับคุณ (นับจำนวนการสัมผัสในแนวทแยงมุม แต่เพียงสัมผัสอย่างเห็นได้ชัดเท่านั้นที่ไม่ได้สัมผัสผ่านคิวบ์)
หลังจากที่ทุกระนาบได้ระบุทิศทางที่พวกเขาต้องการเปลี่ยนพวกมันจะทำเช่นนั้นและย้ายไทล์หนึ่งไปพร้อม ๆ กัน
คุณยังสามารถเลือกที่จะย้ายไปในทิศทางที่ถูกต้อง แต่ยังคงบินไปในทิศทางที่คุณกำลังไปโดยเปลี่ยนทิศทางของคุณไปเป็นทิศทางที่คุณย้ายไป นี่เป็นความคล้ายคลึงกับความแตกต่างระหว่างรถที่วิ่งไปรอบ ๆ มุมถนนกับรถที่เปลี่ยนเลน
ยิงและกำลังจะตาย
คุณสามารถยิงได้มากที่สุดต่อรอบและจะต้องตัดสินใจในเวลาเดียวกันกับที่คุณตัดสินใจว่าจะบินไปทางไหนและคุณต้องการให้เครื่องบินของคุณ (และโดยการขยายปืนของคุณ) ชี้ไปในทิศทางเดียวกันหรือไม่ กระสุนถูกยิงทันทีหลังจากที่เครื่องบินเคลื่อนที่ มีการเทลงหนึ่งครั้งหลังจากยิงในเทิร์นที่สามคุณก็พร้อมที่จะกลับไปอีกครั้ง คุณสามารถยิงไปในทิศทางที่คุณบินเท่านั้นกระสุนนัดหนึ่งและบินเป็นเส้นตรงจนกว่าจะชนกับกำแพงหรือเครื่องบิน
เมื่อคำนึงถึงวิธีที่คุณสามารถเปลี่ยนทิศทางและ 'เปลี่ยนเลน' ซึ่งหมายความว่าคุณสามารถขู่คอลัมน์ได้ถึง 3x3 บรรทัดต่อหน้าคุณนอกจากนี้ในแนวทแยงบางเส้นเดียว
ถ้ามันกระทบกับระนาบระนาบนี้จะตายและหายไปจากกระดานทันที (เพราะมันระเบิดหรืออะไรบางอย่างโดยสิ้นเชิง) กระสุนสามารถยิงได้เพียงหนึ่งระนาบเท่านั้น กระสุนถูกยิงพร้อมกันดังนั้นเครื่องบินสองลำสามารถยิงกันได้ กระสุนสองนัดไม่สามารถชนกันในอากาศได้ (เศร้าฉันรู้)
เครื่องบินสองลำสามารถชนกันได้ (หากพวกเขาลงเอยด้วยลูกบาศก์เดียวกันและไม่ใช่ถ้าพวกเขาข้ามกันโดยไม่ต้องลงเอยด้วยระนาบเดียวกัน) และผลลัพธ์นี้ทำให้ทั้งสองลำกำลังจะตาย (และระเบิดโดยสิ้นเชิง) คุณยังสามารถบินไปที่กำแพงซึ่งจะส่งผลให้เครื่องบินตกอยู่ในความสงสัยและถูกวางไว้ที่มุมเพื่อคิดเกี่ยวกับการกระทำของมัน ชนได้รับการจัดการก่อนที่จะยิง
การสื่อสารกับคอนโทรลเลอร์
ฉันจะยอมรับรายการเป็นภาษาจาวาและภาษาอื่น ๆ หากรายการของคุณเป็นแบบจาวาคุณจะได้รับอินพุตผ่าน STDIN และจะแสดงผลผ่าน STDOUT
หากรายการของคุณอยู่ใน java รายการของคุณต้องขยายคลาสต่อไปนี้:
package Planes;
//This is the base class players extend.
//It contains the arena size and 4 plane objects representing the planes in the arena.
public abstract class PlaneControl {
    // note that these planes are just for your information, modifying these doesn't affect the actual plane instances, 
    // which are kept by the controller
    protected Plane[] myPlanes = new Plane[2];
    protected Plane[] enemyPlanes = new Plane[2];
    protected int arenaSize;
    protected int roundsLeft;
    ...
    // Notifies you that a new fight is starting
    // FightsFought tells you how many fights will be fought.
    // the scores tell you how many fights each player has won.
    public void newFight(int fightsFought, int myScore, int enemyScore) {}
    // notifies you that you'll be fighting anew opponent.
    // Fights is the amount of fights that will be fought against this opponent
    public void newOpponent(int fights) {}
    // This will be called once every round, you must return an array of two moves.
    // The move at index 0 will be applied to your plane at index 0,
    // The move at index1 will be applied to your plane at index1.
    // Any further move will be ignored.
    // A missing or invalid move will be treated as flying forward without shooting.
    public abstract Move[] act();
}
อินสแตนซ์ที่สร้างขึ้นของคลาสนั้นจะคงอยู่ตลอดการแข่งขันดังนั้นคุณสามารถเก็บข้อมูลใด ๆ ที่คุณต้องการเก็บไว้ในตัวแปร อ่านความคิดเห็นในรหัสสำหรับข้อมูลเพิ่มเติม
ฉันยังให้คุณกับผู้ช่วยชั้นเรียนต่อไปนี้:
package Planes;
//Objects of this class contain all relevant information about a plane
//as well as some helper functions.
public class Plane {
    private Point3D position;
    private Direction direction;
    private int arenaSize;
    private boolean alive = true;
    private int coolDown = 0;
    public Plane(int arenaSize, Direction direction, int x, int y, int z) {}
    public Plane(int arenaSize, Direction direction, Point3D position) {}    
    // Returns the x coordinate of the plane
    public int getX() {}
    // Returns the y coordinate of the plane
    public int getY() {}
    // Returns the z coordinate of the plane
    public int getZ() {}
    // Returns the position as a Point3D.
    public Point3D getPosition() {}
    // Returns the distance between the plane and the specified wall,
    // 0 means right next to it, 19 means at the opposite side.
    // Returns -1 for invalid input.
    public int getDistanceFromWall(char wall) {}
    // Returns the direction of the plane.
    public Direction getDirection() {}
    // Returns all possible turning directions for the plane.
    public Direction[] getPossibleDirections() {}
    // Returns the cool down before the plane will be able to shoot, 
    // 0 means it is ready to shoot this turn.
    public int getCoolDown() {}
    public void setCoolDown(int coolDown) {}
    // Returns true if the plane is ready to shoot
    public boolean canShoot() {}
    // Returns all positions this plane can shoot at (without first making a move).
    public Point3D[] getShootRange() {}
    // Returns all positions this plane can move to within one turn.
    public Point3D[] getRange() {}
    // Returns a plane that represents this plane after making a certain move,
    // not taking into account other planes.
    // Doesn't update cool down, see updateCoolDown() for that.
    public Plane simulateMove(Move move) {}
    // modifies this plane's cool down
    public void updateCoolDown(boolean shot) {
        coolDown = (shot && canShoot())?Controller.COOLDOWN:Math.max(0, coolDown - 1);
    }
    // Returns true if the plane is alive.
    public boolean isAlive() {}
    // Sets alive to the specified value.
    public void setAlive(boolean alive) {}
    // returns a copy of itself.
    public Plane copy() {}
    // Returns a string representing its status.
    public String getAsString() {}
    // Returns a string suitable for passing to a wrapped plane process
    public String getDataString() {}
    // Returns true if a plane is on an irreversable colision course with the wall.
    // Use this along with simulateMove() to avoid hitting walls or prune possible emeny moves.
    public boolean isSuicidal() {}
}
// A helper class for working with directions. 
public class Direction {
    // The three main directions, -1 means the first letter is in the direction, 1 means the second is, 0 means neither is.
    private int NS, WE, DU;
    // Creates a direction from 3 integers.
    public Direction(int NSDir, int WEDir, int DUDir) {}
    // Creates a direction from a directionstring.
    public Direction(String direction) {}
    // Returns this direction as a String.
    public String getAsString() {}
    // Returns The direction projected onto the NS-axis.
    // -1 means heading north.
    public int getNSDir() {}
    // Returns The direction projected onto the WE-axis.
    // -1 means heading west.
    public int getWEDir() {}
    // Returns The direction projected onto the DU-axis.
    // -1 means heading down.
    public int getDUDir() {}
    // Returns a Point3D representing the direction.
    public Point3D getAsPoint3D() {}
    // Returns an array of chars representing the main directions.
    public char[] getMainDirections() {}
    // Returns all possible turning directions.
    public Direction[] getPossibleDirections() {}
    // Returns true if a direction is a valid direction to change to
    public boolean isValidDirection(Direction direction) {}
}
public class Point3D {
    public int x, y, z;
    public Point3D(int x, int y, int z) {}
    // Returns the sum of this Point3D and the one specified in the argument.
    public Point3D add(Point3D point3D) {}
    // Returns the product of this Point3D and a factor.
    public Point3D multiply(int factor) {}
    // Returns true if both Point3D are the same.
    public boolean equals(Point3D point3D) {}
    // Returns true if Point3D is within a 0-based arena of a specified size.
    public boolean isInArena(int size) {}
}
public class Move {
    public Direction direction;
    public boolean changeDirection;
    public boolean shoot;
    public Move(Direction direction, boolean changeDirection, boolean shoot) {}
}
คุณสามารถสร้างอินสแตนซ์ของคลาสเหล่านี้และใช้ฟังก์ชันใด ๆ ได้มากเท่าที่คุณต้องการ คุณสามารถค้นหาโค้ดเต็มรูปแบบสำหรับการเรียนผู้ช่วยเหล่านี้ที่นี่
นี่คือตัวอย่างลักษณะของการเข้าร่วมของคุณ (หวังว่าคุณจะทำได้ดีกว่าที่ฉันทำแม้ว่าการจับคู่ส่วนใหญ่กับเครื่องบินเหล่านี้จะจบลงด้วยการที่พวกเขาบินไปที่กำแพงแม้ว่าพวกเขาจะพยายามหลีกเลี่ยงกำแพง)
package Planes;
public class DumbPlanes extends PlaneControl {
    public DumbPlanes(int arenaSize, int rounds) {
        super(arenaSize, rounds);
    }
    @Override
    public Move[] act() {
        Move[] moves = new Move[2];
        for (int i=0; i<2; i++) {
            if (!myPlanes[i].isAlive()) {
                moves[i] = new Move(new Direction("N"), false, false); // If we're dead we just return something, it doesn't matter anyway.
                continue;
            }
            Direction[] possibleDirections = myPlanes[i].getPossibleDirections(); // Let's see where we can go.
            for (int j=0; j<possibleDirections.length*3; j++) {
                int random = (int) Math.floor((Math.random()*possibleDirections.length)); // We don't want to be predictable, so we pick a random direction out of the possible ones.
                if (myPlanes[i].getPosition().add(possibleDirections[random].getAsPoint3D()).isInArena(arenaSize)) { // We'll try not to fly directly into a wall.
                    moves[i] = new Move(possibleDirections[random], Math.random()>0.5, myPlanes[i].canShoot() && Math.random()>0.2);
                    continue; // I'm happy with this move for this plane.
                }
                // Uh oh.
                random = (int) Math.floor((Math.random()*possibleDirections.length));
                moves[i] = new Move(possibleDirections[random], Math.random()>0.5, myPlanes[i].canShoot() && Math.random()>0.2);
            }
        }
        return moves;
    }
    @Override
    public void newFight(int fightsFought, int myScore, int enemyScore) {
        // Using information is for schmucks.
    }
    @Override
    public void newOpponent(int fights) {
        // What did I just say about information?
    }
}
DumbPlanes จะเข้าร่วมทัวร์นาเมนต์พร้อมกับผลงานอื่น ๆ ดังนั้นหากคุณจบมันเป็นความผิดของคุณเองที่ไม่ได้ทำดีกว่า DumbPlanes
ข้อ จำกัด
ข้อ จำกัด ที่กล่าวถึงในKOTH wikiใช้:
- ความพยายามที่จะคนจรจัดกับตัวควบคุมรันไทม์หรือการส่งอื่น ๆ จะถูกตัดสิทธิ์ การส่งทั้งหมดควรทำงานกับอินพุตและพื้นที่เก็บข้อมูลที่ได้รับเท่านั้น
- ไม่ควรเขียนบอทเพื่อเอาชนะหรือสนับสนุนบอทอื่น ๆ โดยเฉพาะ (สิ่งนี้อาจเป็นที่ต้องการในบางกรณีที่หายาก แต่ถ้านี่ไม่ใช่แนวคิดหลักของความท้าทาย
- ฉันขอสงวนสิทธิ์ในการตัดสิทธิ์การส่งผลงานที่ใช้เวลาหรือหน่วยความจำมากเกินไปในการเรียกใช้การทดลองที่มีทรัพยากรในปริมาณที่เหมาะสม
- บอตจะต้องไม่ใช้กลยุทธ์เดียวกันกับกลยุทธ์ที่มีอยู่ไม่ว่าจะโดยเจตนาหรือโดยไม่ตั้งใจ
ทดสอบการส่งของคุณ
ดาวน์โหลดรหัสควบคุมจากที่นี่ เพิ่มการส่งของคุณเป็น Something.java แก้ไข Controller.java เพื่อรวมรายการสำหรับเครื่องบินของคุณในรายการ [] และชื่อ [] ทุกอย่างที่คอมไพล์เป็นโครงการคราสหรือแล้วเรียกใช้ควบคุมด้วยjavac -d . *.java java Planes/Controllerบันทึกการแข่งขันจะมีขึ้นtest.txtพร้อมป้ายบอกคะแนนในตอนท้าย นอกจากนี้คุณยังสามารถโทรหาmatchUp()โดยตรงโดยใช้สองรายการเป็นอาร์กิวเมนต์เพื่อทดสอบเครื่องบินสองรายการต่อกัน
ชนะการต่อสู้
ผู้ชนะของการต่อสู้คือผู้ที่มีเครื่องบินลำสุดท้ายบินหากหลังจาก 100 รอบยังมีเหลืออีก 1 ทีมทีมที่มีเครื่องบินมากที่สุดจะเป็นผู้ชนะ ถ้านี่เท่ากันมันคือการจับฉลาก
การให้คะแนนและการแข่งขัน
การแข่งขันอย่างเป็นทางการครั้งต่อไปจะเริ่มขึ้นเมื่อเงินรางวัลปัจจุบันหมด
แต่ละรายการจะต่อสู้กันทุกรายการ (อย่างน้อย) 100 ครั้งผู้ชนะของการแข่งขันแต่ละครั้งจะเป็นรายการที่มีผู้ชนะมากที่สุดจาก 100 รายการและจะได้รับ 2 คะแนน ในกรณีที่เสมอกันทั้งสองรายการจะได้รับ 1 คะแนน
ผู้ชนะการแข่งขันคือผู้ที่มีคะแนนมากที่สุด ในกรณีที่เสมอผู้ชนะคือผู้ที่ชนะในการแข่งขันระหว่างรายการที่เข้าร่วม
ขึ้นอยู่กับจำนวนของรายการจำนวนของการต่อสู้ระหว่างรายการจะเพิ่มขึ้นอย่างมีนัยสำคัญฉันอาจเลือก 2-4 รายการที่ดีที่สุดหลังจากทัวร์นาเมนต์แรกและตั้งค่าทัวร์นาเมนต์ระดับสูงระหว่างรายการเหล่านั้นที่มีการต่อสู้มากขึ้น การต่อสู้)
(เบื้องต้น) กระดานคะแนน
เรามีรายการใหม่ที่มีอันดับสองในการแข่งขันที่น่าตื่นเต้นอีกครั้งดูเหมือนว่า Crossfire นั้นยากที่จะยิงสำหรับทุกคนยกเว้น PredictAndAvoid โปรดทราบว่าทัวร์นาเมนต์นี้ดำเนินการด้วยการต่อสู้เพียง 10 ครั้งระหว่างเครื่องบินแต่ละชุดและไม่ได้มีการแสดงถึงความแม่นยำของสิ่งต่างๆ
----------------------------
¦ 1. PredictAndAvoid:   14 ¦
¦ 2. Crossfire:         11 ¦
¦ 3. Weeeeeeeeeeee:      9 ¦
¦ 4. Whirligig:          8 ¦
¦ 4. MoveAndShootPlane:  8 ¦
¦ 6. StarFox:            4 ¦
¦ 6. EmoFockeWulf:       2 ¦
¦ 7. DumbPlanes:         0 ¦
----------------------------
นี่คือตัวอย่างของเอาต์พุตจาก wrapper ที่ไม่ใช่ Java:
NEW CONTEST 14 20 บ่งชี้ว่าการแข่งขันใหม่เริ่มต้นขึ้นแล้วในเวทีขนาด 14x14x14 และจะมีการเปิด 20 รอบต่อการต่อสู้
NEW OPPONENT 10 บ่งบอกว่าคุณกำลังเผชิญหน้ากับคู่ต่อสู้คนใหม่และคุณจะต้องสู้กับคู่ต่อสู้นี้ 10 ครั้ง
NEW FIGHT 5 3 2 เป็นการบ่งชี้ว่าการต่อสู้ครั้งใหม่กับฝ่ายตรงข้ามปัจจุบันกำลังเริ่มขึ้นและคุณได้ต่อสู้กับฝ่ายตรงข้าม 5 ครั้งจนถึงตอนนี้ชนะ 3 ครั้งและแพ้ 2 ครั้ง
ROUNDS LEFT 19  หมายถึงมี 19 รอบที่เหลืออยู่ในการต่อสู้ปัจจุบัน
NEW TURN บ่งบอกว่าคุณกำลังจะได้รับข้อมูลสำหรับเครื่องบินทั้งสี่ลำสำหรับการต่อสู้รอบนี้
alive 13 8 13 N 0
alive 13 5 13 N 0
dead 0 0 0 N 0
alive 0 8 0 S 0
สี่บรรทัดเหล่านี้บ่งชี้ว่าเครื่องบินทั้งสองลำของคุณยังมีชีวิตอยู่ที่พิกัด [13,8,13] และ [13,5,13] ตามลำดับทั้งสองหันหน้าไปทางทิศเหนือทั้งคู่มีศูนย์คูลดาวน์ เครื่องบินข้าศึกลำแรกตายไปแล้วและดวงที่สองยังมีชีวิตอยู่ที่ [0,8,0] และหันหน้าไปทางทิศใต้โดยไม่มีคูลดาวน์
ณ จุดนี้โปรแกรมของคุณควรแสดงผลสองบรรทัดคล้ายกับที่แสดงต่อไปนี้:
NW 0 1
SU 1 0
นี่เป็นการระบุว่าเครื่องบินลำแรกของคุณจะเดินทางไปทางทิศตะวันตกเฉียงเหนือโดยไม่ต้องหันหน้าจากหัวปัจจุบันและยิงได้ เครื่องบินลำที่สองของคุณจะเดินทางไปทางทิศตะวันออกเฉียงใต้หันหน้าไปทางทิศตะวันออกเฉียงใต้ไม่ใช่ถ่ายภาพ
ตอนนี้คุณจะได้รับROUNDS LEFT 18ตามมาด้วยNEW TURNฯลฯ นี้ต่อไปจนกว่าจะชนะใครบางคนหรือรอบครั้งจากจุดที่คุณจะได้รับอีกสายที่มีการปรับปรุงการนับคะแนนการต่อสู้และอาจจะนำหน้าด้วยNEW FIGHTNEW OPPONENT

