來源: chestnut-egg??
鏈接: https://www.cnblogs.com/chestnut-egg/p/9302238.html
自動掃雷一般分為兩種,一種是讀取內(nèi)存數(shù)據(jù),而另一種是通過分析圖片獲得數(shù)據(jù),并通過模擬鼠標操作,這里我用的是第二種方式。
代碼已上傳至GitHub
一、準備工作
1.掃雷游戲
我是win10,沒有默認的掃雷,所以去掃雷網(wǎng)下載
http://www.saolei.net/BBS/
2.python 3
我的版本是 python 3.6.1
3.python的第三方庫
我給出我的第三方庫和版本僅供參考
二、關鍵代碼組成
1.找到游戲窗口與坐標
#掃雷游戲窗口
class_name?=?"TMain"
title_name?=?"Minesweeper?Arbiter?"
hwnd?=?win32gui.FindWindow(class_name,?title_name)
#窗口坐標
left?=?0
top?=?0
right?=?0
bottom?=?0
if?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.鎖定并抓取雷區(qū)圖像
#鎖定雷區(qū)坐標
#去除周圍功能按鈕以及多余的界面
#具體的像素值是通過QQ的截圖來判斷的
left?+=?15
top?+=?101
right?-=?15
bottom?-=?42
#抓取雷區(qū)圖像
rect?=?(left,?top,?right,?bottom)
img?=?ImageGrab.grab().crop(rect)
3.各圖像的RGBA值
#數(shù)字1-8?周圍雷數(shù)
#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.掃描雷區(qū)圖像保存至一個二維數(shù)組map
#掃描雷區(qū)圖像
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.掃描所有數(shù)字,如果周圍空白+插旗==數(shù)字,則空白均有雷,右鍵點擊空白插旗
3.掃描所有數(shù)字,如果周圍插旗==數(shù)字,則空白均沒有雷,左鍵點擊空白
4.循環(huán)2、3,如果沒有符合條件的,則隨機點擊一個白塊
#插旗
def?banner():
????showmap()
????for?y?in?range(blocks_y):
????????for?x?in?range(blocks_x):
????????????if?1?<=?map[y][x]?and?map[y][x]?<=?5:
????????????????boom_number?=?map[y][x]
????????????????block_white?=?0
????????????????block_qi?=?0
????????????????for?yy?in?range(y-1,y+2):
????????????????????for?xx?in?range(x-1,x+2):
????????????????????????if?0?<=?yy?and?0?<=?xx?and?yy?<?blocks_y?and?xx?<?blocks_x:
????????????????????????????if?not?(yy?==?y?and?xx?==?x):if?map[yy][xx]?==?0:
????????????????????????????????????block_white?+=?1
????????????????????????????????elif?map[yy][xx]?==?-4:
????????????????????????????????????block_qi?+=?1if?boom_number?==?block_white?+?block_qi:for?yy?in?range(y?-?1,?y?+?2):
????????????????????????for?xx?in?range(x?-?1,?x?+?2):
????????????????????????????if?0?<=?yy?and?0?<=?xx?and?yy?<?blocks_y?and?xx?<?blocks_x:
????????????????????????????????if?not?(yy?==?y?and?xx?==?x):
????????????????????????????????????if?map[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?=?0
????for?y?in?range(blocks_y):
????????for?x?in?range(blocks_x):
????????????if?1?<=?map[y][x]?and?map[y][x]?<=?5:
????????????????boom_number?=?map[y][x]
????????????????block_white?=?0
????????????????block_qi?=?0
????????????????for?yy?in?range(y?-?1,?y?+?2):
????????????????????for?xx?in?range(x?-?1,?x?+?2):
????????????????????????if?0?<=?yy?and?0?<=?xx?and?yy?<?blocks_y?and?xx?<?blocks_x:
????????????????????????????if?not?(yy?==?y?and?xx?==?x):
????????????????????????????????if?map[yy][xx]?==?0:
????????????????????????????????????block_white?+=?1
????????????????????????????????elif?map[yy][xx]?==?-4:
????????????????????????????????????block_qi?+=?1if?boom_number?==?block_qi?and?block_white?>?0:for?yy?in?range(y?-?1,?y?+?2):
????????????????????????for?xx?in?range(x?-?1,?x?+?2):
????????????????????????????if?0?<=?yy?and?0?<=?xx?and?yy?<?blocks_y?and?xx?<?blocks_x:
????????????????????????????????if?not(yy?==?y?and?xx?==?x):
????????????????????????????????????if?map[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?=?1
????if?iscluck?==?0:
????????luck()
#隨機點擊
def?luck():
????fl?=?1
????while(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?=?0
def?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?gameover
????while(1):
????????if(gameover?==?0):
????????????banner()
????????????banner()
????????????dig()
????????else:
????????????gameover?=?0
????????????win32api.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()
這個算法在初級和中級通過率都不錯,但是在高級成功率慘不忍睹,主要是沒有考慮邏輯組合以及白塊是雷的概率問題,可以對這兩個點進行改進,提高成功率。
歡迎加入免費星球,獲取最前沿認知和精英理念
掃碼領取資料
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
