如何基于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 相关文章推荐
web.py中调用文件夹内模板的方法
Aug 26 Python
python动态参数用法实例分析
May 25 Python
Python 比较两个数组的元素的异同方法
Aug 17 Python
Python 基础教程之str和repr的详解
Aug 20 Python
python跳过第一行快速读取文件内容的实例
Jul 12 Python
更改Python的pip install 默认安装依赖路径方法详解
Oct 27 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
Oct 14 Python
Python搭建代理IP池实现获取IP的方法
Oct 27 Python
pandas-resample按时间聚合实例
Dec 27 Python
Python如何读取文件中图片格式
Jan 13 Python
Python GUI库Tkiner使用方法代码示例
Nov 27 Python
python 调用js的四种方式
Apr 11 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
关于mysql字符集设置了character_set_client=binary 在gbk情况下会出现表描述是乱码的情况
2013/01/06 PHP
windows环境下php配置memcache的具体操作步骤
2013/06/09 PHP
PHP的中使用非缓冲模式查询数据库的方法
2017/02/05 PHP
Javascript中的关键字和保留字整理
2014/10/16 Javascript
基于jQuery实现下拉框
2014/11/24 Javascript
node.js操作mongoDB数据库示例分享
2014/11/26 Javascript
jquery实现平滑的二级下拉菜单效果
2015/08/26 Javascript
JS实现网页每隔3秒弹出一次对话框的方法
2015/11/09 Javascript
js简单实现网页换肤功能
2017/04/07 Javascript
node.js的exports、module.exports与ES6的export、export default深入详解
2017/10/26 Javascript
第一个Vue插件从封装到发布
2017/11/22 Javascript
如何获取TypeScript的声明文件.d.ts
2018/05/01 Javascript
详解Vue微信授权登录前后端分离较为优雅的解决方案
2018/06/29 Javascript
详解搭建es6+devServer简单开发环境
2018/09/25 Javascript
微信小程序实现保存图片到相册功能
2018/11/30 Javascript
Javascript通过控制类名更改样式
2019/05/24 Javascript
jQuery实现朋友圈查看图片
2020/09/11 jQuery
Javascript中window.name属性详解
2020/11/19 Javascript
[02:59]2014DOTA2西雅图国际邀请赛 圆满落幕中国夺冠
2014/07/23 DOTA
在Python的Flask框架中实现全文搜索功能
2015/04/20 Python
pandas 快速处理 date_time 日期格式方法
2018/11/12 Python
Python使用sklearn实现的各种回归算法示例
2019/07/04 Python
python识别文字(基于tesseract)代码实例
2019/08/24 Python
Python 实现自动导入缺失的库
2019/10/29 Python
Django异步任务线程池实现原理
2019/12/17 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
Python 面向对象之类class和对象基本用法示例
2020/02/02 Python
美国家居装饰网上商店:Lulu & Georgia
2019/09/14 全球购物
上课迟到检讨书100字
2014/01/11 职场文书
会议开场欢迎词
2014/01/15 职场文书
小学国庆节活动方案
2014/02/11 职场文书
小学学校门卫岗位职责
2014/08/03 职场文书
pytorch中的model.eval()和BN层的使用
2021/05/22 Python
Mysql中调试存储过程最简单的方法
2021/06/30 MySQL
vue如何实现关闭对话框后刷新列表
2022/04/08 Vue.js