Flood-It-Bot/main/BotFloodIt.java

198 lines
7.0 KiB
Java
Raw Permalink Normal View History

2012-01-11 16:38:00 +02:00
package main;
import java.util.ArrayList;
/**
2012-01-11 16:55:25 +02:00
* Класс логики бота.
2012-01-11 16:38:00 +02:00
* @author aNNiMON
*/
public class BotFloodIt {
2012-01-11 16:55:25 +02:00
/* Количество цветов в игре */
2012-01-11 16:38:00 +02:00
private static final int MAX_COLORS = 6;
2012-01-11 16:55:25 +02:00
/* На сколько шагов вперёд просчитывать ход */
2012-01-11 16:38:00 +02:00
private static final int FILL_STEPS = 4;
2012-01-11 16:55:25 +02:00
/* Игровое поле */
2012-01-11 16:38:00 +02:00
private byte[][] table;
2012-01-11 16:55:25 +02:00
/* Цвета, соответствующие ID */
2012-01-11 16:38:00 +02:00
private int[] colors;
public BotFloodIt(int[][] table) {
colors = new int[MAX_COLORS];
for (int i = 0; i < colors.length; i++) {
colors[i] = -1;
}
this.table = colorsToIds(table);
}
/**
2012-01-11 16:55:25 +02:00
* Получить цвета клеток в палитре
* @return массив цветов RGB
2012-01-11 16:38:00 +02:00
*/
public int[] getColors() {
return colors;
}
/**
2012-01-11 16:55:25 +02:00
* Получить последовательность заливки цветов
* @return массив с идентификаторами цветов для заливки
2012-01-11 16:38:00 +02:00
*/
public byte[] getFillSequence() {
byte[][] copyTable = copyTable(table);
ArrayList<Byte> seq = new ArrayList<Byte>();
while(!gameCompleted(copyTable)) {
seq.add(getNextFillColor(copyTable));
}
byte[] out = new byte[seq.size()];
for (int i = 0; i < out.length; i++) {
out[i] = seq.get(i).byteValue();
}
return out;
}
/*
2012-01-11 16:55:25 +02:00
* Получить индекс следующего цвета для заливки
2012-01-11 16:38:00 +02:00
*/
private byte getNextFillColor(byte[][] table) {
2012-01-11 16:55:25 +02:00
// Количество вариантов заливок
2012-01-11 16:38:00 +02:00
int fillSize = (int) Math.pow(MAX_COLORS, FILL_STEPS);
int[] fillRate = new int[fillSize];
2012-01-11 16:55:25 +02:00
// Заполняем значениями степени заливки
2012-01-11 16:38:00 +02:00
int[] fillPow = new int[FILL_STEPS];
for (int i = 0; i < FILL_STEPS; i++) {
fillPow[i] = (int) Math.pow(MAX_COLORS, i);
}
2012-01-11 16:55:25 +02:00
// Заливаем FILL_STEPS раз MAX_COLORS вариантов
2012-01-11 16:38:00 +02:00
for (int i = 0; i < fillSize; i++) {
byte[][] iteration = copyTable(table);
for (int j = 0; j < FILL_STEPS; j++) {
byte fillColor = (byte) (i / fillPow[j] % MAX_COLORS);
fillTable(iteration, fillColor);
}
2012-01-11 16:55:25 +02:00
// Подсчитываем число залитых ячеек
2012-01-11 16:38:00 +02:00
fillRate[i] = getFillCount(iteration);
}
2012-01-11 16:55:25 +02:00
// Теперь ищем максимально залитый участок из FILL_STEPS итераций заливки
2012-01-11 16:38:00 +02:00
int maxArea = fillRate[0];
int maxColor = 0;
for (int i = 1; i < fillSize; i++) {
if (fillRate[i] > maxArea) {
maxColor = i;
maxArea = fillRate[i];
}
}
2012-01-11 16:55:25 +02:00
// Получаем цвет с наибольшей площадью дальнейшей заливки
2012-01-11 16:38:00 +02:00
byte colorID = (byte) (maxColor % MAX_COLORS);
fillTable(table, colorID);
return colorID;
}
/*
2012-01-11 16:55:25 +02:00
* Преобразование массива с цветами в массив с идентификаторами
2012-01-11 16:38:00 +02:00
*/
private byte[][] colorsToIds(int[][] tableColor) {
int size = tableColor.length;
byte[][] out = new byte[size][size];
2012-01-11 16:55:25 +02:00
int colorsReaded = 1; // сколько цветов распознано
2012-01-11 16:38:00 +02:00
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int color = tableColor[i][j];
for (byte k = 0; k < colorsReaded; k++) {
2012-01-11 16:55:25 +02:00
// Добавляем цвет в палитру
2012-01-11 16:38:00 +02:00
if (colors[k] == -1) {
colors[k] = color;
colorsReaded++;
if (colorsReaded > MAX_COLORS) colorsReaded = MAX_COLORS;
}
2012-01-11 16:55:25 +02:00
// Если цвет уже в палитре, то присваиваем ему ID
2012-01-11 16:38:00 +02:00
if (color == colors[k]) {
out[i][j] = k;
break;
}
}
}
}
return out;
}
/**
2012-01-11 16:55:25 +02:00
* Залить заданное поле цветом color
* @param table игровое поле для заливки
* @param color цвет заливки
2012-01-11 16:38:00 +02:00
*/
private void fillTable(byte[][] table, byte color) {
if (table[0][0] == color) return;
fill(table, 0, 0, table[0][0], color);
}
/*
2012-01-11 16:55:25 +02:00
* Заливка поля по координатам
2012-01-11 16:38:00 +02:00
*/
private void fill(byte[][] table, int x, int y, byte prevColor, byte color) {
2012-01-11 16:55:25 +02:00
// Проверка на выход за границы игрового поля
2012-01-11 16:38:00 +02:00
if ( (x < 0) || (y < 0) || (x >= table.length) || (y >= table.length) ) return;
if (table[x][y] == prevColor) {
table[x][y] = color;
2012-01-11 16:55:25 +02:00
// Заливаем смежные области
2012-01-11 16:38:00 +02:00
fill(table, x-1, y, prevColor, color);
fill(table, x+1, y, prevColor, color);
fill(table, x, y-1, prevColor, color);
fill(table, x, y+1, prevColor, color);
}
}
/**
2012-01-11 16:55:25 +02:00
* Получить количество залитых ячеек
* @param table игровое поле
2012-01-11 16:38:00 +02:00
*/
private int getFillCount(byte[][] table) {
return getCount(table, 0, 0, table[0][0]);
}
/*
2012-01-11 16:55:25 +02:00
* Подсчет залитых ячеек по координатам
2012-01-11 16:38:00 +02:00
*/
private int getCount(byte[][] table, int x, int y, byte color) {
2012-01-11 16:55:25 +02:00
// Проверка на выход за границы игрового поля
2012-01-11 16:38:00 +02:00
if ( (x < 0) || (y < 0) || (x >= table.length) || (y >= table.length) ) return 0;
int count = 0;
if (table[x][y] == color) {
table[x][y] = -1;
count = 1;
2012-01-11 16:55:25 +02:00
// Считаем смежные ячейки
2012-01-11 16:38:00 +02:00
count += getCount(table, x-1, y, color);
count += getCount(table, x+1, y, color);
count += getCount(table, x, y-1, color);
count += getCount(table, x, y+1, color);
}
return count;
}
/*
2012-01-11 16:55:25 +02:00
* Проверка, залита ли вся область одним цветом
2012-01-11 16:38:00 +02:00
*/
private boolean gameCompleted(byte[][] table) {
byte color = table[0][0];
int size = table.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (table[i][j] != color) return false;
}
}
return true;
}
/*
2012-01-11 16:55:25 +02:00
* Копирование массива игрового поля
2012-01-11 16:38:00 +02:00
*/
private byte[][] copyTable(byte[][] table) {
int size = table.length;
byte[][] out = new byte[size][size];
for (int i = 0; i < size; i++) {
System.arraycopy(table[i], 0, out[i], 0, size);
}
return out;
}
}