c# 实现自动扫雷

 更新时间:2021年02月19日 11:38:19   作者:seabluescn  
这篇文章主要介绍了c# 实现自动扫雷的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

    年前无意看到一个用Python写的小桌面程序,可以自动玩扫雷的游戏,觉得挺有意思,决定用C#也做一个。【真实情况是:我知道Python最近比较火,非常适合搞爬虫、大数据、机器学习之类的,但现在连桌面程序都用Python做了吗?还给不给.NET程序员活路了?简直不能忍!】

   春节期间正好有闲就搞了一下,先下载了一个第三方的扫雷游戏,实现功能以后觉得下载的这个扫雷游戏分辨率太低了,也不好看,所以又自己做了一个扫雷游戏,凑成一套。

    源码下载地址:https://github.com/seabluescn/AutoMineSweeper

    需要提前说明的是,这两个程序是独立的,之间没有任何接口与联系,自动扫雷的程序通过读取屏幕信息获取游戏状态,并模拟鼠标操作来进行游戏。下面就几个相关技术点和大家分享一下。

1、获取应用程序窗口

[DllImport("user32.dll")]
    private static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);

    private Rect GetWindowRect()
    {
      Process[] processes = Process.GetProcesses();
      Process process = null;
      for (int i = 0; i < processes.Length - 1; i++)
      {
        process = processes[i];
        if (process.MainWindowTitle == "MineSweeper")
        {
          break;
        }        
      }     

      Rect rect = new Rect();
      GetWindowRect(process.MainWindowHandle, out rect);

      return rect;
    }

2、屏幕截图

Rect rect = GetWindowRect();

      int left = rect.Left;
      int top = rect.Top; 

      int centerleft = 21;  //偏移
      int centertop = 93;
      int centerwidth = 300;
      int centerheight = 300;
      
      Bitmap bitmapCenter = new Bitmap(centerwidth, centerheight);
      using (Graphics graphics = Graphics.FromImage(bitmapCenter))
      {
        graphics.CopyFromScreen(left + centerleft, top + centertop, 0, 0, new Size(centerwidth, centerheight));
        this.pictureBox1.Image?.Dispose();
        this.pictureBox1.Image = bitmapCenter;
      }

截图后,根据图片上固定位置的颜色信息判断该位置的状态,最终形成一个数组。

3、模拟鼠标点击

[DllImport("user32")]
    private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

    const int MOUSEEVENTF_MOVE = 0x0001; //移动鼠标
    const int MOUSEEVENTF_LEFTDOWN = 0x0002; //模拟鼠标左键按下
    const int MOUSEEVENTF_LEFTUP = 0x0004; //模拟鼠标左键抬起
    const int MOUSEEVENTF_RIGHTDOWN = 0x0008; //模拟鼠标右键按下
    const int MOUSEEVENTF_RIGHTUP = 0x0010; //模拟鼠标右键抬起
    const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; //模拟鼠标中键按下
    const int MOUSEEVENTF_MIDDLEUP = 0x0040; //模拟鼠标中键抬起
    const int MOUSEEVENTF_ABSOLUTE = 0x8000; //标示是否采用绝对坐标

        int clickPointX = X * 65535 / Screen.PrimaryScreen.Bounds.Width;
        int clickPointY = Y * 65535 / Screen.PrimaryScreen.Bounds.Height;

        //移动鼠标
        mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, clickPointX, clickPointY, 0, 0);

        //左键点击
        mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        
        //右键点击
        mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);

4、游戏算法

获得游戏状态后,需要判断下一步操作,是点开某个位置还是右键标记某个位置,算法循环遍历所有方块,一共三步:

1)基础算法

基础算法1:对于已经翻开的块,中心数字和周围已经标记的雷数一致,其周围所有未知位置都不是雷,左键点开

基础算法2:对于已经翻开的块,中心数字=未知位置数量+周围已经标记的雷数 :其周围所有未知位置均为雷,右键标记

2)高一级算法

先计算所有已翻开的块,其周围未知块含雷的数量之和。

算法1:对于已经翻开的块,如果周围未知块超过2个,其中有一个未知块:中心数字-雷==其他位置块组合雷数总和:该未知块必不是雷

算法2:对于已经翻开的块,如果周围未知块超过2个,其中有一个未知块:数字-雷-其他位置块组合雷数=1:该未知块必是雷

3)实在没有找到合适的点,只能随机点开

对所有未知的点,计算一下周围雷的概率,选择概率最小的点开。

经测试,程序对目标状态的识别率为100%,智能程度还不错,比一般人玩的好,无聊时可以看它玩一天。

以上就是c# 实现自动扫雷的详细内容,更多关于c# 扫雷的资料请关注脚本之家其它相关文章!

相关文章

  • C#中把DataTable、Dataset转Json数据

    C#中把DataTable、Dataset转Json数据

    这篇文章介绍了C#中把DataTable、Dataset转Json数据的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#实现扫雷游戏

    C#实现扫雷游戏

    这篇文章主要为大家详细介绍了C#实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 探讨c#中的unchecked是什么意思,起什么作用?

    探讨c#中的unchecked是什么意思,起什么作用?

    本篇文章是对c#中的unchecked进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C#使用Lazy<T>实现对客户订单的延迟加载

    C#使用Lazy<T>实现对客户订单的延迟加载

    这篇文章介绍了C#使用Lazy<T>实现对客户订单延迟加载的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Unity使用鼠标旋转物体效果

    Unity使用鼠标旋转物体效果

    这篇文章主要为大家详细介绍了Unity使用鼠标旋转物体效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 详解如何在C#中接受或拒绝Excel中的修订

    详解如何在C#中接受或拒绝Excel中的修订

    修订功能可以跟踪文档所有的修改,了解修改的过程,这对于团队协同文档编辑、审阅是非常有用的一个功能。本文将详细为您介绍如何接受或拒绝 Excel 中的修订,感兴趣的可以收藏一下
    2022-12-12
  • C#托管内存与非托管内存之间的转换的实例讲解

    C#托管内存与非托管内存之间的转换的实例讲解

    在本篇文章里小编给大家整理了关于C#托管内存与非托管内存之间的转换的实例以及相关知识点,需要的朋友们学习下。
    2019-08-08
  • Unity3D实现警报灯

    Unity3D实现警报灯

    这篇文章主要为大家详细介绍了Unity3D实现警报灯效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • c#基于winform制作音乐播放器

    c#基于winform制作音乐播放器

    这篇文章主要介绍了c#基于winform制作音乐播放器的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03

最新评论