如何基于Python实现自动扫雷


Posted in Python onJanuary 06, 2020

这篇文章主要介绍了如何基于Python实现自动扫雷,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

如何基于Python实现自动扫雷

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

一、准备工作

我的版本是 python 3.6.1

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 = 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中的__slots__使用示例
Feb 26 Python
Python打造出适合自己的定制化Eclipse IDE
Mar 02 Python
python3连接MySQL数据库实例详解
May 24 Python
Python socket实现多对多全双工通信的方法
Feb 13 Python
python opencv 读取图片 返回图片某像素点的b,g,r值的实现方法
Jul 03 Python
Django 源码WSGI剖析过程详解
Aug 05 Python
Django ORM 查询管理器源码解析
Aug 05 Python
python实现输入的数据在地图上生成热力图效果
Dec 06 Python
Django+boostrap 美化admin后台的操作
Mar 11 Python
PyCharm上安装Package的实现(以pandas为例)
Sep 18 Python
python实现网页录音效果
Oct 26 Python
基于Python实现全自动下载抖音视频
Nov 06 Python
pytorch 自定义参数不更新方式
Jan 06 #Python
3种python调用其他脚本的方法
Jan 06 #Python
pytorch 实现模型不同层设置不同的学习率方式
Jan 06 #Python
浅析Python3 pip换源问题
Jan 06 #Python
通过实例学习Python Excel操作
Jan 06 #Python
pytorch载入预训练模型后,实现训练指定层
Jan 06 #Python
python与mysql数据库交互的实现
Jan 06 #Python
You might like
php 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
PHP中include()与require()的区别说明
2010/03/10 PHP
php 获取全局变量的代码
2011/04/21 PHP
PHP把网页保存为word文件的三种方法
2014/04/01 PHP
php利用反射实现插件机制的方法
2015/03/14 PHP
php文件包含目录配置open_basedir的使用与性能详解
2017/04/03 PHP
PHP实现的迪科斯彻(Dijkstra)最短路径算法实例
2017/09/16 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
深入理解JavaScript系列(12) 变量对象(Variable Object)
2012/01/16 Javascript
jquery插件tooltipv顶部淡入淡出效果使用示例
2013/12/05 Javascript
jquery实现的一个文章自定义分段显示功能
2014/05/23 Javascript
jQuery Password Validation密码验证
2016/12/30 Javascript
jQuery插件扩展操作入门示例
2017/01/16 Javascript
Vue.js对象转换实例
2017/06/07 Javascript
vue.js实现备忘录功能的方法
2017/07/10 Javascript
vue使用i18n实现国际化的方法详解
2019/09/05 Javascript
jQuery实现王者荣耀手风琴效果
2020/01/17 jQuery
js实现整体缩放页面适配移动端
2020/03/31 Javascript
Vue实现菜单切换功能
2020/11/08 Javascript
[04:46]2018年度玩家喜爱的电竞媒体-完美盛典
2018/12/16 DOTA
Python中os.path用法分析
2015/01/15 Python
python实现简单socket程序在两台电脑之间传输消息的方法
2015/03/13 Python
Python两个整数相除得到浮点数值的方法
2015/03/18 Python
Python实现拷贝多个文件到同一目录的方法
2016/09/19 Python
python2 与 pyhton3的输入语句写法小结
2018/09/10 Python
Django异步任务之Celery的基本使用
2019/03/23 Python
Flask框架 CSRF 保护实现方法详解
2019/10/30 Python
Python Process创建进程的2种方法详解
2021/01/25 Python
美国背景检查、公共记录和人物搜索网站:BeenVerified
2018/02/25 全球购物
俄罗斯鲜花递送:AMF
2020/04/24 全球购物
大学本科毕业生求职简历的自我评价
2013/10/09 职场文书
《桥》教学反思
2014/04/09 职场文书
2016预备党员培训心得体会
2016/01/08 职场文书
uwsgi+nginx代理Django无法访问静态资源的解决
2021/05/10 Servers
5行Python代码实现一键批量扣图
2021/06/29 Python
Apache Kafka 分区重分配的实现原理解析
2022/07/15 Servers