浅蓝
浅蓝色试图通过对可能的动作进行详尽的树形研究来找出未来可能发生的情况,但不幸的是,他的下一步行动没有其他进展。然后,他在下一个回合之后在每个可能的董事会状态上打些半估的分数,并用同样可笑的公式为每个分支计算分数,并且:瞧,理想的举动众所周知!
编辑:原始代码的运行速度太慢,所以我对其进行了修改,以便仅对所有可能的动作进行随机采样。当可能的动作很少时,它将尝试几乎所有动作,而当可能的动作更多时,它将尝试较小的百分比。
import java.awt.Point;
public class ShallowBlue {
private static final int MAX_ROUNDS = 5, PLAYERS = 4;
static int me = 0;
public static void main(String[] args) {
if (args[0] == null) {
return;
}
me = Integer.parseInt(args[0].split(",", 2)[0]);
String board = args[0].split(",", 2)[1];
System.out.println(getBestMove(board, me, MAX_ROUNDS - 1));
}
private static String getBestMove(String board, int player, int rounds) {
String [] boards = new String[24];
int checkedBoards = 1;
char playerChar = Integer.toString(player).charAt(0);
String tempMove = getMove(0, 0, 0, 0);
String tempBoard = calculateMove(board, tempMove);
boards[0] = tempBoard;
String bestMove = tempMove;
double us = numberOfUs(board, playerChar);
double skip = (us*2.5/(us*2.5 + 1))/4 + 0.735;
if (rounds == MAX_ROUNDS - 2) {
skip = skip*skip;
}
float bestScore, worstScore, averageScore, tempScore;
int scores;
if (rounds == 0) {
tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
} else {
tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
}
scores = 1;
bestScore = tempScore;
worstScore = tempScore;
averageScore = tempScore;
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
if (getCharAt(board, x, y) == playerChar) {
Point[] possibleMergers = getNeighboringMatches(board, new Point(x, y), playerChar);
if (possibleMergers[0] != null) {
tempMove = getMove(possibleMergers[0].x, possibleMergers[0].y, x, y);
tempBoard = calculateMove(board, tempMove);
if (addIfUnique(boards, tempBoard, checkedBoards)) {
checkedBoards++;
if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
} else {
tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
}
if (tempScore > bestScore) {
bestMove = tempMove;
}
bestScore = Math.max(tempScore, bestScore);
worstScore = Math.min(tempScore, worstScore);
scores++;
averageScore = (averageScore*(scores - 1) + tempScore)/scores;
}
}
} else if (getCharAt(board, x, y) == '.') {
Point[] possibleSpreaders = getNeighboringMatches(board, new Point(x, y), playerChar);
int i = 0;
while (i < possibleSpreaders.length && possibleSpreaders[i] != null) {
tempMove = getMove(possibleSpreaders[i].x, possibleSpreaders[i].y, x, y);
tempBoard = calculateMove(board, tempMove);
if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
} else {
tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
}
if (tempScore > bestScore) {
bestMove = tempMove;
}
bestScore = Math.max(tempScore, bestScore);
worstScore = Math.min(tempScore, worstScore);
scores++;
averageScore = (averageScore*(scores - 1) + tempScore)/scores;
i++;
}
Point[] possibleJumpers = getNextNeighboringMatches(board, new Point(x, y), playerChar);
i = 0;
while (i < possibleJumpers.length && possibleJumpers[i] != null) {
tempMove = getMove(possibleJumpers[i].x, possibleJumpers[i].y, x, y);
tempBoard = calculateMove(board, tempMove);
if ((rounds != MAX_ROUNDS - 1) && (rounds == 0 || Math.random() < skip)) {
tempScore = calculateScore(tempBoard, MAX_ROUNDS - rounds - 1);
} else {
tempScore = getScore(getBestMove(tempBoard, player%PLAYERS + 1, rounds - 1));
}
if (tempScore > bestScore) {
bestMove = tempMove;
}
bestScore = Math.max(tempScore, bestScore);
worstScore = Math.min(tempScore, worstScore);
scores++;
averageScore = (averageScore*(scores - 1) + tempScore)/scores;
i++;
}
}
}
}
if (rounds == MAX_ROUNDS - 1) {
return (bestMove);
} else {
return getScoreString(bestScore, worstScore, averageScore);
}
}
private static int numberOfUs(String board, char playerChar) {
int us = 0;
for (int i = 0; i < board.length(); i++ ) {
if (board.charAt(i) == playerChar) {
us++;
}
}
return us;
}
private static float calculateScore(String board, int roundsPassed) {
int empties = 0;
int us = 0;
int enemy1 = 0;
int enemy2 = 0;
int enemy3 = 0;
for (int i = 0; i < board.length(); i++ ) {
if (board.charAt(i) == '.') {
empties++;
} else if (board.charAt(i) == Integer.toString(me).charAt(0)) {
us++;
} else if (board.charAt(i) == Integer.toString(me%PLAYERS + 1).charAt(0)) {
enemy1++;
} else if (board.charAt(i) == Integer.toString(me%PLAYERS + 2).charAt(0)) {
enemy2++;
} else if (board.charAt(i) == Integer.toString(me%PLAYERS + 3).charAt(0)) {
enemy3++;
}
}
if (us != 0) {
us += roundsPassed;
}
if (enemy1 != 0) {
enemy1 = enemy1 + (roundsPassed + 3)%PLAYERS;
}
if (enemy2 != 0) {
enemy2 = enemy2 + (roundsPassed + 2)%PLAYERS;
}
if (enemy3 != 0) {
enemy3 = enemy3 + (roundsPassed + 1)%PLAYERS;
}
return us*(empties + 1)/(Math.max(Math.max(enemy1, enemy2), enemy3) + 1);
}
private static float getScore(String scoreString) {
float bestScore, worstScore, averageScore;
String[] scores = new String[3];
scores = scoreString.split(",");
bestScore = Float.parseFloat(scores[0]);
worstScore = Float.parseFloat(scores[1]);
averageScore = Float.parseFloat(scores[2]);
return (float) Math.sqrt(Math.sqrt(bestScore*averageScore*worstScore*worstScore));
}
private static String getScoreString(float bestScore, float worstScore, float averageScore) {
return Float.toString(bestScore) + ',' + Float.toString(worstScore) + ',' + Float.toString(averageScore);
}
private static boolean addIfUnique(String[] boards, String board, int checkedBoards) {
int i = 0;
while (i < boards.length && boards[i] != null) {
if (boards[i].equals(board)) {
return false;
}
i++;
}
if (i < boards.length) {
boards[i] = board;
} else {
boards[checkedBoards%boards.length] = board;
}
return true;
}
private static String calculateMove(String board, String move) {
int x1 = Integer.parseInt(Character.toString(move.charAt(0)));
int y1 = Integer.parseInt(Character.toString(move.charAt(2)));
int x2 = Integer.parseInt(Character.toString(move.charAt(4)));
int y2 = Integer.parseInt(Character.toString(move.charAt(6)));
if ((Math.abs(y1 - y2) == 2 || Math.abs(x1 - x2) == 2)
&& getCharAt(board, x2, y2) == '.') {
Point[] enemies = new Point[8];
enemies = getNeighboringEnemies(board, new Point(x1, y1), Integer.parseInt(Character.toString(getCharAt(board, x1, y1))));
board = replace(board, enemies, getCharAt(board, x1, y1));
Point[] middle = {new Point(x1, y1)};
board = replace(board, middle, '.');
}
if ((Math.abs(y1 - y2) == 1 || Math.abs(x1 - x2) == 1)) {
if (getCharAt(board, x2, y2) == '.' || getCharAt(board, x1, y1) == getCharAt(board, x2, y2)) {
boolean merge = true;
if (getCharAt(board, x2, y2) == '.') {
merge = false;
}
Point[] spaces = new Point[8];
spaces = getNeighboringMatches(board, new Point(x1, y1), '.');
board = replace(board, spaces, getCharAt(board, x1, y1));
if (merge) {
Point[] source = {new Point(x1, y1)};
board = replace(board, source, '.');
}
}
}
return board;
}
private static String replace(String board, Point[] targets, char source) {
int i = 0;
while (i < targets.length && targets[i] != null) {
if (targets[i].x == 7 && targets[i].y == 7) {
board = board.substring(0, getIndexAt(targets[i].x, targets[i].y)) + source;
} else if (targets[i].x == 0 && targets[i].y == 0) {
board = source + board.substring(getIndexAt(targets[i].x, targets[i].y) + 1);
} else {
board = board.substring(0, getIndexAt(targets[i].x, targets[i].y)) + source + board.substring(getIndexAt(targets[i].x, targets[i].y) + 1);
}
i++;
}
return board;
}
private static Point[] getNeighboringMatches(String board, Point coord, char match) {
Point[] matches = new Point[8];
int i = 0;
for (int x = coord.x - 1; x <= coord.x + 1; x++) {
for (int y = coord.y - 1; y <= coord.y + 1; y++) {
if ((y != coord.y || x != coord.x ) && getCharAt(board, x, y) == match){
matches[i] = new Point(x, y);
i++;
}
}
}
return matches;
}
private static Point[] getNeighboringEnemies(String board, Point coord, int player) {
Point[] enemies = new Point[8];
for (int i = 1; i <= PLAYERS; i++){
enemies = mergeArr(enemies, getNeighboringMatches(board, coord, Integer.toString((player + i - 1)%PLAYERS + 1).charAt(0)));
}
return enemies;
}
private static Point[] getNextNeighboringMatches(String board, Point coord, char match) {
Point[] matches = new Point[16];
int i = 0;
for (int x = coord.x - 2; x <= coord.x + 2; x++) {
for (int y = coord.y - 2; y <= coord.y + 2; y++) {
if ((Math.abs(y - coord.y) == 2 || Math.abs(x - coord.x) == 2) && getCharAt(board, x, y) == match){
matches[i] = new Point(x, y);
i++;
}
}
}
return matches;
}
private static char getCharAt(String board, int x, int y) {
if (x >= 0 && x < 8 && y >= 0 && y < 8) {
return board.charAt(9*x + y);
} else {
return '\0';
}
}
private static int getIndexAt(int x, int y) {
return 9*x + y;
}
private static Point[] mergeArr(Point[] arr1, Point[] arr2) {
int i = 0;
int j = 0;
while (i < arr1.length && arr1[i] != null) {
i++;
}
while (j < arr2.length && arr2[j] != null) {
arr1[i + j] = arr2[j];
j++;
}
return arr1;
}
private static String getMove(int x1, int y1, int x2, int y2) {
return Integer.toString(x1) + " " + Integer.toString(y1) + " " + Integer.toString(x2) + " " + Integer.toString(y2);
}
}