连连看游戏辅助工具python版的实现

时间:2021-08-05 23:21:21

最近自学python, 想起以前用C++在VS上实现的连连看辅助工具, 决定拿此来练手. 


首先需要下载并安装python的相关插件:Pywin32(操作windows窗口), Pyqt(设计gui), py2exe(将python转成exe), 并假定已经有spy(研究窗口标题与类). 


    首先要查找到连连看的窗口,  打开连连看游戏, 然后再打开SPY查看相关窗口标题, 类名, 如下图:


   连连看游戏辅助工具python版的实现

   连连看游戏辅助工具python版的实现

可以看到此窗口的标题是"QQ游戏 - 连连看角色版", 并继续查看spy可以看到, 此标题唯一, 故可以以此来查找相关窗口,  网上搜索一下, 发现win32gui等类是比较推荐的操作窗口内的扩展包, 故下载安装Pywin32包, 然后相关操作如下:


import win32gui, win32con, win32api, win32ui


def find_llk_hwnd_DC(self):
hwnd=win32gui.FindWindow(None,"QQ游戏 - 连连看角色版")
if not hwnd:
return [None, None]
else:
print(hwnd)
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
win32gui.SetForegroundWindow(hwnd)
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC=win32ui.CreateDCFromHandle(hwndDC)
llkDC=mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
MoniterDev=win32api.EnumDisplayMonitors(hwndDC,None)
w = MoniterDev[0][2][2]
h = MoniterDev[0][2][3]
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
llkDC.SelectObject(saveBitMap)
llkDC.BitBlt((0,0),(w, h) , mfcDC, (0,0), win32con.SRCCOPY)
return [hwnd, llkDC]


至此, 就拿到了相关的句柄与HDC, 能够执行显示和获取图像数据的操作了. 


将QQ连连看游戏窗口截屏, 然后在VS中打开, 研究一下模块的分布, 发现其水平方向有19列, 竖直方向有11行, 每个小方块有31x35个像素, 起始坐标在(14, 181)处,  此时根据前面代码的HDC, 就已经能够完全统计出每个模块的像素值之和. 然后其空白方块处的图像与其背景色一致, 故取左下角某处采集出背景色像素, 计算出空白方块处的像素值, 与前面的统计信息作比较, 发现吻合. 至此已经完成了对窗口数据的采样, 接着就是对能消去的相同模块的查找了. 


采用了递归调用, 相关代码如下:

def FindSameBlock(self,cur_pos, blockPixSum, search_dir, cur_step, cur_block_value, emptyBlockSumValue):
x,y=cur_pos
#print(cur_pos)
xNum=len(blockPixSum)
yNum=len(blockPixSum[0])
if(search_dir==[]): #all dir are try out and still not able to find a connectable block
return [];
cur_dir=search_dir.pop(0)
if(cur_dir == 0): #right_dir
for i in range(x+1,xNum):
if(blockPixSum[i][y] == cur_block_value):
return [i,y] #find the connectable block, [i,y] is the pos
elif(blockPixSum[i][y] == emptyBlockSumValue ):
if(cur_step<2): #there is more steps left
nextResult=self.FindSameBlock([i,y], blockPixSum, [1,3], cur_step+1, cur_block_value, emptyBlockSumValue) #change to next step, and next dir
if(nextResult!=[]):
return nextResult
else:
break
elif(cur_dir==1): #down_dir
for j in range(y+1,yNum):
if(blockPixSum[x][j] == cur_block_value):
return [x,j] #find the connectable block
elif(blockPixSum[x][j] == emptyBlockSumValue ):
if(cur_step<2): #there is more steps left
nextResult=self.FindSameBlock([x,j], blockPixSum, [0,2], cur_step+1, cur_block_value, emptyBlockSumValue) #change to next step, and next dir
if(nextResult!=[]):
return nextResult
else:
break
elif(cur_dir==2): #left_dir
for i in range(x-1,-1,-1):
if(blockPixSum[i][y] == cur_block_value):
return [i,y] #find the connectable block
elif(blockPixSum[i][y] == emptyBlockSumValue ):
if(cur_step<2): #there is more steps left
nextResult=self.FindSameBlock([i,y], blockPixSum, [1,3], cur_step+1, cur_block_value, emptyBlockSumValue) #change to next step, and next dir
if(nextResult!=[]):
return nextResult
else:
break
elif(cur_dir==3): #up_dir
for j in range(y-1,-1,-1):
if(blockPixSum[x][j] == cur_block_value):
return [x,j] #find the connectable block
elif(blockPixSum[x][j] == emptyBlockSumValue ):
if(cur_step<2): #there is more steps left
nextResult=self.FindSameBlock([x,j], blockPixSum, [0,2], cur_step+1, cur_block_value, emptyBlockSumValue) #change to next step, and next dir
if(nextResult!=[]):
return nextResult
else:
break
if(cur_step<3): #there is more steps left, and if code goes here, means that cur_dir is try out and so change to other dir and with the same step num
return self.FindSameBlock([x,y], blockPixSum, search_dir, cur_step, cur_block_value, emptyBlockSumValue) #change to dirtions that left
else:
return []


其调用方式为findSame=FindSameBlock(pos, blockPixSum, [0,1,2,3], 0, cur_block_value, emptyBlockSumValue), 其中pos为当前位置, blockPixSum为包含像素点之和的信息矩阵, [0, 1,2,3] 表示将向四个方向寻找, 0表示当前为第一步, cur_block_value表示当前要查找的方块值, emptyBlockSumValue为空白方块值. 


此时核心的东西已经搞定, 剩下的就是利用PyQt设计一些ui, 然后再利用win32api实现模拟鼠标点击, 比较简单. 最终效果如下


连连看游戏辅助工具python版的实现


完整代码已经上传到我的资源里.