您的位置:首页 > 编程语言 > Java开发

JAVA 打豆豆辅助工具

2012-01-27 23:10 190 查看
分析、开发、测试过程:

(1) 分析:
想到了先截屏,然后根据每个点的颜色把 地图地区出来,形成一个数字矩阵,然后逐个枚举,判断。由于不同的消除顺序会产生不同的结果,可能导致死局。不过目前没想出在相对较短时间内得到完美解法的算法。不过一般190+的分数还是很容易的。
(2) 开发过程:
查找需要的功能实现方法:
1. java获取屏幕上特定位置的图片
2. 获得屏幕的尺寸
3. Java模拟鼠标点击
4. 全屏幕模式
5. 改变鼠标形状
6. Jar打包

(3) 功能及使用方法:
1. 打开本软件以及打豆豆游戏页面
2. 点击自动设定或者手动设定确定游戏区域。要保证游戏区域完整的显示在屏幕上。手动设定的时候要点击游戏区域线框的左上角。
3. 设定点击频率,默认为300ms。过快可能会导致无效点击,影响结果。
4. 点击开始按钮。会弹出游戏区域截图,如果范围正确覆盖了游戏区域,点击确定开始游戏,否则取消重新选择区域。一般情况下,如果游戏区域不正确,点击确定后会自动识别出无效的游戏区域。(由于正确的游戏区域只会出现10种豆豆颜色,不正确的一般多于10种,所以会识别出不正确的区域)
5. 标识下的数字表示时间间隔(单位ms),并不是真正的频率。

(4) 测试:
发现点击间隔过低可能导致“误点”错误。特增加人为设定点击间隔。50—1000ms可供选择。
(5) 未解决问题:
1.由于不太清楚给定状态的生成过程,感觉并不能保证一定有完美解。而且状态量巨大,局部最优不能保证全局最优,故难以在多项式时间下求出最优解。没有想出可行的最优解算法。
2.由于java调用系统API比较困难,故没有实现中途退出的功能,故只能等游戏技术才能使用鼠标。因此建议时间间隔不要太高

功能实现:

(1) 信息的获取

1. 区域定位

区域定位一开始是使用了手动定位的方法。由于java调用API需要JNI据说,貌似很麻烦的样子,所以结果鼠标消息不太容易实现。于是我想到让鼠标消息被自己的窗口所接受。于是我先用截图函数对整个屏幕截图,然后用一个全屏的窗口显示这个图像,并且置鼠标形状为十字形。当用户点击对应位置的时候可以获得鼠标的坐标,作为区域的参考坐标。

后来发现每次都要手动设定位置十分的麻烦,于是写了一个自动获取坐标的。一开始想利用游戏区域的规则性智能搜索。然后突然发现游戏的外面有一个淡淡的灰色边框,于是直接获得这个灰色边框的位置就能确定游戏区域了。

2. 游戏数据获取

经过测量发现每个豆豆的偏移量为25像素,而且同样颜色的豆豆的绘制是完全一样的,所以只要每次偏移25像素取色,对每次取到的颜色进行编号,如果之前已经取过则直接编号为已有的,否则新编号。这样即使定位有偏差,因为是动态确定颜色的编号的,所以不影响数据获取。因为很多情况下,桌面的颜色是很杂乱的,所以如果游戏区域定位不正确的话,绝大多数情况会导致最后分析豆豆的时候获取不止10种颜色。如果发现取色不止10种,就不会进行下面的分析与处理了。

(2) 处理过程

1.将豆豆的颜色值离散化并存贮到二维的Map数组中,然后从左上角开始循环遍历每个点,如果发现四个方向有且有一对或两对颜色相同的豆豆,则模拟鼠标点击该坐标。如果发现3个豆豆颜色相同,根据贴吧众吧友的经验,跳过,可能会导致较好的结果。

总结:

1. 熟悉了java GUI程序设计的方法

2. 一开始不知道内部匿名类可以直接访问外部的成员变量。一直用getsouce来获得引用。后来发现自己一直直接调用成员方法。。然后知道了内部匿名类的特性。

3. 利用传递父窗口引用给子窗口的方式可以解决从 子窗口操作父窗口的功能。

4. 一个窗口在dispose之前依然是存在的。

5. Java的整数类型不能直接转换到boolean类型

6. 不要把代码随意的给别人,否则他可能会修改修改发到自己的blog上去,比如sina Blog啥的。。T.T

使用说明:

1. 在”开始”之前,应先定位,即点击”手动位置”,鼠标变成 十字 形状,在游戏flash的左上角,下图红色标记位置点击,确定位置。或者直接使用自动设定。

代码:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.System;
import java.lang.*;
import java.util.Timer;

