python实战教程之自动扫雷


Posted in Python onJuly 13, 2018

前言

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

一、准备工作

1.扫雷游戏

我是win10,没有默认的扫雷,所以去扫雷网下载

http://www.saolei.net/BBS/

python实战教程之自动扫雷

2.python 3

我的版本是 python 3.6.1

3.python的第三方库

win32api,win32gui,win32con,Pillow,numpy,opencv

可通过 pip install --upgrade SomePackage 来进行安装

注意:有的版本是下载pywin32,但是有的要把pywin32升级到最高并自动下载了pypiwin32,具体情况每个python版本可能都略有不同

我给出我的第三方库和版本仅供参考

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.锁定并抓取雷区图像

#锁定雷区坐标#去除周围功能按钮以及多余的界面#具体的像素值是通过QQ的截图来判断的
left += 15
top += 101
right -= 15
bottom -= 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()
 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()

这个算法在初级和中级通过率都不错,但是在高级成功率惨不忍睹,主要是没有考虑逻辑组合以及白块是雷的概率问题,可以对这两个点进行改进,提高成功率

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python 网页解析HTMLParse的实例详解
Aug 10 Python
一道python走迷宫算法题
Jan 22 Python
python如何统计序列中元素
Jul 31 Python
Python补齐字符串长度的实例
Nov 15 Python
Python中一般处理中文的几种方法
Mar 06 Python
详解python 爬取12306验证码
May 10 Python
如何通过python画loss曲线的方法
Jun 26 Python
django admin组件使用方法详解
Jul 19 Python
Python中__repr__和__str__区别详解
Nov 07 Python
从pandas一个单元格的字符串中提取字符串方式
Dec 17 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
Jan 14 Python
matplotlib 生成的图像中无法显示中文字符的解决方法
Jun 10 Python
详解Python3.6的py文件打包生成exe
Jul 13 #Python
python2 与 python3 实现共存的方法
Jul 12 #Python
Python3单行定义多个变量或赋值方法
Jul 12 #Python
Python读取数据集并消除数据中的空行方法
Jul 12 #Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
Jul 12 #Python
python跳过第一行快速读取文件内容的实例
Jul 12 #Python
python 读取文本文件的行数据,文件.splitlines()的方法
Jul 12 #Python
You might like
如何在smarty中增加类似foreach的功能自动加载数据
2013/06/26 PHP
PHP数组相加操作及与array_merge的区别浅析
2016/11/26 PHP
js textarea自动增高并隐藏滚动条
2009/12/16 Javascript
javascript 获取url参数和script标签中获取url参数函数代码
2010/01/22 Javascript
控制input输入框中提示信息的显示和隐藏的方法
2014/02/12 Javascript
node.js中的fs.futimesSync方法使用说明
2014/12/17 Javascript
js+css实现导航效果实例
2015/02/10 Javascript
JavaScript实现网页对象拖放功能的方法
2015/04/15 Javascript
在JavaScript中如何解决用execCommand(
2015/10/19 Javascript
JavaScript中字面量与函数的基本使用知识
2015/10/20 Javascript
Javascript的表单验证长度
2016/03/16 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
jQuery实现的简单分页示例
2016/06/01 Javascript
jquery延迟对象解析
2016/10/26 Javascript
通过V8源码看一个关于JS数组排序的诡异问题
2017/08/14 Javascript
JS简单实现数组去重的方法分析
2017/10/14 Javascript
Vue2 轮播图slide组件实例代码
2018/05/31 Javascript
浅谈Angular6的服务和依赖注入
2018/06/27 Javascript
vue实现动态添加数据滚动条自动滚动到底部的示例代码
2018/07/06 Javascript
js字符串倒序的实例代码
2018/11/30 Javascript
jQuery - AJAX load() 实例用法详解
2019/08/27 jQuery
解决vue自定义指令导致的内存泄漏问题
2020/08/04 Javascript
vue离开当前页面触发的函数代码
2020/09/01 Javascript
python正则表达式去掉数字中的逗号(python正则匹配逗号)
2013/12/25 Python
python3的输入方式及多组输入方法
2018/10/17 Python
python中字符串数组逆序排列方法总结
2019/06/23 Python
flask的orm框架SQLAlchemy查询实现解析
2019/12/12 Python
在django admin详情表单显示中添加自定义控件的实现
2020/03/11 Python
CSS3 创建网页动画实现弹跳球动效果
2018/10/30 HTML / CSS
Expedia印度尼西亚站:预订酒店、廉价航班和度假套餐
2018/01/31 全球购物
TheFork葡萄牙:欧洲领先的在线餐厅预订平台
2019/05/27 全球购物
ECOSUSI官网:女式皮革背包
2019/09/27 全球购物
丝芙兰墨西哥官网:Sephora墨西哥
2020/05/30 全球购物
新闻专业个人求职信
2013/12/19 职场文书
运动会800米赞词
2015/07/22 职场文书
思品教学工作总结
2015/08/10 职场文书