(如想转载,请联系博主或贴上本博地址)

仅供学习python之用,勿用做商业用途。运行环境为1920*1080屏幕,python3.7,win7,谷歌浏览器版本 75.0.3770.100。

参考https://www.cnblogs.com/reader/p/10111777.htmlhttps://baijiahao.baidu.com/s?id=1618385402903335091&wfr=spider&for=pc

感谢先辈提供的优秀思路。

连连看游戏链接:http://www.4399.com/flash/80972.htm#search3

下面直接贴上代码。

# -*- coding:utf-8 -*-

from win32 import win32gui
import time
from PIL import ImageGrab, Image
import numpy as np
import operator
from pymouse import PyMouse
import win32gui class GameAssist: def __init__(self, wdname):
"""初始化""" # 取得窗口句柄
self.hwnd = win32gui.FindWindow(0, wdname)
if not self.hwnd:
print("窗口找不到,请确认窗口句柄名称:【%s】" % wdname )
exit() # 窗口显示最前面
win32gui.SetForegroundWindow(self.hwnd) # 小图标编号矩阵
self.im2num_arr = [] # 主截图的左上角坐标和右下角坐标
self.scree_left_and_right_point = (577, 289, 1043, 599)
# 小图标宽高
self.im_width = 39 # PyMouse对象,鼠标点击
self.mouse = PyMouse() def screenshot(self):
"""屏幕截图""" # 1、用grab函数截图,参数为左上角和右下角左标
# image = ImageGrab.grab((417, 257, 885, 569))
image = ImageGrab.grab(self.scree_left_and_right_point)
# 2、分切小图
# exit()
image_list = {}
offset = self.im_width # 39 # 8行12列
for x in range(8):
image_list[x] = {}
for y in range(12):
# print("show",x, y)
# exit()
top = x * offset
left = y * offset
right = (y + 1) * offset
bottom = (x + 1) * offset # 用crop函数切割成小图标,参数为图标的左上角和右下角左边
im = image.crop((left, top, right, bottom))
# 将切割好的图标存入对应的位置
image_list[x][y] = im return image_list def image2num(self, image_list):
"""将图标矩阵转换成数字矩阵""" # 1、创建全零矩阵和空的一维数组
arr = np.zeros((10, 14), dtype=np.int32) # 以数字代替图片
image_type_list = [] # 2、识别出不同的图片,将图片矩阵转换成数字矩阵
for i in range(len(image_list)):
for j in range(len(image_list[0])):
im = image_list[i][j] # 验证当前图标是否已存入
index = self.getIndex(im, image_type_list) # 不存在image_type_list
if index < 0:
image_type_list.append(im)
arr[i + 1][j + 1] = len(image_type_list)
else:
arr[i + 1][j + 1] = index + 1 print("图标数:", len(image_type_list)) self.im2num_arr = arr
return arr # 检查数组中是否有图标,如果有则返回索引下表
def getIndex(self,im, im_list):
for i in range(len(im_list)):
if self.isMatch(im, im_list[i]):
return i return -1 # 汉明距离判断两个图标是否一样
def isMatch(self, im1, im2): # 缩小图标,转成灰度
image1 = im1.resize((20, 20), Image.ANTIALIAS).convert("L")
image2 = im2.resize((20, 20), Image.ANTIALIAS).convert("L") # 将灰度图标转成01串,即系二进制数据
pixels1 = list(image1.getdata())
pixels2 = list(image2.getdata()) avg1 = sum(pixels1) / len(pixels1)
avg2 = sum(pixels2) / len(pixels2)
hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pixels1))
hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pixels2)) # 统计两个01串不同数字的个数
match = sum(map(operator.ne, hash1, hash2)) # 原作者郭靖愕然阀值设为10,实测400位数字,50合适
return match < 50 # 判断矩阵是否全为0
def isAllZero(self, arr):
for i in range(1, 9):
for j in range(1, 13):
if arr[i][j] != 0:
return False
return True # 是否为同行或同列且可连
def isReachable(self, x1, y1, x2, y2):
# 1、先判断值是否相同
if self.im2num_arr[x1][y1] != self.im2num_arr[x2][y2]:
return False # 1、分别获取两个坐标同行或同列可连的坐标数组
list1 = self.getDirectConnectList(x1, y1)
list2 = self.getDirectConnectList(x2, y2)
# print(x1, y1, list1)
# print(x2, y2, list2) # exit() # 2、比较坐标数组中是否可连
for x1, y1 in list1:
for x2, y2 in list2:
if self.isDirectConnect(x1, y1, x2, y2):
return True
return False # 获取同行或同列可连的坐标数组
def getDirectConnectList(self, x, y): plist = []
for px in range(0, 10):
for py in range(0, 14):
# 获取同行或同列且为0的坐标
if self.im2num_arr[px][py] == 0 and self.isDirectConnect(x, y, px, py):
plist.append([px, py]) return plist # 是否为同行或同列且可连
def isDirectConnect(self, x1, y1, x2, y2):
# 1、位置完全相同
if x1 == x2 and y1 == y2:
return False # 2、行列都不同的
if x1 != x2 and y1 != y2:
return False # 3、同行
if x1 == x2 and self.isRowConnect(x1, y1, y2):
return True # 4、同列
if y1 == y2 and self.isColConnect(y1, x1, x2):
return True return False # 判断同行是否可连
def isRowConnect(self, x, y1, y2):
minY = min(y1, y2)
maxY = max(y1, y2) # 相邻直接可连
if maxY - minY == 1:
return True # 判断两个坐标之间是否全为0
for y0 in range(minY + 1, maxY):
if self.im2num_arr[x][y0] != 0:
return False
return True # 判断同列是否可连
def isColConnect(self, y, x1, x2):
minX = min(x1, x2)
maxX = max(x1, x2) # 相邻直接可连
if maxX - minX == 1:
return True # 判断两个坐标之间是否全为0
for x0 in range(minX + 1, maxX):
if self.im2num_arr[x0][y] != 0:
return False
return True # 点击事件并设置数组为0
def clickAndSetZero(self, x1, y1, x2, y2):
# print("click", x1, y1, x2, y2) # (299, 251, 768, 564)
# 原理:左上角图标中点 + 偏移量
p1_x = int(self.scree_left_and_right_point[0] + (y1 - 1)*self.im_width + (self.im_width / 2))
p1_y = int(self.scree_left_and_right_point[1] + (x1 - 1)*self.im_width + (self.im_width / 2)) p2_x = int(self.scree_left_and_right_point[0] + (y2 - 1)*self.im_width + (self.im_width / 2))
p2_y = int(self.scree_left_and_right_point[1] + (x2 - 1)*self.im_width + (self.im_width / 2)) time.sleep(0.1)
#原作者郭靖愕然用的click方法,实测click为双击,press单击
self.mouse.press(p1_x, p1_y)
time.sleep(0.1)
self.mouse.press(p2_x, p2_y) # 设置矩阵值为0
#while self.im2num_arr[x1][y1-1]!=0
#上面都是0没有图标,就置矩阵值为0 self.im2num_arr[x1][y1] = 0
self.im2num_arr[x2][y2] = 0 print("消除:(%d, %d) (%d, %d)" % (x1, y1, x2, y2))
# exit() # 程序入口、控制中心
def start(self): # 1、先截取游戏区域大图,然后分切每个小图
image_list = self.screenshot() # 2、识别小图标,收集编号
self.image2num(image_list) print(self.im2num_arr) # 3、遍历查找可以相连的坐标
while not self.isAllZero(self.im2num_arr):
for x1 in range(1, 9):
for y1 in range(1, 13):
if self.im2num_arr[x1][y1] == 0:
continue for x2 in range(1, 9):
for y2 in range(1, 13):
# 跳过为0 或者同一个
if self.im2num_arr[x2][y2] == 0 or (x1 == x2 and y1 == y2):
continue
if self.isReachable(x1, y1, x2, y2):
self.clickAndSetZero(x1, y1, x2, y2) if __name__ == "__main__":
# wdname 为连连看窗口的名称,必须写完整
wdname = '宠物连连看经典版2,宠物连连看经典版2小游戏,4399小游戏 www.4399.com - Google Chrome' demo = GameAssist(wdname)
demo.start()

