Added sources
This commit is contained in:
commit
59fdc4a3c0
197
main/BotFloodIt.java
Normal file
197
main/BotFloodIt.java
Normal 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
369
main/ImageUtils.java
Normal 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
222
main/RobotFrame.form
Normal 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
362
main/RobotFrame.java
Normal 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
78
main/RobotUtils.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user