利用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 ="Minesweeper Arbiter "hwnd = win32gui.FindWindow(class_name, title_name)#窗口坐标left=0top=0right=0bottom=0if hwnd: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

#扫描雷区图像def showmap(): img = ImageGrab.grab().crop(rect) for y in range(blocks_y): for x in range(blocks_x): this_image = img.crop((x * block_width, y* block_height, (x + 1) *block_width, (y + 1) * block_height)) if this_image.getcolors() == rgba_0: map[y][x] = 0 elif this_image.getcolors() == rgba_1: map[y][x] = 1 elif this_image.getcolors() == rgba_2: map[y][x] = 2 elif this_image.getcolors() == rgba_3: map[y][x] = 3 elif this_image.getcolors() == rgba_4: map[y][x] = 4 elif this_image.getcolors() == rgba_5: map[y][x] = 5 elif this_image.getcolors() == rgba_6: map[y][x] = 6 elif this_image.getcolors() == rgba_8: map[y][x] = 8 elif this_image.getcolors() == rgba_ed: map[y][x] = -1 elif this_image.getcolors() == rgba_hongqi: map[y][x] = -4 elif this_image.getcolors() == rgba_boom or this_image.getcolors() == rgba_boom_red: global gameover gameover = 1 break #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,如果没有符合条件的,则随机点击一个白块

#插旗def banner(): 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<= xxandyy < blocks_yandxx < blocks_x:ifnot(yy == yandxx == x):ifmap[yy][xx] ==0: block_white +=1elifmap[yy][xx] == -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[yy][xx] ==0: win32api.SetCursorPos([left+xx*block_width, top+yy*block_height]) win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,0,0,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,0,0,0,0) showmap()#点击白块def dig(): showmap() iscluck =0foryinrange(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<= xxandyy < blocks_yandxx < blocks_x:ifnot(yy == yandxx == x):ifmap[yy][xx] ==0: block_white +=1elifmap[yy][xx] == -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[yy][xx] ==0: win32api.SetCursorPos([left + xx * block_width, top + yy * block_height]) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0) iscluck =1ifiscluck ==0: luck()#随机点击def luck(): fl =1while(fl): random_x =random.randint(0, blocks_x -1) random_y =random.randint(0, blocks_y -1)if(map[random_y][random_x] ==0): win32api.SetCursorPos([left + random_x * block_width, top + random_y * block_height]) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0) fl =0def gogo(): win32api.SetCursorPos([left, top]) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0) showmap() global gameoverwhile(1):if(gameover ==0): banner() banner() dig()else: gameover =0win32api.keybd_event(113,0,0,0) win32api.SetCursorPos([left, top]) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0,0,0) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0,0,0) showmap()

最后,Python学习关注,免费直播最新课程学习群:839383765 分享业内最新python知识!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • 自动扫雷一般分为两种,一种是读取内存数据,而另一种是通过分析图片获得数据,并通过模拟鼠标操作,这里我用的是第二种方...
    嗨学编程阅读 613评论 0 0
  • 偶然的机会发现简书这个软件,起初以为是读书软件,点入后发现原来是写书软件。其实我不是一个会写作的人,但是对于那些会...
    海盗船长甜阅读 205评论 0 0
  • 2017年6月4日晚 如果说失败是做事的妈,那成功就是他爹!我心里清楚,首仗胜利是个偶然,有必要做个总结: 第一,...
    思辨365阅读 383评论 0 0
  • T40-C3 红瓶精油 5.8ml 编号:2164 零售价:160 优惠价:112 T36-c5 绿瓶精油 15...
    Anna柳青华阅读 2,088评论 0 0
  • 经常在单位宿舍里,放假也不回家。一次,有个同事很诧异的看着我问:“你为什么老不回家啊?”我诧异的反问:“回家干嘛啊...
    屋顶上的橘猫阅读 127评论 0 0