如何基于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中删除文件的程序代码
Mar 13 Python
Python实现动态添加类的属性或成员函数的解决方法
Jul 16 Python
python利用装饰器进行运算的实例分析
Aug 04 Python
浅谈终端直接执行py文件,不需要python命令
Jan 23 Python
PyTorch线性回归和逻辑回归实战示例
May 22 Python
Python实现Dijkstra算法
Oct 17 Python
scrapy-redis的安装部署步骤讲解
Feb 27 Python
Python后台开发Django的教程详解(启动)
Apr 08 Python
python 五子棋如何获得鼠标点击坐标
Nov 04 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
Dec 04 Python
Python 使用 PyQt5 开发的关机小工具分享
Jul 16 Python
使用python tkinter开发一个爬取B站直播弹幕工具的实现代码
Feb 07 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桌面中心(一) 创建数据库
2007/03/11 PHP
yii的CURD操作实例详解
2014/12/04 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
2019/03/21 PHP
jQuery获取文本节点之 text()/val()/html() 方法区别
2011/03/01 Javascript
jQuery操作input值的各种方法总结
2013/11/21 Javascript
jquery遍历table的tr获取td的值实现方法
2016/05/19 Javascript
微信小程序实现图片上传、删除和预览功能的方法
2017/12/18 Javascript
Node.js实现注册邮箱激活功能的方法示例
2018/03/23 Javascript
axios携带cookie配置详解(axios+koa)
2018/12/28 Javascript
了解javascript中let和var及const关键字的区别
2019/05/24 Javascript
JS实现transform实现扇子效果
2020/01/17 Javascript
微信小程序接入vant Weapp组件的详细步骤
2020/10/28 Javascript
js闭包的9个使用场景
2020/12/29 Javascript
用Python编写简单的微博爬虫
2016/03/04 Python
Python实现字符串匹配算法代码示例
2017/12/05 Python
对python修改xml文件的节点值方法详解
2018/12/24 Python
python3实现表白神器
2019/04/09 Python
Python Django给admin添加Action的方法实例详解
2019/04/29 Python
python用类实现文章敏感词的过滤方法示例
2019/10/27 Python
Python 实现数组相减示例
2019/12/27 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
python如何通过闭包实现计算器的功能
2020/02/22 Python
Python 日期与时间转换的方法
2020/08/01 Python
html5 canvas 实现光线沿不规则路径运动
2020/04/20 HTML / CSS
Erwin Müller穆勒家居瑞士官网:您整个家庭的邮购公司
2019/12/28 全球购物
计算机大学生职业生涯规划书范文
2014/02/19 职场文书
数控专业毕业生自荐信范文
2014/03/04 职场文书
公司授权委托书范本
2014/04/03 职场文书
家庭教育的心得体会
2014/09/01 职场文书
2014坚持党风廉政建设思想汇报
2014/09/18 职场文书
教师党员自我评议不足范文
2014/10/19 职场文书
2016幼儿园毕业感言
2015/12/08 职场文书
2019财务管理制度最新范本!
2019/07/09 职场文书
MySQL 百万级数据的4种查询优化方式
2021/06/07 MySQL
Java8 Stream API 提供了一种高效且易于使用的处理数据的方式
2022/04/13 Java/Android
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
2022/06/01 Java/Android