标题:
扫雷AI核心代码(不读内存完全拟人按数字逻辑去解)
[打印本页]
作者:
liuyy
时间:
2015-1-11 19:53
标题:
扫雷AI核心代码(不读内存完全拟人按数字逻辑去解)
这是扫雷算法的后台数据处理,前台的模拟按键和读棋盘信息由按键精灵完成
解决了一个大家写com组件时不能以数组做参数或返回值的难题
至于怎么处理的方法全在源码中就不解释了
/*********************************************************************
欢迎您为按键精灵制作插件!
这是按键精灵的插件模板 091026版
请编译Release版的插件使用,Debug版的插件会导致按键精灵出现异常错误
如果有其他问题,欢迎通过以下方式和我们取得联系
Email: hi@vrbrothers.com
论坛: bbs.ajjl.cn
插件模板更新记录:
091026
解决由于MFC的功能不完善导致所有的插件函数都在主线程中执行的问题。
这个问题会导致插件效率低下,而且可能互相阻塞,甚至阻塞主线程。
*********************************************************************/
#include "stdafx.h"
#include "CQMPlugin.h"
#include "QMLibraryStub.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_MESSAGE_MAP(CQMPlugin, CCmdTarget)
//{{AFX_MSG_MAP(CQMPlugin)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#ifdef _DEBUG
#pragma comment(lib,"CommonLibD.lib")
#else
#pragma comment(lib,"CommonLib.lib")
#endif
BEGIN_DISPATCH_MAP(CQMPlugin, CCmdTarget)
DISP_FUNCTION(CQMPlugin, "Get_Plugin_Description", GetPluginDescription, VT_BSTR, VTS_BSTR)
DISP_FUNCTION(CQMPlugin, "Get_Plugin_Interpret_Template", GetPluginInterpretTemplate, VT_BSTR, VTS_BSTR)
//{{AFX_DISPATCH_MAP(CQMPlugin)
DISP_FUNCTION(CQMPlugin, "tishi", tishi, VT_EMPTY, VTS_BSTR)
DISP_FUNCTION(CQMPlugin, "leigeset", leigeset, VT_EMPTY, VTS_I4 VTS_I4 VTS_I4)
DISP_FUNCTION(CQMPlugin, "leigeget", leigeget, VT_I4, VTS_I4 VTS_I4)
DISP_FUNCTION(CQMPlugin, "leizhengjs", leizhengjs, VT_EMPTY, VTS_NONE)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
IMPLEMENT_OLECREATE(CQMPlugin, "QMPlugin.saoleiDLL", 0x1117E497, 0x126E, 0x4FC8, 0xB4, 0x30, 0x1C, 0x61, 0x43, 0x48, 0x4A, 0xA9)
BOOL g_bEnablePluginValidate = TRUE;
/*********************************************************************
按键精灵的每个插件可以支持若干条命令。
如果您需要写一条自己的命令,需要遵循以下步骤:
1. 打开文件CQMPlugin.cpp,就是您现在看到的这个文件
2. 在Visual C++ 6.0的菜单中选择 View->ClassWizard
3. 在弹出的对话框中选择Automation面板,按Add Method按钮
4. 依次填写您的插件函数的名字、返回类型和参数类型
需要注意的是,如果返回值是字符串类型,请选择BSTR
如果参数是字符串类型,请选择LPCTSTR
如果需要传地址的参数(可用于返回多个值),参数类型请选择VARIANT*,如下面的GetScreenResolution插件函数所示
5. 按OK按钮,您会看到CQMPlugin.cpp有了一个空白的函数,您只需要填写函数功能即可
6. 您也可以在Automation面板中选择删除某个已有的函数,并同时在下面的程序中删除对应的函数体
7. 在下面的m_DescriptionList表格中填写您的插件说明和函数说明
8. 编译形成DLL文件,把DLL文件放在按键精灵的Plugin目录下
9. 打开按键精灵,进入编辑脚本界面,打开“插件命令”面板,编写脚本测试你的插件!
*********************************************************************/
/*********************************************************************
* 名称:m_DescriptionList
* 你可以把它看成一个表格,表格中的每一行代表了一条插件命令。
* 每行第一个字符串是插件命令的名字(如果为空,则代表整个插件);第二个字符串是这条插件命令的解释;
* 第三个字符串是插件命令的显示模板信息,其中的$1 $2 ... 等内容在显示时将用第一个参数、第二个参数、... 代替
* 当你需要新增一条插件命令的时候,就需要在表格里面加一行。
*********************************************************************/
CQMPlugin::DESCRIPTION_LIST CQMPlugin::m_DescriptionList[] =
{
{"","扫雷算法",""},
{"tishi","弹窗提示","提示内容"},
{"leigeset","设置雷格状态","雷格Y坐标雷格X坐标雷格状态值"},
{"leigeget","返回雷格状态","雷格Y坐标雷格X坐标"},
{"leizhengjs","计算雷阵信息返回能翻开的雷格坐标",""},
};
//这行您不需要修改
const int CQMPlugin::m_iDescriptionListSize = sizeof(CQMPlugin::m_DescriptionList) / sizeof(CQMPlugin::DESCRIPTION_LIST);
/*********************************************************************
* 下面是各个插件命令的处理函数,函数名和插件名是对应的。
* 如果要增加一个插件命令,通常Visual C++会帮您写一个空的处理函数
* 如果要删除一个插件命令,别忘了把对应的处理函数也一起删掉。
*********************************************************************/
/*********************************************************************
* 下面是公共处理函数。
* OnLoad 函数会在插件被加载时调用,返回值通常为TRUE。如果返回FALSE,表示插件拒绝被加载
* OnLoad 函数的第一个参数表示加载动态链接库的Instance Handle,第二个参数暂时保留
* OnExit 函数会在插件被卸载是调用,没有返回值
*********************************************************************/
BOOL OnLoad(HMODULE hModule, int iReserved)
{
return TRUE;
}
void OnExit()
{
return;
}
//////////////////////////////////////////////////////////////////////
// 扫雷算法插件
// BY:DEBUG 2014/9/12
//////////////////////////////////////////////////////////////////////
void CQMPlugin::tishi(LPCTSTR str)
{
//提供一个弹窗口提示方法
AfxMessageBox(str);
}
//////////////////////////////////////////////////////////////////////
long leizheng[16][30]; //保存雷阵输入信息的全局变量
long leizhengout[16][30];//保存计算后雷阵的输出信息
/////////////////////////////////////////////////////////////////////
void CQMPlugin::leigeset(long Y, long X, long zhi)
{
// 提供设置雷格信息的方法
leizheng[Y][X]=zhi;
}
//////////////////////////////////////////////////////////////////////
long CQMPlugin::leigeget(long Y, long X)
{
// 提供返回计算后的雷格信息的方法 88表示能翻开 44表示确定为雷格提示标记 0不做任何操作
// 必须先调用计算雷阵方法后再掉用这个方法
return leizhengout[Y][X];
}
//////////////////////////////////////////////////////////////////////
void CQMPlugin::leizhengjs()
{
// 提供一个雷阵信息计算的方法,在对象获取玩所有雷格信息后才能调用此方法
long i;
long j;
for(i=0;i<16;i++)
for(j=0;j<30;j++)
{
//清零输出数组
leizhengout[i][j]=0;
}
//开始判定翻开与否
for(i=0;i<16;i++)
for(j=0;j<30;j++)
{
if(i>=1&&j>=1&&i<=14&&j<=28)
{
//不是边界上的4行
long leibiao=0;//周边已经确定的地雷个数
//统计九宫格内地雷的个数
if(leizheng[i-1][j-1]==9) leibiao++;//左上
if(leizheng[i-1][j]==9) leibiao++;//上
if(leizheng[i-1][j+1]==9) leibiao++;//右上
if(leizheng[i][j-1]==9) leibiao++;//左
if(leizheng[i][j+1]==9) leibiao++;//右
if(leizheng[i+1][j-1]==9) leibiao++;//左下
if(leizheng[i+1][j]==9) leibiao++;//下
if(leizheng[i+1][j+1]==9) leibiao++;//左下
long hei=0;//周边未翻开的雷格数
//统计九宫格内未翻开的雷格数
if(leizheng[i-1][j-1]==10) hei++;//左上
if(leizheng[i-1][j]==10) hei++;//上
if(leizheng[i-1][j+1]==10) hei++;//右上
if(leizheng[i][j-1]==10) hei++;//左
if(leizheng[i][j+1]==10) hei++;//右
if(leizheng[i+1][j-1]==10) hei++;//左下
if(leizheng[i+1][j]==10) hei++;//下
if(leizheng[i+1][j+1]==10) hei++;//左下
////////////////////////////////////////////////
if(leizheng[i][j]==1&&hei==1)
{
//周围只有一个雷且周围只剩一个未翻开的雷格确定一个地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==1&&leibiao==1)
{
//周围只有一个雷且周围已经标记了一个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////
if((leizheng[i][j]==2&&hei==2&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有2个雷且周围只剩2个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==2&&leibiao==2)
{
//周围只有2个雷且周围已经标记了2个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////////
if((leizheng[i][j]==3&&hei==3&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有3个雷且周围只剩3个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==3&&leibiao==3)
{
//周围只有3个雷且周围已经标记了3个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////////
if((leizheng[i][j]==4&&hei==4&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有4个雷且周围只剩4个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==4&&leibiao==4)
{
//周围只有4个雷且周围已经标记了4个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////////
if((leizheng[i][j]==5&&hei==5&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有5个雷且周围只剩5个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==5&&leibiao==5)
{
//周围只有5个雷且周围已经标记了5个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////////
if((leizheng[i][j]==6&&hei==6&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有6个雷且周围只剩6个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==6&&leibiao==6)
{
//周围只有6个雷且周围已经标记了6个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
////////////////////////////////////////////////////////////////////
if((leizheng[i][j]==7&&hei==7&&leibiao==0)||(leizheng[i][j]==(leibiao+hei)))
{
//周围只有7个雷且周围只剩7个未翻开的雷格,或者周围未翻开和已经标记为地雷的和等于雷格状态值则确定一组地雷并在输出数组中做标记
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=44;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=44;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=44;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=44;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=44;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=44;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=44;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=44;//左下
}
if(leizheng[i][j]==7&&leibiao==7)
{
//周围只有7个雷且周围已经标记了7个地雷就把周围其它未翻开的雷格翻开
if(leizheng[i-1][j-1]==10) leizhengout[i-1][j-1]=88;//左上
if(leizheng[i-1][j]==10) leizhengout[i-1][j]=88;//上
if(leizheng[i-1][j+1]==10) leizhengout[i-1][j+1]=88;//右上
if(leizheng[i][j-1]==10) leizhengout[i][j-1]=88;//左
if(leizheng[i][j+1]==10) leizhengout[i][j+1]=88;//右
if(leizheng[i+1][j-1]==10) leizhengout[i+1][j-1]=88;//左下
if(leizheng[i+1][j]==10) leizhengout[i+1][j]=88;//下
if(leizheng[i+1][j+1]==10) leizhengout[i+1][j+1]=88;//左下
}
}
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1