Added sources

This commit is contained in:
Victor Melnik 2012-01-11 16:38:00 +02:00
commit 59fdc4a3c0
5 changed files with 1228 additions and 0 deletions

197
main/BotFloodIt.java Normal file
View File

@ -0,0 +1,197 @@
package main;
import java.util.ArrayList;
/**
* Êëàññ ëîãèêè áîòà.
* @author aNNiMON
*/
public class BotFloodIt {
/* Êîëè÷åñòâî öâåòîâ â èãðå */
private static final int MAX_COLORS = 6;
/* Íà ñêîëüêî øàãîâ âïåð¸ä ïðîñ÷èòûâàòü õîä */
private static final int FILL_STEPS = 4;
/* Èãðîâîå ïîëå */
private byte[][] table;
/* Öâåòà, ñîîòâåòñòâóþùèå ID */
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);
}
/**
* Ïîëó÷èòü öâåòà êëåòîê â ïàëèòðå
* @return ìàññèâ öâåòîâ RGB
*/
public int[] getColors() {
return colors;
}
/**
* Ïîëó÷èòü ïîñëåäîâàòåëüíîñòü çàëèâêè öâåòîâ
* @return ìàññèâ ñ èäåíòèôèêàòîðàìè öâåòîâ äëÿ çàëèâêè
*/
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;
}
/*
* Ïîëó÷èòü èíäåêñ ñëåäóþùåãî öâåòà äëÿ çàëèâêè
*/
private byte getNextFillColor(byte[][] table) {
// Êîëè÷åñòâî âàðèàíòîâ çàëèâîê
int fillSize = (int) Math.pow(MAX_COLORS, FILL_STEPS);
int[] fillRate = new int[fillSize];
// Çàïîëíÿåì çíà÷åíèÿìè ñòåïåíè çàëèâêè
int[] fillPow = new int[FILL_STEPS];
for (int i = 0; i < FILL_STEPS; i++) {
fillPow[i] = (int) Math.pow(MAX_COLORS, i);
}
// Çàëèâàåì FILL_STEPS ðàç MAX_COLORS âàðèàíòîâ
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);
}
// Ïîäñ÷èòûâàåì ÷èñëî çàëèòûõ ÿ÷ååê
fillRate[i] = getFillCount(iteration);
}
// Òåïåðü èùåì ìàêñèìàëüíî çàëèòûé ó÷àñòîê èç FILL_STEPS èòåðàöèé çàëèâêè
int maxArea = fillRate[0];
int maxColor = 0;
for (int i = 1; i < fillSize; i++) {
if (fillRate[i] > maxArea) {
maxColor = i;
maxArea = fillRate[i];
}
}
// Ïîëó÷àåì öâåò ñ íàèáîëüøåé ïëîùàäüþ äàëüíåéøåé çàëèâêè
byte colorID = (byte) (maxColor % MAX_COLORS);
fillTable(table, colorID);
return colorID;
}
/*
* Ïðåîáðàçîâàíèå ìàññèâà ñ öâåòàìè â ìàññèâ ñ èäåíòèôèêàòîðàìè
*/
private byte[][] colorsToIds(int[][] tableColor) {
int size = tableColor.length;
byte[][] out = new byte[size][size];
int colorsReaded = 1; // ñêîëüêî öâåòîâ ðàñïîçíàíî
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++) {
// Äîáàâëÿåì öâåò â ïàëèòðó
if (colors[k] == -1) {
colors[k] = color;
colorsReaded++;
if (colorsReaded > MAX_COLORS) colorsReaded = MAX_COLORS;
}
// Åñëè öâåò óæå â ïàëèòðå, òî ïðèñâàèâàåì åìó ID
if (color == colors[k]) {
out[i][j] = k;
break;
}
}
}
}
return out;
}
/**
* Çàëèòü çàäàííîå ïîëå öâåòîì color
* @param table èãðîâîå ïîëå äëÿ çàëèâêè
* @param color öâåò çàëèâêè
*/
private void fillTable(byte[][] table, byte color) {
if (table[0][0] == color) return;
fill(table, 0, 0, table[0][0], color);
}
/*
* Çàëèâêà ïîëÿ ïî êîîðäèíàòàì
*/
private void fill(byte[][] table, int x, int y, byte prevColor, byte color) {
// Ïðîâåðêà íà âûõîä çà ãðàíèöû èãðîâîãî ïîëÿ
if ( (x < 0) || (y < 0) || (x >= table.length) || (y >= table.length) ) return;
if (table[x][y] == prevColor) {
table[x][y] = color;
// Çàëèâàåì ñìåæíûå îáëàñòè
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);
}
}
/**
* Ïîëó÷èòü êîëè÷åñòâî çàëèòûõ ÿ÷ååê
* @param table èãðîâîå ïîëå
*/
private int getFillCount(byte[][] table) {
return getCount(table, 0, 0, table[0][0]);
}
/*
* Ïîäñ÷åò çàëèòûõ ÿ÷ååê ïî êîîðäèíàòàì
*/
private int getCount(byte[][] table, int x, int y, byte color) {
// Ïðîâåðêà íà âûõîä çà ãðàíèöû èãðîâîãî ïîëÿ
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;
// Ñ÷èòàåì ñìåæíûå ÿ÷åéêè
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;
}
/*
* Ïðîâåðêà, çàëèòà ëè âñÿ îáëàñòü îäíèì öâåòîì
*/
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;
}
/*
* Êîïèðîâàíèå ìàññèâà èãðîâîãî ïîëÿ
*/
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;
}
}

