如何基于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 相关文章推荐
使用py2exe在Windows下将Python程序转为exe文件
Mar 04 Python
python爬虫_实现校园网自动重连脚本的教程
Apr 22 Python
Python绘制正余弦函数图像的方法
Aug 28 Python
python实现桌面气泡提示功能
Jul 29 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
Sep 02 Python
python-OpenCV 实现将数组转换成灰度图和彩图
Jan 09 Python
Python标准库itertools的使用方法
Jan 17 Python
python字典key不能是可以是啥类型
Aug 04 Python
python 基于opencv实现高斯平滑
Dec 18 Python
python常量折叠基础知识点讲解
Feb 28 Python
PyQt5爬取12306车票信息程序的实现
May 14 Python
浅谈Python中的函数(def)及参数传递操作
May 25 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笔记之常用文件操作
2010/10/12 PHP
CMS中PHP判断系统是否已经安装的方法示例
2014/07/26 PHP
使用ob系列函数实现PHP网站页面静态化
2014/08/13 PHP
PHP url的pathinfo模式加载不同控制器的简单实现
2016/08/12 PHP
永不消失的title提示代码
2007/02/15 Javascript
jQuery实战之品牌展示列表效果
2011/04/10 Javascript
jquery中获取select选中值的代码
2011/06/27 Javascript
div+css+js实现无缝滚动类似marquee无缝滚动兼容firefox
2013/08/29 Javascript
js获取当前页面的url网址信息
2014/06/12 Javascript
angularjs客户端实现压缩图片文件并上传实例
2015/07/06 Javascript
基于JavaScript如何实现ajax调用后台定义的方法
2015/12/29 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
js获取html页面代码中图片地址的实现代码
2018/03/05 Javascript
Webpack之tree-starking 解析
2018/09/11 Javascript
[02:07]DOTA2新英雄展现中国元素,完美“圣典”亮相央视
2016/12/19 DOTA
python MySQLdb Windows下安装教程及问题解决方法
2015/05/09 Python
利用Python代码实现数据可视化的5种方法详解
2018/03/25 Python
pandas 快速处理 date_time 日期格式方法
2018/11/12 Python
Python 3.8新特征之asyncio REPL
2019/05/28 Python
Pyqt5 实现跳转界面并关闭当前界面的方法
2019/06/19 Python
深入了解python中元类的相关知识
2019/08/29 Python
pycharm sciview的图片另存为操作
2020/06/01 Python
python让函数不返回结果的方法
2020/06/22 Python
python中使用asyncio实现异步IO实例分析
2021/02/26 Python
css3中flex布局宽度不生效的解决
2020/12/09 HTML / CSS
中兴通讯全球官方网站:ZTE
2020/12/26 全球购物
医大实习自我鉴定
2013/12/07 职场文书
大学生表扬信范文
2014/01/09 职场文书
拖鞋店创业计划书
2014/01/15 职场文书
彩色的翅膀教学反思
2014/04/25 职场文书
新教师培训心得体会
2014/09/02 职场文书
毕业生见习报告总结
2014/11/08 职场文书
检讨书范文
2015/01/27 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
初中政治教学工作总结
2015/08/13 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android