class MainFrame extends JFrame
{
//成员变量
WindowForGetRect m_windowForGetRect;
JButton m_btn_start,m_btn_setpos,m_btn_auto_set;
JLabel m_Label;
JSlider m_frequence;
//Image m_Screen;
BufferedImage m_image;
int m_Map[][] = new int[15][23],m_px,m_py,m_screenH,m_screenW;
int m_StdColor[] =new int[10],m_class_num;
boolean m_Running=true;
boolean m_HaveSet;
//构造函数
MainFrame()
{
super("打豆豆辅助工具");

m_HaveSet=false;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setAlwaysOnTop(true);
setSize(180+100,125);
Container c = getContentPane();
c.setLayout(new FlowLayout(FlowLayout.LEFT));

this.m_btn_start = new JButton("开始");
this.m_btn_auto_set = new JButton("自动设定");
this.m_btn_setpos =new JButton("手动设定");
this.m_Label = new JLabel("设定频率");
this.m_frequence = new JSlider(50,1000,300);
//this.m_frequence.createStandardLabels(250);
this.m_frequence.setPaintLabels(true);
this.m_frequence.setMinorTickSpacing (50);
this.m_frequence.setMajorTickSpacing (200);
this.m_frequence.setPaintTicks (true);
this.m_frequence.putClientProperty("JSlider.isFilled",Boolean.TRUE);
//this.m_frequence.setExtent(400);
//
c.add(this.m_btn_start);
c.add(this.m_btn_auto_set);
c.add(this.m_btn_setpos);
c.add(this.m_Label);
c.add(this.m_frequence);
//c.add(this.m_Label);

//this.setCursor(Cursor.CROSSHAIR_CURSOR);
this.addKeyListener
(
new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ESCAPE)
{
m_Running=false;
}
}
}
);
this.m_btn_start.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
DoStart();
}
}
);
this.m_btn_auto_set.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(DoAutoSet())
{
JOptionPane.showMessageDialog(null,"自动获取成功","注意",JOptionPane.INFORMATION_MESSAGE);

}else
{
JOptionPane.showMessageDialog(null,"自动获取失败","注意",JOptionPane.ERROR_MESSAGE);
}
}
}
);
this.m_btn_setpos.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{

DoSetPos();
}
}
);

//set position of window
DoGetScreenSize();
this.setLocation(this.m_screenW/2-90,this.m_screenH/2-140);

setVisible(true);
}

void DoGetScreenSize()
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension screenSize=tk.getScreenSize();
this.m_screenH = (int)screenSize.getHeight();
this.m_screenW = (int)screenSize.getWidth();
}

boolean DoAutoSet()
{
int StdW=583;
int StdH=466;
int i,j;

Robot robot;
try
{
robot = new Robot();
BufferedImage image = robot.createScreenCapture(new Rectangle(0, 0,this.m_screenW,this.m_screenH));
for(i=0;i<=this.m_screenW-StdW;++i)
{
for(j=0;j<=this.m_screenH-StdH;++j)
{
if(image.getRGB(i,j)==-1973791 && image.getRGB(i+583,j)==-1973791 && image.getRGB(i,j+465)==-1973791 && image.getRGB(i+583,j+465)==-1973791)
{
this.m_px = i;
this.m_py = j+6;
return true;
}
}
}
return false;
}
catch(AWTException e)
{
return false;
}

}
//功能函数
void DoSetPos()
{

Robot robot;
try
{
robot = new Robot();
BufferedImage image = robot.createScreenCapture(new Rectangle(0, 0,this.m_screenW,this.m_screenH));
//JOptionPane.showMessageDialog(null,"11","d",JOptionPane.ERROR_MESSAGE,new ImageIcon(image));
this.m_windowForGetRect = new WindowForGetRect(this,image);
}
catch(AWTException e)
{
}
}

void DoStart()
{
DoGetImg();
//JOptionPane.showMessageDialog(null,"","d",JOptionPane.ERROR_MESSAGE,new ImageIcon(this.m_image));
if(JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this,"捕获是否合适?","捕获效果",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,new ImageIcon(this.m_image)))
{
if(DoAnalysis())
{
m_Running=true;
DoProc();
}else
{
int i,j;
for(i=0;i<15;i++)
{
for(j=0;j<23;j++)
{
System.out.printf("%d ",this.m_Map[i][j]);
}
System.out.printf("\n");
}
}

}

}
void DoGetImg()
{
Robot robot;
try
{
robot = new Robot();
this.m_image = robot.createScreenCapture(new Rectangle(this.m_px+3,this.m_py+40,575,375));
}
catch(AWTException e)
{
}
}

// get the map of game
boolean  DoAnalysis()
{
int i,j,k;
this.m_class_num=0;
// getColorCategory
for(i=0;i<15;i++)
{
for(j=0;j<23;j++)
{
//System.out.printf("<%d,%d>\n",j*25+13,i*25+13);
int color = this.m_image.getRGB(j*25+13,i*25+13);

//System.out.printf("<%d,%d>=%d\n",i,j,color);

if(color==0xffffffff || color==-1184275)
{
this.m_Map[i][j] = -1;
continue;
}
for(k=0;k<this.m_class_num;++k)
{
if(equal(this.m_StdColor[k],color))
{
this.m_Map[i][j] = k;
break;
}
}
if(k==this.m_class_num)
{
this.m_Map[i][j] = k;
this.m_StdColor[this.m_class_num++]=color;
if(this.m_class_num>10)
return false;
}
}
}
for(i=0;i<15;i++)
{
for(j=0;j<23;j++)
{
System.out.printf("%d ",this.m_Map[i][j]);
}
System.out.printf("\n");
}
return true;
}
// test color
boolean equal(int ca,int cb)
{
return ca==cb;
}

