分析、开发、测试过程:

 


(1)      分析:

想到了先截屏,然后根据每个点的颜色把 地图地区出来,形成一个数字矩阵,然后逐个枚举,判断。由于不同的消除顺序会产生不同的结果,可能导致死局。不过目前没想出在相对较短时间内得到完美解法的算法。不过一般190+的分数还是很容易的。

(2)      开发过程:

查找需要的功能实现方法:

1.       java获取屏幕上特定位置的图片

2.       获得屏幕的尺寸

3.       Java模拟鼠标点击

4.       全屏幕模式

5.       改变鼠标形状

6.       Jar打包

(3)      功能及使用方法:

1.       打开本软件以及打豆豆游戏页面

java image提高分辨率 java游戏改分辨率工具_java

2.       点击自动设定或者手动设定确定游戏区域。要保证游戏区域完整的显示在屏幕上。手动设定的时候要点击游戏区域线框的左上角。

java image提高分辨率 java游戏改分辨率工具_import_02

3.       设定点击频率,默认为300ms。过快可能会导致无效点击,影响结果。

4.       点击开始按钮。会弹出游戏区域截图,如果范围正确覆盖了游戏区域,点击确定开始游戏,否则取消重新选择区域。一般情况下,如果游戏区域不正确,点击确定后会自动识别出无效的游戏区域。(由于正确的游戏区域只会出现10种豆豆颜色,不正确的一般多于10种,所以会识别出不正确的区域)

java image提高分辨率 java游戏改分辨率工具_image_03

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类型 

使用说明:

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();
	}
}