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 FIGHT
NEW OPPONENT