博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个扫雷游戏和一个自动玩扫雷游戏的程序
阅读量:4561 次
发布时间:2019-06-08

本文共 3234 字,大约阅读时间需要 10 分钟。

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

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

    源码下载地址:

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

 

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%,智能程度还不错,比一般人玩的好,无聊时可以看它玩一天。

 

转载于:https://www.cnblogs.com/seabluescn/p/10522627.html

你可能感兴趣的文章
Solr6.5与mysql集成建立索引
查看>>
.NET 4.0中的缓存功能
查看>>
Jfinal 使用 JsonKit 转换不了问题
查看>>
canvas sprite动画 简单封装
查看>>
CentOS 64位 codeblocks安装
查看>>
Hibernate4实战 之 第二部分:Hibernate的基本配置
查看>>
02-CSS基础与进阶-day4_2018-08-31-20-42-09
查看>>
PHP中对数组进行操作的常用函数总结
查看>>
Prometheus(2)
查看>>
sublime text3 常用配置
查看>>
Python爬虫实践~BeautifulSoup+urllib+Flask实现静态网页的爬取
查看>>
debian安装tftp服务
查看>>
python zeros用法实例
查看>>
C语言(第十章):文件操作
查看>>
Donet.HighCharts
查看>>
CSS3动画库animate.css
查看>>
Type类型详解
查看>>
C#面向对象(一)
查看>>
Excel 求差集和并集
查看>>
设计抗住千万级流量的架构思路
查看>>