当前位置: 首页 > 科技观察

使用Python实现自动扫雷小脚本

时间:2023-03-13 06:23:23 科技观察

自动扫雷一般有两种,一种是读取内存数据,另一种是通过分析图片和模拟鼠标操作来获取数据。这里我使用第二种方法。一、准备工作1、扫雷游戏我是win10,没有默认扫雷,所以去扫雷下载http://www.saolei.net/BBS/2.python3我的版本是python3.6.13.python的三方库win32api、win32gui、win32con、Pillow、numpy、opencv可以通过pipinstall--upgradeSomePackage安装注:部分版本下载pywin32,但部分需要将pywin32升级到最高级别自动下载pypiwin32,具体情况每个python版本可能略有不同。我给出的第三方库和版本仅供参考。二、关键代码组成1、找到游戏窗口和坐标#MinesweeperGameWindowclass_name="TMain"title_name="MinesweeperArbiter"hwnd=win32gui.FindWindow(class_name,title_name)#windowcoordinateleft=0top=0right=0bottom=0ifhwnd:print("查找窗口")left,top,right,bottom=win32gui.GetWindowRect(hwnd)#win32gui.SetForegroundWindow(hwnd)print("窗口坐标:")print(str(left)+''+str(right)+''+str(top)+''+str(bottom))else:print("Windownotfound")2.锁定捕捉雷区图片#锁定雷区坐标#去除周边功能按钮和多余界面#具体像素值由QQ截图判断left+=15top+=101right-=15bottom-=42#捕捉雷区图片rect=(left,top,right,bottom)img=ImageGrab.grab().crop(rect)3.每张图片的RGBA值#编号1-8周围的雷编号#0未打开#ed打开空白#hongqiredflag#boomCommonthunder#boom_redThethunderrgb踩到a_ed=[(225,(192,192,192)),(31,(128,128,128))]rgba_hongqi=[(54,(255,255,255)),(17,(255,0,0)),(109,(192,192,192)),(54,(128,128,128)),(22,(0,0,0))]rgba_0=[(54,(255,255,255)),(148,(192,192,192)),(54,(128,128,128))]rgba_1=[(185,(192,192,192)),(31,(128,128,128)),(40,(0,0,255))]rgba_2=[(160,(192,192,192)),(31,(128,128,128)),(65,(0,128,0))]rgba_3=[(62,(255,0,0)),(163,(192,192,192)),(31,(128,128,128))]rgba_4=[(169,(192,192,192)),(31,(128,128,128)),(56,(0,0,128))]rgba_5=[(70,(128,0,0)),(155,(192,192,192)),(31,(128,128,128))]rgba_6=[(153,(192,192,192)),(31,(128,128,128)),(72,(0,128,128))]rgba_8=[(149,(192,192,192)),(107,(128,128,128))]rgba_boom=[(4,(255,255,255))),(144,(192,192,192)),(31,(128,128,128)),(77,(0,0,0))]rgba_boom_red=[(4,(255,255,255)),(144,(255,0,0)),(31,(128,128,128)),(77,(0,0,0))]4.将扫描的雷区图片保存到二维数组map#扫描雷区图片defshowmap():img=ImageGrab.grab().crop(rect)foryinrange(blocks_y):forxinrange(blocks_x):this_image=img.crop((x*block_width,y*block_height,(x+1)*block_width,(y+1)*block_height))ifthis_image.getcolors()==rgba_0:map[y][x]=0elifthis_image.getcolors()==rgba_1:map[y][x]=1elifthis_image.getcolors()==rgba_2:map[y][x]=2elifthis_image.getcolors()==rgba_3:map[y][x]=3elifthis_image.getcolors()==rgba_4:map[y][x]=4elifthis_image.getcolors()==rgba_5:map[y][x]=5elifthis_image.getcolors()==rgba_6:map[y][x]=6elifthis_image.getcolors()==rgba_8:map[y][x]]=8elifthis_image.getcolors()==rgba_ed:map[y][x]=-1elifthis_image.getcolors()==rgba_hongqi:map[y][x]=-4elifthis_image.getcolors()==rgba_boomorthis_image.getcolors()==rgba_boom_red:globalgameovergameover=1break#sys.exit(0)else:print("无法识别的图像")print("坐标")print((y,x))print("color")print(this_image.getcolors())sys.exit(0)#print(map)5.扫雷算法我这里用的最基本的算法1.先指出一个点2.扫描所有的数字,如果周围的空格+标志==数字,那么空白还有是地雷,右击空白标志3.扫描所有数字,如果有e周围的flags==numbers,空白处没有地雷,左键点击空白处4.循环2、3,如果没有符合条件的,随机点击一个Whiteblock#flagdefbanner():showmap()foryinrange(blocks_y):forxinrange(blocks_x):if1<=map[y][x]andmap[y][x]<=5:boom_number=map[y][x]block_white=0block_qi=0foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy0:foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy