利用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;
}