369
main/ImageUtils.java Normal file
View File

@ -0,0 +1,369 @@
package main;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* Êëàññ îáðàáîòêè èçîáðàæåíèé.
* @author aNNiMON
*/
public class ImageUtils {
/* Çà ñêîëüêî òî÷åê ìû áóäåì óçíàâàòü ïðåîáëàäàþùèé ôîí */
private static final int MAX_COLOR_POINTS = 50;
/* ×óâñòâèòåëüíîñòü ê ïîèñêó êíîïîê */
private static final int FIND_BUTTON_TOLERANCE = 20;
/* Èçîáðàæåíèå îêíà */
private BufferedImage image;
/* Ðàçìåð èçîáðàæåíèÿ */
private int w, h;
/* Ðàçìåðíîñòü ïîëÿ */
private int boardSize;
/* Ðàçìåð ÿ÷ååê */
private int cellSize;
/* Êîîðäèíàòà óãëà èãðîâîãî ïîëÿ */
private Point board;
/* Ìîíîõðîìíîå ïðåäñòàâëåíèå èçîáðàæåíèÿ */
private boolean[] monochrome;
/**
* Êîíñòðóêòîð äëÿ îïðåäåëåíèÿ íàñòðîåê
* @param image
* @param boardSize
*/
public ImageUtils(BufferedImage image, int boardSize) {
this.image = image;
this.boardSize = boardSize;
w = image.getWidth();
h = image.getHeight();
}
/**
* Êîíñòðóêòîð äëÿ ïðîâåðêè íàñòðîåê
* @param image
* @param boardSize
* @param cellSize
* @param x
* @param y
*/
public ImageUtils(BufferedImage image, int boardSize, int cellSize, int x, int y) {
this.image = image;
this.boardSize = boardSize;
this.cellSize = cellSize;
this.board = new Point(x, y);
w = image.getWidth();
h = image.getHeight();
}
/**
* Ïîëó÷èòü ðàçìåð ÿ÷åéêè
* @return
*/
public int getCellSize() {
return cellSize;
}
/**
* Ïîëó÷èòü êîîðäèíàòû èãðîâîãî ïîëÿ
* @return òî÷êà ñ êîîðäèíàòàìè ëåâîãî âåðõíåãî óãëà ïîëÿ
*/
public Point getBoardParameters() {
int[] pixels = new int[w * h];
image.getRGB(0, 0, w, h, pixels, 0, w);
monochrome = threshold(pixels, 64);
board = getBoardXY(boardSize);
return board;
}
/**
* Ïîëó÷èòü èçîáðàæåíèå èãðîâîãî ïîëÿ
* @return êàðòèíêà èãðîâîãî ïîëÿ
*/
public BufferedImage getBoardImage() {
int size = cellSize * boardSize;
try {
return image.getSubimage(board.x, board.y, size, size);
} catch (Exception e) {
return image;
}
}
/**
* Ïîëó÷èòü êîîðäèíàòû êíîïîê äëÿ àâòîìàòè÷åñêîãî íàæàòèÿ
* @param colors ìàññèâ öâåòîâ, ïî êîòîðûì áóäåì èñêàòü êíîïêè
* @return ìàññèâ êîîðäèíàò ñ òî÷êàìè, èëè null - åñëè íå óäàëîñü íàéòè
*/
public Point[] getButtons(int[] colors) {
Point[] out = new Point[colors.length];
// Ðàçìåð èãðîâîãî ïîëÿ â ïèêñåëàõ
int size = boardSize * cellSize;
// Ðàçìåðû ÷àñòåé èçîáðàæåíèÿ, íà êîòîðûõ áóäåì èñêàòü êíîïêè
Rectangle[] partsOfImage = new Rectangle[] {
new Rectangle(0, board.y, board.x, size), // ñëåâà îò ïîëÿ
new Rectangle(0, 0, w, board.y), // ñâåðõó îò ïîëÿ
new Rectangle(board.x+size, board.y,
w-board.x-size, size), // ñïðàâà îò ïîëÿ
new Rectangle(0, board.y+size,
w, h-board.x-size) // ñíèçó îò ïîëÿ
};
for (int i = 0; i < partsOfImage.length; i++) {
Rectangle rect = partsOfImage[i];
BufferedImage part = image.getSubimage(rect.x, rect.y, rect.width, rect.height);
// Âûðåçàåì ÷àñòü èçîáðàæåíèÿ, â êîòîðîì áóäåì èñêàòü
boolean found = true;
for (int j = 0; j < colors.length; j++) {
if (colors[i] == -1) continue;
Point pt = findButton(part, colors[j]);
if (pt != null) {
// Ó÷èòûâàåì ñìåùåíèÿ îòíîñèòåëüíî ÷àñòåé êàðòèíîê
pt.translate(rect.x, rect.y);
out[j] = pt;
} else {
found = false;
break;
}
}
if (found) return out;
}
// Íå óäàëîñü íàéòè âñå òî÷êè
return null;
}
/**
* Ïðåîáðàçîâàòü ìàññèâ öâåòîâ â ãðàôè÷åñêèé âèä
* @param ids ìàññèâ èäåíòèôèêàòîðîâ ïîñëåäîâàòåëüíîñòè
* @param palette ìàññèâ ïàëèòðû öâåòîâ
* @return èçîáðàæåíèå ïîñëåäîâàòåëüíîñòè öâåòîâ
*/
public BufferedImage sequenceToImage(byte[] ids, int[] palette) {
final int size = 20; // ðàçìåð êàæäîé ÿ÷åéêè
// Ðàçáèâàòü áóäåì ïî 10 êëåòîê íà ñòðîêó
final int CELLS_IN_ROW = 10;
int width = CELLS_IN_ROW * size;
if (width == 0) width = size;
int rows = ids.length / CELLS_IN_ROW;
BufferedImage out = new BufferedImage(width, (rows*size)+size, BufferedImage.TYPE_INT_RGB);
Graphics G = out.getGraphics();
for (int i = 0; i < ids.length; i++) {
G.setColor(new Color(palette[ids[i]]));
G.fillRect(i % CELLS_IN_ROW * size,
i / CELLS_IN_ROW * size,
size, size);
}
G.dispose();
return out;
}
/**
* Ïðåîáðàçîâàòü öâåòíîå èçîáðàæåíèå â ìîíîõðîìíîå.
* Íóæíî òàêæå ó÷åñòü, ÷òî åñëè ïîëå ðàñïîëîæåíî íà ñâåòëîì
* ôîíå, òî íåîáõîäèìî èíâåðòèðîâàòü èçîáðàæåíèå, ÷òîáû
* ïîëó÷èòü ñïëîøíóþ áåëóþ îáëàñòü íà ìåñòå ïîëÿ.
* @param pixels ìàññèâ ïèêñåëåé èçîáðàæåíèÿ
* @param value ðàçäåëÿþùåå çíà÷åíèå
* @return ìàññèâ boolean, true - áåëûé, false - ÷¸ðíûé
*/
private boolean[] threshold(int[] pixels, int value) {
boolean inverse = isBackgroundLight(MAX_COLOR_POINTS);
if (inverse) value = 255 - value;
boolean[] bw = new boolean[pixels.length];
for (int i = 0; i < pixels.length; i++) {
int brightNess = getBrightness(pixels[i]);
bw[i] = (brightNess >= value) ^ inverse;
}
return bw;
}
/**
* Ïîëó÷åíèå ñîñòîÿíèÿ ÿðêîñòè ôîíà.
* @param numPoints ñêîëüêî òî÷åê íóæíî äëÿ îïðåäåëåíèÿ.
* @return true - ôîí ñâåòëûé, false - ò¸ìíûé
*/
private boolean isBackgroundLight(int numPoints) {
// Ïîëó÷àåì numPoints ñëó÷àéíûõ òî÷åê
Random rnd = new Random();
int[] colors = new int[numPoints];
for (int i = 0; i < numPoints; i++) {
int x = rnd.nextInt(w);
int y = rnd.nextInt(h);
colors[i] = image.getRGB(x, y);
}
// Íàõîäèì ñðåäíþþ ÿðêîñòü âñåõ numPoints òî÷åê
long sum = 0;
for (int i = 0; i < numPoints; i++) {
int brightness = getBrightness(colors[i]);
sum = sum + brightness;
}
sum = sum / numPoints;
return (sum > 128);
}
/**
* Îïðåäåëèòü êîîðäèíàòû ëåâîé âåðõíåé ÿ÷åéêè èãðîâîãî ïîëÿ.
* @param boardSize ðàçìåðíîñòü ïîëÿ (10x10, 14x14 è ò.ä.)
* @return êîîðäèíàòà ëåâîãî âåðõíåãî ïðÿìîóãîëüíèêà
*/
private Point getBoardXY(int boardSize) {
/*
* Ñíà÷àëà ïîäñ÷èòàåì êîëè÷åñòâî áåëûõ òî÷åê ïî ãîðèçîíòàëè è âåðòèêàëè
*/
int[] horizontal = new int[h];
for (int i = 0; i < h; i++) {
int count = 0;
for (int j = 0; j < w; j++) {
if (getBWPixel(j, i)) count++;
}
horizontal[i] = count;
}
int[] vertical = new int[w];
for (int i = 0; i < w; i++) {
int count = 0;
for (int j = 0; j < h; j++) {
if (getBWPixel(i, j)) count++;
}
vertical[i] = count;
}
/*
* Çàòåì "îòôèëüòðóåì" ëèøíåå: ïîäñ÷èòàåì ñðåäíåå çíà÷åíèå
* è íà åãî îñíîâå óáåð¸ì ìàëîçíà÷èìûå ñòðîêè è ñòîëáöû.
*/
horizontal = filterByMean(horizontal);
vertical = filterByMean(vertical);
/*
* Èùåì íàèáîëüøóþ íåíóëåâóþ ïîñëåäîâàòåëüíîñòü.
* Èíäåêñû ãðàíèö ïîñëåäîâàòåëüíîñòè è áóäóò ãðàíè÷íûìè òî÷êàìè ïîëÿ.
*/
int[] vParam = getParamsFromSequence(horizontal);
int[] hParam = getParamsFromSequence(vertical);
int outX = hParam[0];
int outY = vParam[0];
int outWidth = hParam[1];
int outHeight = vParam[1];
// Ïîäñ÷åò ðàçìåðà ÿ÷åéêè
cellSize = Math.max((outWidth / boardSize), (outHeight / boardSize));
return new Point(outX, outY);
}
/**
* Ôèëüòð ïîñëåäîâàòåëüíîñòè îò ìàëîçíà÷èìûõ çíà÷åíèé.
* @param source ïîñëåäîâàòåëüíîñòü âõîæäåíèé öâåòà
* @return îòôèëüòðîâàííûé ìàññèâ ñî çíà÷åíèÿìè 0 è 1
*/
private int[] filterByMean(int[] source) {
long mean = 0;
for (int i = 0; i < source.length; i++) {
mean += source[i];
}
mean = mean / source.length;
for (int i = 0; i < source.length; i++) {
source[i] = (source[i] > mean) ? 1 : 0;
}
return source;
}
/**
* Ïîèñê ñàìîé äëèííîé ïîñëåäîâàòåëüíîñòè â ìàññèâå.
* @param source âõîäíàÿ ïîñëåäîâàòåëüíîñòü èç íóëåé è åäèíèö
* @return ìàññèâ ïàðàìåòðîâ - èíäåêñ íà÷àëà ïîñëåäîâàòåëüíîñòè è å¸ äëèíà
*/
private int[] getParamsFromSequence(int[] source) {
int maxStart = 0, start = 0;
int maxLength = 0, length = 0;
for (int i = 1; i < source.length; i++) {
if (source[i] == 0) {
start = 0;
length = 0;
continue;
}
if (source[i] == source[i-1]) {
length++;
if (maxLength < length) {
maxStart = start;
maxLength = length;
}
} else {
// Åñëè ïðåäûäóùèé ýëåìåíò áûë íóëåâûì - íà÷èíàåì íîâóþ ïîñëåäîâàòåëüíîñòü
start = i;
}
}
return new int[] {maxStart, maxLength};
}
/**
* Ïîèñê êîîðäèíàòû êíîïêè ñ öâåòîì template
* @param img èçîáðàæåíèå, íà êîòîðîì áóäåì èñêàòü
* @param template øàáëîí öâåòà
* @return êîîðäèíàòà X. Y, èëè null åñëè íå íàøëè
*/
private Point findButton(BufferedImage img, int template) {
int h2 = img.getHeight() / 2;
// Èñêàòü áóäåì ñ ñåðåäèíû ïî âåðòèêàëè, òàê áûñòðåå íàéä¸ì
for (int y = 0; y < h2; y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, h2 - y);
if (isEquals(color, template, FIND_BUTTON_TOLERANCE)) {
return new Point(x, h2 - y);
}
color = img.getRGB(x, h2 + y);
if (isEquals(color, template, FIND_BUTTON_TOLERANCE)) {
return new Point(x, h2 + y);
}
}
}
// Íå íàøëè
return null;
}
/**
* Ïðîâåðêà íà ñîîòâåòñòâèå öâåòîâ äðóã äðóãó
* @param color1 ïåðâûé öâåò
* @param color2 âòîðîé öâåò
* @param tolerance ÷óâñòâèòåëüíîñòü
* @return true - ñîîòâåòñòâóþò, false - íåò
*/
private boolean isEquals(int color1, int color2, int tolerance) {
if (tolerance < 2) return color1 == color2;
int r1 = (color1 >> 16) & 0xff;
int g1 = (color1 >> 8) & 0xff;
int b1 = color1 & 0xff;
int r2 = (color2 >> 16) & 0xff;
int g2 = (color2 >> 8) & 0xff;
int b2 = color2 & 0xff;
return (Math.abs(r1 - r2) <= tolerance) &&
(Math.abs(g1 - g2) <= tolerance) &&
(Math.abs(b1 - b2) <= tolerance);
}
/**
* Ïîëó÷åíèå ÿðêîñòè öâåòà
* @param color èñõîäíûé öâåò
* @return ÿðêîñòü (0..255)
*/
private int getBrightness(int color) {
int qr = (color >> 16) & 0xff;
int qg = (color >> 8) & 0xff;
int qb = color & 0xff;
return (qr + qg + qb) / 3;
}
/*
* Ïîëó÷åíèå öâåòà èç ìîíîõðîìíîãî èçîáðàæåíèÿ.
* return true - áåëûé, false - ÷¸ðíûé
*/
private boolean getBWPixel(int x, int y) {
if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) return false;
return monochrome[y * w + x];
}
}

