欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

利用vs 2019和easyx图形库完成QQ游戏连连看的脚本

程序员文章站 2022-06-25 21:46:02
...

利用vs 2019和easyx图形库完成QQ游戏连连看的脚本

需要的工具:

win 10
vs 2019
easyx

#include <stdio.h>
#include <easyx.h>

#define ROW 11
#define COL 19

HWND qqHwnd = NULL;
IMAGE image(800, 600);
HDC qqHdc, imgHdc;
IMAGE img[ROW][COL];
RECT rect;

void ClearImage(IMAGE* pimg)
{
	SetWorkingImage(pimg);
	setbkcolor(RGB(48, 76, 112));
	cleardevice();
	SetWorkingImage(NULL);
}
bool IsSimilar(IMAGE* pimg1, IMAGE* pimg2)
{
	//10 10
	SetWorkingImage(pimg1);
	COLORREF color11 = getpixel(3, 3);
	COLORREF color12 = getpixel(3, 6);
	COLORREF color13 = getpixel(6, 3);
	COLORREF color14 = getpixel(6, 6);
	COLORREF color15 = getpixel(5, 5);
	SetWorkingImage(pimg2);
	COLORREF color21 = getpixel(3, 3);
	COLORREF color22 = getpixel(3, 6);
	COLORREF color23 = getpixel(6, 3);
	COLORREF color24 = getpixel(6, 6);
	COLORREF color25 = getpixel(5, 5);

	if (color11 == color21 && color12 == color22 && color13 == color23 && color14 == color24 && color15 == color25)
		return true;
	else
		return false;
}
bool IsBlank(IMAGE* pimg)
{
	SetWorkingImage(pimg);
	COLORREF color11 = getpixel(2, 2);
	COLORREF color12 = getpixel(2, 7);
	COLORREF color13 = getpixel(7, 2);
	COLORREF color14 = getpixel(7, 7);
	COLORREF color15 = getpixel(5, 5);

	if (color11 == RGB(48, 76, 112) &&
		color12 == RGB(48, 76, 112) &&
		color13 == RGB(48, 76, 112) &&
		color14 == RGB(48, 76, 112) &&
		color15 == RGB(48, 76, 112))
		return true;
	else
		return false;
}
void GameInit()
{
	//初始化image对象
	qqHwnd = FindWindowA(NULL, "QQ游戏 - 连连看角色版"); //获取连连看窗口句柄
	if (qqHwnd == NULL)
	{
		printf("没有找到游戏窗口\n");
		system("pause");
		exit(0);
	}
	qqHdc = GetDC(qqHwnd);			//获取游戏窗口绘图句柄
	imgHdc = GetImageHDC(&image);	//获取image绘图句柄
	BitBlt(imgHdc, 0, 0, 800, 600, qqHdc, 0, 0, SRCCOPY);  //调用winapi将窗口图像绘制到image中

	SetWorkingImage(&image);  //设置image位当前工作对象
	setorigin(15, 182);		  //设置坐标原点
	for (int i = 0; i < ROW; i++)  //切割图像
		for (int j = 0; j < COL; j++)
			getimage(&img[i][j], j * 31 + 10, i * 35 + 10, 10, 10);  //缩小范围
	SetWorkingImage(NULL);
}
bool IsExist()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (!IsBlank(&img[i][j]))
				return true;
		}
	}
	return false;
}
bool HorizConnect(int row1, int col1, int row2, int col2) {
	if (row1 != row2) {  //如果r1 != r2 
		return false;  //不连通
	}

	int maxCol = col1 > col2 ? col1 : col2;  //最大的列
	int minCol = col1 > col2 ? col2 : col1;  //最小的列

	if (maxCol - minCol == 1) { //两图块相邻
		return true;  //连通
	}

	for (int i = minCol + 1; i < maxCol; i++) {
		if (!IsBlank(&img[row1][i])) {
			return false;
		}
	}

	return true;
}
bool VerticConnect(int row1, int col1, int row2, int col2) {
	if (col1 != col2) {
		return false;
	}

	int maxRow = row1 > row2 ? row1 : row2;
	int minRow = row1 > row2 ? row2 : row1;

	if (maxRow - minRow == 1) { //两图块相邻
		return true;
	}

	for (int i = minRow + 1; i < maxRow; i++) {
		// 水平方向遇到一个非空节点,就认为水平连接失败
		if (!IsBlank(&img[i][col1])) {
			return false;
		}
	}

	return true;
}
bool OneTurnConnect(int row1, int col1, int row2, int col2) {
	if (row1 == row2 || col1 == col2) {
		return false;  //不能在同一水平线,或同一垂直线上
	}

	// 第1个拐点
	int turnRow1 = row1;
	int turnCol1 = col2;
	// 第2个拐点
	int turnRow2 = row2;
	int turnCol2 = col1;

	if (IsBlank(&img[turnRow1][turnCol1]) && //第1个拐点是空节点
		HorizConnect(row1, col1, turnRow1, turnCol1) &&
		VerticConnect(turnRow1, turnCol1, row2, col2)) {
		return true;
	}

	if (IsBlank(&img[turnRow2][turnCol2]) && //第2个拐点是空节点
		VerticConnect(row1, col1, turnRow2, turnCol2) &&
		HorizConnect(turnRow2, turnCol2, row2, col2)) {
		return true;
	}

	return false;
}
bool TwoTurnConnect(int row1, int col1, int row2, int col2) {
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COL; j++) {
			if (!IsBlank(&img[i][j])) { // 寻找空节点
				continue;
			}

			// 双折拐点必须和起点(或终点)同一行(或同一列),
			// 否则不能作为双折拐点
			if (i != row1 && i != row2 && j != col1 && j != col2) {
				continue;
			}

			if (OneTurnConnect(row1, col1, i, j) &&
				(HorizConnect(i, j, row2, col2) ||
					VerticConnect(i, j, row2, col2))) {
				return true;
			}

			if (OneTurnConnect(i, j, row2, col2) &&
				(HorizConnect(row1, col1, i, j) ||
					VerticConnect(row1, col1, i, j))) {
				return true;
			}
		}
	}

	return false;
}
bool CheckConnect(int row1, int col1, int row2, int col2) {
	// 1. 起点和终点都不能是空白点
	if (IsBlank(&img[row1][col1]) ||
		IsBlank(&img[row2][col2]) ||
		// 2. 起点和终点不能是同一个点
		row1 == row2 && col1 == col2 ||
		// 3. 起点和终点必须是相同的图块
		!IsSimilar(&img[row1][col1], &img[row2][col2])) {
		return false;
	}

	if (HorizConnect(row1, col1, row2, col2) ||  // Redmi
		VerticConnect(row1, col1, row2, col2) ||
		OneTurnConnect(row1, col1, row2, col2) ||
		TwoTurnConnect(row1, col1, row2, col2)) {
		return true;
	}

	return false;
}
void Match()
{
	//找第一个点 起点/终点
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (IsBlank(&img[i][j]))  //不管  0空的
				continue;//找下一个

			//找下一个
			for (int m = i; m < ROW; m++)
			{
				for (int n = 0; n < COL; n++)
				{
					if (IsSimilar(&img[i][j], &img[m][n])) //找到2个一样
					{
						if (CheckConnect(i, j, m, n))  //判断是否连通
						{
							//鼠标移动到起点上。
							SetCursorPos((rect.left + 15 + j * 31) + 10, (rect.top + 182 + i * 35) + 10);

							//鼠标点击一下起点。
							mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

							//Sleep(20);

							//鼠标设置到终点。
							SetCursorPos((rect.left + 15 + n * 31) + 10, (rect.top + 182 + m * 35) + 10);
							//鼠标点击一下终点。
							mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
							ClearImage(&img[i][j]);
							ClearImage(&img[m][n]);
							//Sleep(20);
						}
					}
				}
			}
		}
	}
}
int main()
{
	GameInit();

	GetWindowRect(qqHwnd, &rect);
	SetForegroundWindow(qqHwnd);
	Sleep(1000);
	while (IsExist())
		Match();

	return 0;
}
相关标签: 游戏 c++