协调细菌
希望我还不晚。
在我的测试中,击败其他对手(并且总是杀死所有对手),如果战斗面对面,战斗将永远不会结束,这证明了该战略的强大。
单细胞时,您可以记住以前的状态,但是可以利用自己的位置来表现不同!=)
这会将细菌分为分配器和推动器,这样做将使更多的细菌有用,而不仅仅是第一线,同时保持防御力。
它还协调攻击以集中于特定敌人,以便更快地杀死敌人(这是要面对我的另一个专注于HP的单细胞)。
在游戏中期,通过棋盘上的细胞数量来检测它们,他们将试图越过它们的侧面将其推入敌方领土。这是关键的制胜策略。
与目前所有其他对手相比,它的增长率最高,但起步缓慢,因此在大型竞技场上效果更好。
运行它 java CoordinatedBacteria
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
public class CoordinatedBacteria {
public static final int MAX_HP = 6;
public static final int MAX_ENERGY = 6;
public static final int ACIDITY = 0;
// given arena state and cell stats, return an action string (e.g., "ATTACK NW 2", "DIVIDE S")
public static String decide(final Arena arena, Point cell, int hp, int energy) {
// empty and corpses are free for movement and division
final Point2D enemyCenter = arena.getCenterOf("x");
final Point2D ourCenter = arena.getCenterOf("o");
final int moverPos = (enemyCenter.x <= ourCenter.x || enemyCenter.y <= ourCenter.y) ? (arena.width+arena.height+1)%2 : 1;
final int attackPos = (enemyCenter.x <= ourCenter.x || enemyCenter.y <= ourCenter.y) ? (arena.width+arena.height)%2 : 1;
int selfCount = arena.count("o");
boolean isMidWay = selfCount > (arena.width*arena.height/2-1);
if(!isMidWay){
if(enemyCenter.x < ourCenter.x){
enemyCenter.x = 0;
enemyCenter.y = 0;
ourCenter.x = arena.width;
ourCenter.y = arena.height;
} else {
enemyCenter.x = arena.width;
enemyCenter.y = arena.height;
ourCenter.x = 0;
ourCenter.y = 0;
}
}
ArrayList<Point> nearbyEmpty = arena.getAdjacentMatches(cell, ".");
Collections.sort(nearbyEmpty, new Comparator<Point>(){
@Override
public int compare(Point o1, Point o2) {
Double score1 = arena.getAdjacentMatches(o1, ".").size()
+ arena.getAdjacentMatches(o1, "c").size()
+ arena.getAdjacentMatches(o1, "x").size()
- arena.getAdjacentMatches(o1, "o").size()
+ distance(o1.x, o1.y, enemyCenter.x, enemyCenter.y)*100;
Double score2 = arena.getAdjacentMatches(o2, ".").size()
+ arena.getAdjacentMatches(o2, "c").size()
+ arena.getAdjacentMatches(o2, "x").size()
- arena.getAdjacentMatches(o2, "o").size()
+ distance(o1.x, o1.y, enemyCenter.x, enemyCenter.y)*100;
return Double.compare(score2, score1);
}
});
ArrayList<Point> nearbyEnemies = arena.getAdjacentMatches(cell, "x");
Collections.sort(nearbyEnemies, new Comparator<Point>(){
@Override
public int compare(Point o1, Point o2) {
Integer score1 = (arena.getAdjacentMatches(o1, ".").size()
+ arena.getAdjacentMatches(o1, "c").size()
- arena.getAdjacentMatches(o1, "x").size()
+ arena.getAdjacentMatches(o1, "o").size())
*10
+ (isAtBoundary(o1, arena)?1000:0)
+ (o1.x + o1.y + attackPos + 1)%2;
Integer score2 = (arena.getAdjacentMatches(o2, ".").size()
+ arena.getAdjacentMatches(o2, "c").size()
- arena.getAdjacentMatches(o2, "x").size()
+ arena.getAdjacentMatches(o2, "o").size())
*10
+ (isAtBoundary(o2, arena)?1000:0)
+ (o2.x + o2.y + attackPos + 1)%2;
return Integer.compare(score2, score1);
}
});
ArrayList<Point> nearbyCorpses = arena.getAdjacentMatches(cell, "c");
Collections.sort(nearbyCorpses, new Comparator<Point>(){
@Override
public int compare(Point o1, Point o2) {
Integer score1 = arena.getAdjacentMatches(o1, "x").size()
- arena.getAdjacentMatches(o1, "o").size();
Integer score2 = arena.getAdjacentMatches(o2, "x").size()
- arena.getAdjacentMatches(o2, "o").size();
return Integer.compare(score1, score2);
}
});
ArrayList<Point> nearbyFriends = arena.getAdjacentMatches(cell, "o");
for(Point empty: nearbyEmpty){
if(nearbyFriends.size()>=2 && energy >= 1 && arena.getAdjacentMatches(empty, "x").size()==3 && isAtBoundary(empty, arena)){
return "MOVE "+arena.getDirection(cell, empty);
}
}
for(Point empty: nearbyCorpses){
if(nearbyFriends.size()>=2 && energy >= 1 && arena.getAdjacentMatches(empty, "x").size()==3 && isAtBoundary(empty, arena)){
return "MOVE "+arena.getDirection(cell, empty);
}
}
if ((cell.x+cell.y)%2 == moverPos && energy >= 1 && energy <= 5){
if(nearbyEmpty.size()>0){
Point foremost = nearbyEmpty.get(0);
if(nearbyFriends.size() >= 4){
return "MOVE "+arena.getDirection(cell, foremost);
}
}
if(nearbyCorpses.size() > 0) {
Point corpse = nearbyCorpses.get(0);
return "EAT " + arena.getDirection(cell, corpse);
}
if(energy > 0 && nearbyEnemies.size() > 0) {
int attackStrength = Math.min(energy, 3);
Point enemy = nearbyEnemies.get(0);
return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
}
if(nearbyFriends.size() >= 4 && nearbyEmpty.size() > 0){
Point movePoint = getBestPointToDivide(arena, nearbyEmpty);
return "MOVE " + arena.getDirection(cell, movePoint);
}
}
if(energy >= 5 && nearbyEmpty.size() > 0) {
Point divisionPoint = getBestPointToDivide(arena, nearbyEmpty);
if(energy == MAX_ENERGY && nearbyFriends.size() >= 5
&& distance(enemyCenter.x, enemyCenter.y, cell.x, cell.y) > distance(enemyCenter.x, enemyCenter.y, divisionPoint.x, divisionPoint.y)){
return "MOVE " + arena.getDirection(cell, divisionPoint);
}
return "DIVIDE " + arena.getDirection(cell, divisionPoint);
}
if(nearbyCorpses.size() > 0) {
Point corpse = nearbyCorpses.get(0);
if (energy < MAX_ENERGY){
return "EAT " + arena.getDirection(cell, corpse);
} else {
return "DIVIDE " + arena.getDirection(cell, corpse);
}
}
if(energy >= 5 && nearbyCorpses.size() > 0) {
Point divisionPoint = getBestPointToDivide(arena, nearbyCorpses);
if(energy == MAX_ENERGY && nearbyFriends.size() >= 5
&& distance(enemyCenter.x, enemyCenter.y, cell.x, cell.y) < distance(enemyCenter.x, enemyCenter.y, divisionPoint.x, divisionPoint.y)){
return "MOVE " + arena.getDirection(cell, divisionPoint);
}
return "DIVIDE " + arena.getDirection(cell, divisionPoint);
}
// if at least one adjacent enemy, attack if possible
if(energy > 0 && nearbyEnemies.size() > 0) {
int attackStrength = Math.min(energy, 3);
Point enemy = nearbyEnemies.get(0);
return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
}
return "REST";
}
public static boolean isAtBoundary(Point point, Arena arena){
return point.x==0 || point.x==arena.width-1 || point.y==0 || point.y==arena.height-1;
}
public static double distance(double x1, double y1, double x2, double y2){
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
public static Point getBestPointToDivide(Arena arena, List<Point> nearbyEmpty){
Point result = null;
double minDist = 100000;
List<Point> mostEmpty = new ArrayList<Point>();
int max = -1000;
List<Point> neighbor = nearbyEmpty;
for(Point point: neighbor){
int emptyNeighborScore = arena.getAdjacentMatches(point, ".").size()
+ arena.getAdjacentMatches(point, "c").size()
+ arena.getAdjacentMatches(point, "x").size()
- arena.getAdjacentMatches(point, "o").size();
if(emptyNeighborScore > max){
mostEmpty = new ArrayList<Point>();
mostEmpty.add(point);
max = emptyNeighborScore;
} else if(emptyNeighborScore == max){
mostEmpty.add(point);
}
}
for(Point point: mostEmpty){
Point2D enemyCenter = arena.getCenterOf("x");
double dist = Math.pow(point.x-enemyCenter.x, 2) + Math.pow(point.y-enemyCenter.y, 2);
if(dist < minDist){
minDist = dist;
result = point;
}
}
return result;
}
public static void main(String[] args) throws IOException {
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
String firstLine;
firstLine = br.readLine();
if(firstLine.equals("BEGIN")) {
System.out.println(MAX_HP + " " + MAX_ENERGY + " " + ACIDITY);
} else {
String[] dimensions = firstLine.split(" ");
int width = Integer.parseInt(dimensions[0]);
int height = Integer.parseInt(dimensions[1]);
Point[][] arena = new Point[height][];
String input;
int lineno = 0;
while(!(input=br.readLine()).equals("")) {
char[] charList = input.toCharArray();
arena[lineno] = new Point[width];
for(int i=0; i<charList.length; ++i) {
arena[lineno][i] = new Point(i, lineno, charList[i]);
}
lineno++;
}
String[] stats = br.readLine().split(" ");
int x = Integer.parseInt(stats[0]);
int y = Integer.parseInt(stats[1]);
int hp = Integer.parseInt(stats[2]);
int energy = Integer.parseInt(stats[3]);
Arena arenaObj = new Arena(arena, width, height);
System.out.print(decide(arenaObj, arenaObj.get(x,y), hp, energy));
}
}
public static class Arena {
public Point[][] array;
public HashMap<String, String> c2d;
public int height;
public int width;
public Arena(Point[][] array, int width, int height) {
this.array = array;
this.width = width;
this.height = height;
this.c2d = new HashMap<String, String>();
this.c2d.put("0,0", "-");
this.c2d.put("0,-1", "N");
this.c2d.put("0,1", "S");
this.c2d.put("1,0", "E");
this.c2d.put("-1,0", "W");
this.c2d.put("-1,-1", "NW");
this.c2d.put("1,-1", "NE");
this.c2d.put("-1,1", "SW");
this.c2d.put("1,1", "SE");
}
// get the character at x,y
// or return empty string if out of bounds
public Point get(int x, int y) {
if(y < 0 || y >= this.array.length){
return null;
}
Point[] row = this.array[y];
if(x < 0 || x >= row.length) {
return null;
}
return row[x];
}
// get arraylist of Points for each adjacent space that matches the target string
public ArrayList<Point> getAdjacentMatches(Point p, String match) {
ArrayList<Point> result = new ArrayList<Point>();
for(int i=-1; i<=1; ++i) {
for(int j=-1; j<=1; ++j) {
Point found = this.get(p.x+i, p.y+j);
if((i!=0 || j!=0) && found != null && found.symbol.equals(match)) {
result.add(found);
}
}
}
return result;
}
public ArrayList<Point> getAdjacents(Point p){
ArrayList<Point> result = new ArrayList<Point>();
for(int i=-1; i<=1; ++i) {
for(int j=-1; j<=1; ++j) {
Point found = this.get(p.x+i, p.y+j);
if((i!=0 || j!=0) && found != null) {
result.add(found);
}
}
}
return result;
}
public int count(String sym){
int result = 0;
for(int y=0; y<array.length; y++){
for(int x=0; x<array[y].length; x++){
Point cur = this.get(x, y);
if(cur!=null && cur.symbol.equals(sym)){
result++;
}
}
}
return result;
}
// get the direction string from point 1 to point 2
public String getDirection(Point p1, Point p2) {
int dx = p2.x - p1.x;
int dy = p2.y - p1.y;
dx = Math.abs(dx) / (dx==0?1:dx);
dy = Math.abs(dy) / (dy==0?1:dy);
return this.c2d.get(dx + "," + dy);
}
public Point2D getCenterOf(String sym){
Point2D result = new Point2D(0,0);
int count = 0;
for(int y=0; y<array.length; y++){
for(int x=0; x<array[y].length; x++){
if(this.get(x,y).symbol.equals(sym)){
result.x += x;
result.y += y;
count++;
}
}
}
result.x /= count;
result.y /= count;
return result;
}
}
public static class Point {
int x, y;
String symbol;
public Point(int x, int y, String sym) {
this.x=x;
this.y=y;
this.symbol=sym;
}
public Point(int x, int y, char sym){
this(x, y, ""+sym);
}
}
public static class Point2D{
double x,y;
public Point2D(double x, double y){
this.x = x;
this.y = y;
}
}
}
'node c:/cell/cell_template.js'
为每个参数指定一个完全可运行的命令,就像您需要'java CellTemplate'
为Java代码指定一样。我将在挑战文本中更清楚地说明这一点。如果您仍然遇到问题,我们(以及其他存在技术问题的人)可以在我刚刚建立的聊天室中继续进行此讨论。