222
main/RobotFrame.form Normal file
View File

@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="3"/>
<Property name="title" type="java.lang.String" value="FloodItBot"/>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="windowPanel" max="32767" attributes="1"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="startStop" pref="172" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="57" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="windowPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="startStop" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="startStop">
<Properties>
<Property name="text" type="java.lang.String" value="Start"/>
<Property name="actionCommand" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="startStopActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Bot for FloodIt"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="windowPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Options"/>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="detectButton" alignment="0" pref="140" max="32767" attributes="0"/>
<Component id="checkButton" alignment="1" pref="140" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="1">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="windowXTextField" min="-2" pref="35" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="windowYTextField" min="-2" pref="35" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="boardSizeSpinner" min="-2" pref="45" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cellSizeSpinner" min="-2" pref="45" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="windowXTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="windowYTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cellSizeSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="boardSizeSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="detectButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="checkButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JTextField" name="windowXTextField">
<Properties>
<Property name="text" type="java.lang.String" value="0"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" value="x:"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="windowYTextField">
<Properties>
<Property name="text" type="java.lang.String" value="0"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String" value="y:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="text" type="java.lang.String" value="Window:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="text" type="java.lang.String" value="Cell size:"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="checkButton">
<Properties>
<Property name="text" type="java.lang.String" value="Check"/>
<Property name="actionCommand" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JSpinner" name="boardSizeSpinner">
</Component>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="11" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="Field size:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="cellSizeSpinner">
</Component>
<Component class="javax.swing.JButton" name="detectButton">
<Properties>
<Property name="text" type="java.lang.String" value="Detect"/>
<Property name="actionCommand" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="detectButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_SerializeTo" type="java.lang.String" value="RobotFrame_detectButton"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