python之自动化连连看脚本-第一关不动-小记的更多相关文章

  1. Appium+Python app自动化测试之脚本启动和停止Appium服务

    研究了一段时间的Appium android app的自动化测试,工作中需要连接多台手机终端同时执行测试用例,我实现的方式是获取用例中需要执行用例的设备id个数以及实际连接到的设备数(通过adb de ...

  2. [python]MS17-010自动化扫描脚本

    一种是3gstudent分享的调用Nsa泄露的smbtouch-1.1.1.exe实现验证,另一种是参考巡风的poc.这里整合学习了下两种不同的方法. import os import fileinp ...

  3. Appium + Python App自动化第一个脚本

    今天跟大家讲解一个Appium和Python App自动化的脚本.[1]打开你的夜神模拟器(或者连接你的手机) [2]打开桌面的Appium [3]下载你要测的App的apk文件,放到桌面[4]拖动你 ...

  4. python+paramiko库+svn写的自动化部署脚本

    第一篇博文 直接开门见山的说了. 这是件什么事?:每次部署都是复制本地的文件粘贴到服务器端,因为路径复杂,所以费时且手工容易出漏洞. 一直在想有什么办法可以解决这种,因为以前在微软的一个牛人同事做过一 ...

  5. 简单的抓取淘宝关键字信息、图片的Python爬虫|Python3中级玩家:淘宝天猫商品搜索爬虫自动化工具(第一篇)

    Python3中级玩家:淘宝天猫商品搜索爬虫自动化工具(第一篇) 淘宝改字段,Bugfix,查看https://github.com/hunterhug/taobaoscrapy.git 由于Gith ...

  6. python自动化执行脚本

    ---恢复内容开始--- 1 (1)首先在你的.py文件上加上一行代码注释: #!/usr/local/bin/python2.7 (2)终端下执行: crontab -e 进入后,输入i 进入可编辑 ...

  7. 《转载》Jenkins持续集成-自动化部署脚本的实现《python》

    本文转载自慕课网 读者须知:1.本手记本着记续接前面的两张手记内容整理2.本手记针对tomcat部署测试环境实现 最近工作比较繁忙,导致这章一直拖延,没有太抽出时间来总结.要实现Jenkins端的持续 ...

  8. Python 爬虫闯关(第一关)

    在学习爬虫时,遇到了一个有意思的网站,这个网站设置了几个关卡,需要经过爬虫进行闯关,随着关卡的网后,难度不断增加,在闯关的过程中需要学习不同的知识,你的爬虫水平也自然随之提高. 今天我们先来第一关,访 ...

  9. Python Challenge 第一关

    偶然在网上看到这个,PYTHON CHALLENGE,利用Python语言闯关,觉得挺有意思,就记录一下. 第0关应该算个入口吧,试了好几次才试出来,没什么代码就不写了.计算一个结果出来就行. 第一关 ...

  10. 【Linux】CentOS下升级Python和Pip版本全自动化py脚本

    [Linux]CentOS下升级Python和Pip版本全自动化py脚本 CentOS7.6自带py2.7和py3.6 想要安装其它版本的话就要自己重新下载和编译py其它版本并且配置环境,主要是软链接 ...

随机推荐

  1. maven工程运行环境修改 maven的java工程取mysql数据库数据

    maven工程运行环境修改  <plugins> <plugin> <!-- https://mvnrepository.com/artifact/org.apache. ...

  2. Unity 复杂Json 解析

    最近项目需要, 搞了一串嵌套非常多的Json 用LitJson读取体验不太好,上网查了一下发现NetwtonsoftJson ,十分好用 一句代码就可以了 JObject data = JsonCon ...

  3. 049_Search Lookup (二)

    其实就是 在父object中 设置,search setting 中选中 enhanced lookup, and select the dialoge & Filter  默认looukp搜 ...

  4. MFC编辑框字符显示时无法换行的问题解决

    字符串结尾加上"\r\n": 编辑框属性设置:Auto HScroll为False,Multiline为True,Want Return为True.

  5. 关于webdriver和谷歌浏览器的那些事

    早上看了一个视频,讲述爬虫的,首先一开始就写了一行这样代码(如下): from selenium import webdriver # 创建浏览器对象 ,这会在电脑中打开浏览器窗口browser = ...

  6. windows快捷键, 基本dos命令

    Ctrl+C 复制Ctrl+V 粘贴Ctrl+A 全选Ctrl+X 剪切Ctrl+S 保存Alt+F4 关闭窗口shift+delete 永久删除Window+R 打开运行cmd 打开命令行窗口Win ...

  7. bzoj 4176

    题意:求$\sum_{i=1}^{n}\sum_{j=1}^{n}d(ij)$ 首先推一发式子: $\sum_{i=1}^{n}\sum_{j=1}^{n}d(ij)$ 有一个结论:$d(nm)=\s ...

  8. new关键字的作用

    new关键字会进行如下的操作: 1. 创建一个空的简单JavaScript对象(即`{}`): 2. 为步骤1新创建的对象添加属性`__proto__`,将该属性链接至构造函数的原型对象 : 3. 将 ...

  9. SQL Server datetime类型为null的有趣实验

    @data1 --变量 测试用 @data2 --当前时间 当@data1为null 则格式转换错误 直接控制台什么也不显示 也不报错 当定义'' 显示默认时间

  10. Arrays.asList()的使用

    JDK文档说明: @SafeVarargs public static <T> List<T> asList(T... a) 返回由指定数组支持的固定大小的列表(将返回的列表更 ...