Bigmerboy 发表于 2020-1-6 12:08:31

利用Python实现自动扫雷小脚本!就没有我过不了的扫雷游戏 ...

自动扫雷一般分为两种,一种是读取内存数据,而另一种是通过分析图片获得数据,并通过模拟鼠标操作,这里我用的是第二种方式。
代码已上传至GitHub:

https://github.com/chestnut-egg/GoMine

作者:chestnut_egg

源自:

https://www.cnblogs.com/chestnut-egg/p/9302238.html


一、准备工作

1.扫雷游戏

我是win10,没有默认的扫雷,所以去扫雷网下载
http://www.saolei.net/BBS/

2.python 3

我的版本是 python 3.6.1
3.python的第三方库

win32api,win32gui,win32con,Pillow,numpy,opencv
可通过 pip install --upgrade SomePackage 来进行安装
注意:有的版本是下载pywin32,但是有的要把pywin32升级到最高并自动下载了pypiwin32,具体情况每个python版本可能都略有不同
我给出我的第三方库和版本仅供参考


二、关键代码组成

1.找到游戏窗口与坐标



#扫雷游戏窗口class_name="TMain"title_name="MinesweeperArbiter"hwnd=win32gui.FindWindow(class_name,title_name)#窗口坐标left=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("未找到窗口")

2.锁定并抓取雷区图像



#锁定雷区坐标#去除周围功能按钮以及多余的界面#具体的像素值是通过QQ的截图来判断的left+=15top+=101right-=15bottom-=42#抓取雷区图像rect=(left,top,right,bottom)img=ImageGrab.grab().crop(rect)

3.各图像的RGBA值



#数字1-8周围雷数#0未被打开#ed被打开空白#hongqi红旗#boom普通雷#boom_red踩中的雷rgba_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=0elifthis_image.getcolors()==rgba_1:map=1elifthis_image.getcolors()==rgba_2:map=2elifthis_image.getcolors()==rgba_3:map=3elifthis_image.getcolors()==rgba_4:map=4elifthis_image.getcolors()==rgba_5:map=5elifthis_image.getcolors()==rgba_6:map=6elifthis_image.getcolors()==rgba_8:map=8elifthis_image.getcolors()==rgba_ed:map=-1elifthis_image.getcolors()==rgba_hongqi:map=-4elifthis_image.getcolors()==rgba_boomorthis_image.getcolors()==rgba_boom_red:globalgameovergameover=1break#sys.exit(0)else:print("无法识别图像")print("坐标")print((y,x))print("颜色")print(this_image.getcolors())sys.exit(0)#print(map)

(左右滑动可查看完整代码)

5.扫雷算法

这里我采用的最基础的算法
1.首先点出一个点
2.扫描所有数字,如果周围空白+插旗==数字,则空白均有雷,右键点击空白插旗
3.扫描所有数字,如果周围插旗==数字,则空白均没有雷,左键点击空白
4.循环2、3,如果没有符合条件的,则随机点击一个白块


#插旗defbanner():showmap()foryinrange(blocks_y):forxinrange(blocks_x):if1<=mapandmap<=5:boom_number=mapblock_white=0block_qi=0foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy<blocks_yandxx<blocks_x:ifnot(yy==yandxx==x):ifmap==0:block_white+=1elifmap==-4:block_qi+=1ifboom_number==block_white+block_qi:foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy<blocks_yandxx<blocks_x:ifnot(yy==yandxx==x):ifmap==0:win32api.SetCursorPos()win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,0,0,0,0)showmap()#点击白块defdig():showmap()iscluck=0foryinrange(blocks_y):forxinrange(blocks_x):if1<=mapandmap<=5:boom_number=mapblock_white=0block_qi=0foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy<blocks_yandxx<blocks_x:ifnot(yy==yandxx==x):ifmap==0:block_white+=1elifmap==-4:block_qi+=1ifboom_number==block_qiandblock_white>0:foryyinrange(y-1,y+2):forxxinrange(x-1,x+2):if0<=yyand0<=xxandyy<blocks_yandxx<blocks_x:ifnot(yy==yandxx==x):ifmap==0:win32api.SetCursorPos()win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)iscluck=1ifiscluck==0:luck()#随机点击defluck():fl=1while(fl):random_x=random.randint(0,blocks_x-1)random_y=random.randint(0,blocks_y-1)if(map==0):win32api.SetCursorPos()win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)fl=0defgogo():win32api.SetCursorPos()win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)showmap()globalgameoverwhile(1):if(gameover==0):banner()banner()dig()else:gameover=0win32api.keybd_event(113,0,0,0)win32api.SetCursorPos()win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0)showmap()私信小编01 领取完整项目代码!

家家顺小伍 发表于 2020-1-6 12:16:29

好,很好,非常好!

夜·月痕 发表于 2020-1-21 16:44:56

不错 支持一个了

在下菊发 发表于 2020-1-28 10:18:51

支持,楼下的跟上哈~

smcgrady 发表于 2020-1-29 07:51:02

路过 帮顶 嘿嘿

alina222 发表于 2020-2-3 00:55:24

我也来顶一下..

萧笠翁寒江雪 发表于 2020-2-4 15:05:19

支持楼主,用户楼主,楼主英明呀!!!

chenpps 发表于 2020-2-15 02:10:43

非常好,顶一下

1058715979 发表于 2020-2-16 04:08:59

无论是不是沙发都得回复下

柔柔贝贝 发表于 2020-2-23 03:32:32

支持,楼下的跟上哈~
页: [1] 2 3 4 5 6 7 8
查看完整版本: 利用Python实现自动扫雷小脚本!就没有我过不了的扫雷游戏 ...