362
main/RobotFrame.java Normal file
View File

@ -0,0 +1,362 @@
package main;
import java.awt.AWTException;
import java.awt.Point;
import java.awt.image.BufferedImage;
import javax.swing.*;
/**
* Îêíî ïðèëîæåíèÿ.
* @author aNNiMON
*/
public class RobotFrame extends JFrame {
/* Ñòàòóñ ðàáîòû ïðèëîæåíèÿ */
private boolean isRunning;
private Thread robotAction;
/** Creates new form RobotFrame */
public RobotFrame() {
initComponents();
isRunning = false;
setAlwaysOnTop(true);
boardSizeSpinner.setModel(new SpinnerNumberModel(14, 5, 40, 1));
cellSizeSpinner.setModel(new SpinnerNumberModel(24, 5, 100, 1));
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
startStop = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
windowPanel = new javax.swing.JPanel();
windowXTextField = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
windowYTextField = new javax.swing.JTextField();
jLabel3 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
checkButton = new javax.swing.JButton();
boardSizeSpinner = new javax.swing.JSpinner();
jLabel7 = new javax.swing.JLabel();
cellSizeSpinner = new javax.swing.JSpinner();
detectButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("FloodItBot");
setResizable(false);
startStop.setText("Start");
startStop.setActionCommand("");
startStop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
startStopActionPerformed(evt);
}
});
jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel1.setText("Bot for FloodIt");
jLabel1.setFocusable(false);
jLabel1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
windowPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Options"));
windowXTextField.setText("0");
jLabel2.setText("x:");
windowYTextField.setText("0");
jLabel3.setText("y:");
jLabel5.setText("Window:");
jLabel6.setText("Cell size:");
checkButton.setText("Check");
checkButton.setActionCommand("");
checkButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
checkButtonActionPerformed(evt);
}
});
jLabel7.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
jLabel7.setText("Field size:");
detectButton.setText("Detect");
detectButton.setActionCommand("");
detectButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
detectButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout windowPanelLayout = new javax.swing.GroupLayout(windowPanel);
windowPanel.setLayout(windowPanelLayout);
windowPanelLayout.setHorizontalGroup(
windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(windowPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(detectButton, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
.addComponent(checkButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
.addGroup(windowPanelLayout.createSequentialGroup()
.addGroup(windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addGroup(windowPanelLayout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(windowXTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(windowYTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(windowPanelLayout.createSequentialGroup()
.addComponent(jLabel7)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(boardSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(windowPanelLayout.createSequentialGroup()
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cellSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
windowPanelLayout.setVerticalGroup(
windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(windowPanelLayout.createSequentialGroup()
.addComponent(jLabel5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(windowXTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3)
.addComponent(windowYTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel6)
.addComponent(cellSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(windowPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(boardSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(detectButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(checkButton))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(windowPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(startStop, javax.swing.GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGap(57, 57, 57)
.addComponent(jLabel1)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addComponent(windowPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(startStop)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void startStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startStopActionPerformed
if (isRunning) {
startStop.setText("Start");
isRunning = false;
} else {
startStop.setText("Stop");
isRunning = true;
robotAction = new Thread(new Runnable() {
@Override
public void run() {
int windowX, windowY, boardSize, cellSize;
BufferedImage detectImage;
RobotUtils robot;
// Ïîëó÷àåì íàñòðîéêè
try {
robot = new RobotUtils();
detectImage = robot.getImage(-1, -1, -1, -1);
windowX = Integer.valueOf(windowXTextField.getText());
windowY = Integer.valueOf(windowYTextField.getText());
boardSize = (Integer) boardSizeSpinner.getValue();
cellSize = (Integer) cellSizeSpinner.getValue();
} catch (Exception ex) {
ex.printStackTrace();
return;
}
ImageUtils iu = new ImageUtils(detectImage, boardSize, cellSize, windowX, windowY);
// Îáðåçàåì êàðòèíêó äî âèäà èãðîâîãî ïîëÿ
detectImage = iu.getBoardImage();
// Ïîëó÷àåì öâåòà èç êàðòèíêè
int[][] table = new int[boardSize][boardSize];
int offset = cellSize / 2;
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
table[i][j] = detectImage.getRGB(j*cellSize + offset,
i*cellSize + offset);
}
}
BotFloodIt bfi = new BotFloodIt(table);
// Ïîëó÷àåì ðåçóëüòèðóþùóþ ïîñëåäîâàòåëüíîñòü öâåòîâ
byte[] result = bfi.getFillSequence();
int[] colors = bfi.getColors();
// Ïûòàåìñÿ ïîëó÷èòü êîîðäèíàòû êíîïîê äëÿ àâòîìàòè÷åñêîé èãðû
Point[] buttons = iu.getButtons(colors);
if (buttons == null) {
// Åñëè íå óäàëîñü íàéòè êíîïêè, òî ïðîñòî âûâîäèì ïîñëåäîâàòåëüíîñòü â âèäå êàðòèíêè
BufferedImage out = iu.sequenceToImage(result, colors);
showImageWindow("Result: "+result.length+" steps", out);
} else {
// Çàïóñêàåì àâòîèãðó
robot.autoClick(buttons, result);
}
isRunning = false;
startStop.setText("Start");
}
});
robotAction.start();
}
}//GEN-LAST:event_startStopActionPerformed
private void checkButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkButtonActionPerformed
if (isRunning) return; // íåëüçÿ ïðîâåðÿòü íàñòðîéêè âî âðåìÿ ðàáîòû
int windowX, windowY, boardSize, cellSize;
BufferedImage detectImage;
RobotUtils robot;
try {
robot = new RobotUtils();
detectImage = robot.getImage(-1, -1, -1, -1);
windowX = Integer.valueOf(windowXTextField.getText());
windowY = Integer.valueOf(windowYTextField.getText());
boardSize = (Integer) boardSizeSpinner.getValue();
cellSize = (Integer) cellSizeSpinner.getValue();
} catch (Exception ex) {
ex.printStackTrace();
return;
}
ImageUtils iu = new ImageUtils(detectImage, boardSize, cellSize, windowX, windowY);
showImageWindow("Checking", iu.getBoardImage());
}//GEN-LAST:event_checkButtonActionPerformed
private void detectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_detectButtonActionPerformed
if (isRunning) return; // íåëüçÿ îïðåäåëÿòü íàñòðîéêè âî âðåìÿ ðàáîòû
RobotUtils robot;
try {
robot = new RobotUtils();
BufferedImage detectImage = robot.getImage(-1, -1, -1, -1);
int boardSize = (Integer) boardSizeSpinner.getValue();
ImageUtils iu = new ImageUtils(detectImage, boardSize);
Point pt = iu.getBoardParameters();
int cellSize = iu.getCellSize();
windowXTextField.setText(String.valueOf(pt.x));
windowYTextField.setText(String.valueOf(pt.y));
cellSizeSpinner.setValue(cellSize);
} catch (AWTException ex) {
ex.printStackTrace();
}
}//GEN-LAST:event_detectButtonActionPerformed
/**
* Ïîêàçàòü ìîäàëüíîå îêíî ñ èçîáðàæåíèåì
* @param title çàãîëîâîê îêíà
* @param image èçîáðàæåíèå
* @throws SecurityException
*/
private void showImageWindow(String title, BufferedImage image) throws SecurityException {
ImageIcon icon = new ImageIcon(image);
JLabel backlabel = new JLabel(icon);
getLayeredPane().add(backlabel, new Integer(Integer.MIN_VALUE));
backlabel.setBounds(0, 0, icon.getIconWidth(), icon.getIconHeight());
JDialog dialog = new JDialog(this);
dialog.setAlwaysOnTop(true);
dialog.setLocationByPlatform(true);
dialog.setTitle(title);
dialog.setResizable(true);
dialog.add(backlabel);
dialog.pack();
dialog.setVisible(true);
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(RobotFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(RobotFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(RobotFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(RobotFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new RobotFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JSpinner boardSizeSpinner;
private javax.swing.JSpinner cellSizeSpinner;
private javax.swing.JButton checkButton;
private javax.swing.JButton detectButton;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JButton startStop;
private javax.swing.JPanel windowPanel;
private javax.swing.JTextField windowXTextField;
private javax.swing.JTextField windowYTextField;
// End of variables declaration//GEN-END:variables
}

78
main/RobotUtils.java Normal file
View File

@ -0,0 +1,78 @@
package main;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
/**
* Ðàáîòà ñ êëàññîì Robot.
* @author aNNiMON
*/
public class RobotUtils {
private static final int CLICK_DELAY = 300;
private Robot robot;
/**
* Êîíñòðóêòîð
* @throws AWTException îøèáêà èíèöèàëèçàöèè Robot
*/
public RobotUtils() throws AWTException {
robot = new Robot();
}
/**
* Êëèêíóòü â íóæíóþ òî÷êó
* @param click òî÷êà ïî êîòîðîé íóæíî êëèêíóòü
*/
public void clickPoint(Point click) {
robot.mouseMove(click.x, click.y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.delay(CLICK_DELAY);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
/**
* Àâòîìàòè÷åñêè âîñïðîèçâåñòè çàäàííóþ ïîñëåäîâàòåëüíîñòü íàæàòèé
* @param buttons êîîðäèíàòû òî÷åê, êóäà ñëåäóåò íàæèìàòü
* @param result ïîñëåäîâàòåëüíîñòü id äëÿ óêàçàíèÿ íà íóæíóþ êíîïêó
*/
public void autoClick(Point[] buttons, byte[] result) {
for (int i = 0; i < result.length; i++) {
clickPoint(buttons[result[i]]);
}
}
/**
* Àâòîìàòè÷åñêîå íàïèñàíèå ñîîáùåíèÿ
* @param text "ïå÷àòàåìûé" òåêñò
*/
public void writeMessage(String text) {
for (char symbol : text.toCharArray()) {
boolean needShiftPress = Character.isUpperCase(symbol) && Character.isLetter(symbol);
if(needShiftPress) {
robot.keyPress(KeyEvent.VK_SHIFT);
}
int event = KeyEvent.getExtendedKeyCodeForChar(symbol);
try {
robot.keyPress(event);
} catch (Exception e) {}
if(needShiftPress) {
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}
}
/*
* Ïîëó÷åíèå êàðòèíêè ðàçìåðîì [width x height] ñ ýêðàíà ñ ïîçèöèè [x, y]
* Åñëè width èëè height ðàâíû -1, òî âîçâðàùàåì âåñü ýêðàí.
*/
public BufferedImage getImage(int x, int y, int width, int height) {
Rectangle area;
if ((width == -1) || (height == -1)) {
area = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
} else area = new Rectangle(x, y, width, height);
return robot.createScreenCapture(area);
}
}