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的左上角,下图红色标记位置点击,确定位置。或者直接使用自动设定。
代码:
(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(); } }
相关文章推荐
- Java监控工具、调优、调试辅助函数
- Anntation(注解)-----Java之辅助工具(大有前途)
- 八字易经算法之用JAVA实现硬币卜卦辅助工具
- Java监控工具、调优、调试辅助函数
- Java扩展算法和辅助工具
- 开源java开发的可视化打增量包、发http请求、生成ibatis辅助工具20170628更新
- Java监控工具、调优、调试辅助函数
- Java环境变量设置辅助工具
- java开发的可视化打增量包、发http请求、生成ibatis辅助工具20160603更新
- SQLite-Java-Hibernate类似hibernate的数据库辅助工具
- [置顶] 跳一跳辅助工具的原理分析,和Java实现。(其实没那么复杂)
- Java监控工具、调优、调试辅助函数
- Java开发工具_Eclipse中内容辅助键的使用
- java动态数组、集合类、以及数组辅助工具的简单使用
- 微信跳一跳高分系列四:一个 JAVA 版开源的微信跳一跳辅助工具
- 在Java中辅助报表工具展现json
- java开发工具之myeclipse调优
- Java常用公共工具记录
- Java单元测试工具:JUnit4(四)——JUnit测试套件使用及参数化设置
- JAVA图片压缩工具