JAVA 打豆豆辅助工具

来源:互联网 发布:郎咸平 离婚 知乎 编辑:程序博客网 时间:2024/04/30 15:20

分析、开发、测试过程:

 

(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 windowDoGetScreenSize();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 gameboolean  DoAnalysis(){int i,j,k;this.m_class_num=0;// getColorCategoryfor(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 clickedboolean 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 clickvoid 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 mevoid DoProc(){int n=15*20,i=0,j=0;int flag=0;int fre=this.m_frequence.getValue();//loopwhile(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 pj+=1;if(j==23){i+=1;j=0;if(i==15){i=0;}}}//output left mapfor(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 capturedclass 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 TitlesetUndecorated(true);//FullScreen GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();GraphicsDevice gd = ge.getDefaultScreenDevice();if(gd.isFullScreenSupported())gd.setFullScreenWindow(this);elseSystem.out.println("Unsupported full screen.");//Set Cursorthis.setCursor(Cursor.CROSSHAIR_CURSOR);//Add listenerthis.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();}}













原创粉丝点击