// test whether this point can be clicked
boolean can(int i,int j)
{
int a=i,b=i,c=j,d=j;
int c1,c2,c3,c4,t;
int s[] = new int [10];

while(this.m_Map[a][j]==-1 ) { if(a==0) break; --a;}
while(this.m_Map[b][j]==-1 ) { if(b==14) break;++b;}
while(this.m_Map[i][c]==-1 ) { if(c==0) break; --c;}
while(this.m_Map[i][d]==-1 ) { if(d==22) break;++d;}

c1=this.m_Map[a][j];
c2=this.m_Map[b][j];
c3=this.m_Map[i][c];
c4=this.m_Map[i][d];

if(c1>=0) s[c1]++;
if(c2>=0) s[c2]++;
if(c3>=0) s[c3]++;
if(c4>=0) s[c4]++;

for(t=0;t<10;++t)
{
if(s[t]==2)
{
if(c1==c2)
{
this.m_Map[a][j]=-1;
this.m_Map[b][j]=-1;
}
if(c1==c3)
{
this.m_Map[a][j]=-1;
this.m_Map[i][c]=-1;
}
if(c1==c4)
{
this.m_Map[a][j]=-1;
this.m_Map[i][d]=-1;
}
if(c2==c3)
{
this.m_Map[b][j]=-1;
this.m_Map[i][c]=-1;
}
if(c2==c4)
{
this.m_Map[b][j]=-1;
this.m_Map[i][d]=-1;
}
if(c3==c4)
{
this.m_Map[i][c]=-1;
this.m_Map[i][d]=-1;
}
return true;
}
if(s[t]==4)
{
this.m_Map[a][j]=-1;
this.m_Map[b][j]=-1;
this.m_Map[i][c]=-1;
this.m_Map[i][d]=-1;
return true;
}

}

return false;
}
// perform mouse click
void PerformClick(int i,int j)
{
Robot robot;
try
{
robot = new Robot();
robot.mouseMove(this.m_px+j*25+15,this.m_py+i*25+53);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
catch(AWTException e)
{
}
//System.out.println("0");
}
//play game for me
void DoProc()
{
int n=15*20,i=0,j=0;
int flag=0;
int fre=this.m_frequence.getValue();
//loop
while(m_Running)
{
flag++;
if(flag>23*15) break;

if(this.m_Map[i][j]==-1)
{
if(can(i,j))
{
flag=0;
n--;
PerformClick(i,j);
this.requestFocus(true);
try
{
Thread.sleep(fre);
}
catch(InterruptedException e)
{
}
}
}
// next p
j+=1;
if(j==23)
{
i+=1;
j=0;
if(i==15)
{
i=0;
}
}
}
//output left map
for(i=0;i<15;i++)
{
for(j=0;j<23;j++)
{
System.out.printf("%d ",this.m_Map[i][j]);
}
System.out.printf("\n");
}
}

}

// window for get Rect to be Captured,Capture a ScreenShoot ,show it in the window
//user can set the position to be captured
class WindowForGetRect extends JFrame
{
JLabel m_label;
BufferedImage m_bf_img;
MainFrame m_owner;

WindowForGetRect(MainFrame own,BufferedImage img)
{
m_owner = own;
m_bf_img =img;
Container c = getContentPane();
this.m_label = new JLabel(new ImageIcon(img));
c.add(this.m_label);

//Hide Window's Title
setUndecorated(true);

//FullScreen
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
if(gd.isFullScreenSupported())
gd.setFullScreenWindow(this);
else
System.out.println("Unsupported full screen.");

//Set Cursor
this.setCursor(Cursor.CROSSHAIR_CURSOR);

//Add listener
this.addKeyListener
(
new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ESCAPE)
{
((WindowForGetRect)e.getSource()).dispose();
}
}
}
);

this.addMouseListener
(
new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
//BufferedImage iimg= new BufferedImage(((WindowForGetRect)e.getSource()).img);
//
((WindowForGetRect)e.getSource()).m_owner.m_px = e.getX();
((WindowForGetRect)e.getSource()).m_owner.m_py = e.getY();
((WindowForGetRect)e.getSource()).dispose();
//JOptionPane.showMessageDialog(null,""+((WindowForGetRect)e.getSource()).m_bf_img.getRGB(e.getX(),e.getY()),"注意",JOptionPane.ERROR_MESSAGE);
}
}
);
}
}

public class Main
{
public static void main(String args[])
{
MainFrame m_mainFrame = new MainFrame();
}
}






内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: