本文主要介绍基于“确定性神经网络”开发AI对战版井字棋(三连子)的过程,并用开发出的软件进行对战来生成对弈数据,这些数据可用于训练确定性神经网络模型。另外,通过测试发现了一些井字棋的特性和对弈数据的情形。

1. AI对战版井字棋

这是基于MFC对话框开发的神经网络连子棋的一个特定版本,即获胜连子数为3的版本——三连子,而且,是AI与AI对战的版本,不需要人工参与即可进行对弈。

(1)创建项目

运行Visual Studio 2015,选择菜单“文件-->新建-->项目”,在对话框的左侧选择“已安装-->模板-->Visual C++-->MFC”,在右侧选择“MFC应用程序”,并选定项目保存的位置和项目名称(此处项目名为test,保存在桌面),如下图所示:

点击“确定”按钮,在弹出的对话框的左侧选择“应用程序类型”,右侧选择“基于对话框”,并取消“安全开发生命周期(SDL)检查”的选择,详细如下图所示:

点击“完成”按钮,至此完成了项目的创建,显示如下:

(2)界面(GUI)设计

删除中间对话框上已有的“TODO:在此防止对话框控件”控件;从上图右侧“工具箱”中将“Picture Control” 拖拽到中间的对话框上,调整大小,右击该控件,在右键菜单中选择“属性”,在弹出的属性框中找到ID,并将其修改为IDC_BOARD,并调整按钮的大小和位置,如下图:

(3)导入SDK

打开源代码所在的目录,将SDK文件(AIWZQDll.dll、AIWZQDll.lib、Inter.h)拷贝到该目录,如下图:

然后,在解决方案资源管理器中右击test项目,在右键菜单中选择“添加-->现有项” ,在弹出的对话框内选中Inter.h并点击“添加”按钮即可。

(4)初始化神经网络

在解决方案资源管理器中双击testDlg.cpp文件,在显示的代码头部添加以下代码来引入SDK:

#include "Inter.h"
#pragma comment(lib, "AIWZQDll.lib")

显示如下:

在该文件中找到CtestDlg::OnInitDialog()函数,并添加Login()函数和InitFromModelFile()函数的调用来初始化网络模型:

 Login("user", "password");if (!InitFromModelFile("model.mod"))    //使用模型文件初始化InitWithoutModelFile(3, 3, 3);

结果显示如下:

其中的user和password是调用确定性神经网络所使用的用户名和密码,可以在官网www.gnxxkj.com下载客户端软件进行用户注册,并将注册的用户名和密码填至此处。 如果没有神经网络模型,则调用InitWithoutModel()函数来通过“棋盘大小”、“几连子获胜”这样的参数进行初始化(初始化为空的网络),此处代码表示初始化为3x3棋盘上的三连子(井字棋)。

(5)实现“确定”

打开testDlg.h文件,添加如下代码来定义棋盘变量:

CStatic m_objBoard;

在testDlg.cpp文件中找到CtestDlg::DoDataExchange(CDataExchange* pDX)并添加如下代码来将变量m_objBoard的值绑定到ID为IDC_BOARD的控件上显示:

DDX_Control(pDX, IDC_BOARD, m_objBoard);

在前面的界面上找到“确定”按钮,双击该按钮,会自动添加该按钮的单击事件,即CtestDlg::OnBnClickedOk()函数,注释掉该函数内原有的代码,并添加以下代码来初始化游戏数据:

 StartNewGame();DrawBoard(&m_objBoard);SetTimer(1, 10, NULL);

此处代码在初始化游戏数据之后会启动一个定时器,该定时器每10毫秒触发一次,用于AI落子,以此来实现AI对战(无需人工参与的对弈)。

为了配合定时器,需要添加定时器函数,用于实现触发定时器时的操作。首先在testDlg.h文件中添加如下的函数声明:

afx_msg void OnTimer(UINT_PTR nIDEvent);

结果如下图所示:

然后在testDlg.cpp文件中添加该函数的实现:

void CtestDlg::OnTimer(UINT_PTR nIDEvent)
{char strFileName[256] = { 0 };static int nFileIndex = 1;switch (nIDEvent){case 1:if (!SetPieceByAIAndShow(&m_objBoard)){AfxMessageBox(_T("积分不足或网络问题,请确保网络畅通且积分充足(若是积分不足,充值后可继续本次对局)"));return;}if (IsGameOver()){KillTimer(1);if (GetWinner()){sprintf(strFileName, "%d.txt", nFileIndex++);SaveSteps(strFileName);}OnBnClickedOk();}break;case 2:break;}CDialogEx::OnTimer(nIDEvent);
}

该代码表示,当触发1号定时器时,调用SetPieceByAIAndShow()函数进行AI预测和落子,并将结果显示在棋盘上;落子后判断是否游戏结束,若游戏结束了,则停止定时器并保存有效的对弈数据(平局时数据无效,不保存)。

此处要注意的是之后的OnBnClickedOk()函数的调用:若此处不调用该函数,则每次点击“确定”按钮时会进行一局对弈,对弈结束后就会停下,用户可以查看对弈结果;而调用该函数之后,点击“确定”按钮后会持续进行对弈,一局结束会立刻开始新一局,永不停息,用户也无法在界面上查看一局的对弈结果,只能通过保存的数据进行复盘和查看。

结果如下图所示:

最后,在BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)部分添加如下代码来将定时器消息绑定到定时器函数上 :

ON_WM_TIMER()

结果如下图所示:

2. 测试

(1)3x3棋盘

运行程序(点击“确定”按钮只对战一局的版本),点击“确定”按钮,结果如下图所示:

运行连续开始新局对弈的AI对战版本,很快我们就生成了数千个数据文件,即进行了数千局的对弈,但是,经过筛选,过滤掉相同的对弈数据之后,仅剩余了13个数据文件,如下图所示:

这表明,对于3x3棋盘上的井字棋而言,13局对弈后神经网络就趋于稳定了,而且先落子者几乎不会输(可能赢,也可能平局)。

(2)15x15棋盘

将棋盘大小初始化为15x15,并进行测试,首局的结果如下所示:

但是,进行几局之后会发现,棋局固定在了一种情形,如下所示:

每次点击“确定”按钮得到的都是这个棋局,这说明,神经网络模型已经形成了定式,和前面的3x3的棋盘上的结果一致,区别仅是定式棋局和到达定式的时间。

(3)对弈分析

若想获得更多有效数据,可以在对战中只设定一方由神经网络进行预测和落子,另一方则自己编写代码进行落子(例如随机落子),有兴趣的可以自行尝试,或可得出不一样的结果。

总的来说,不管过程如何,最终学到的确定性神经网络模型会很快达到稳定,之后几乎不再增长;而且,通过测试分析,我们也不难发现,在井字棋中,先手的优势非常明显。

3. 完整代码

(1)文中所提的SDK(及案例的完整代码)可在如下地址下载

官网下载:www.gnxxkj.com

github下载:https://github.com/wangdechang119

gitlab下载:https://gitlab.com/wangdechang119

gitee下载:https://gitee.com/wangdechang119

(2)本例代码


// testDlg.h : 头文件
//#pragma once// CtestDlg 对话框
class CtestDlg : public CDialogEx
{
// 构造
public:CtestDlg(CWnd* pParent = NULL); // 标准构造函数// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_TEST_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnBnClickedOk();afx_msg void OnTimer(UINT_PTR nIDEvent);DECLARE_MESSAGE_MAP()public:CStatic m_objBoard;
};

// testDlg.cpp : 实现文件
//#include "stdafx.h"
#include "test.h"
#include "testDlg.h"
#include "afxdialogex.h"#include "Inter.h"
#pragma comment(lib, "AIWZQDll.lib")#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CtestDlg 对话框CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/): CDialogEx(IDD_TEST_DIALOG, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CtestDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_BOARD, m_objBoard);
}BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDOK, &CtestDlg::OnBnClickedOk)ON_WM_TIMER()
END_MESSAGE_MAP()// CtestDlg 消息处理程序BOOL CtestDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);           // 设置大图标SetIcon(m_hIcon, FALSE);        // 设置小图标// TODO: 在此添加额外的初始化代码Login("user", "password");if (!InitFromModelFile("model.mod"))   //使用模型文件初始化InitWithoutModelFile(15,15, 3);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CtestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CtestDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CtestDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CtestDlg::OnBnClickedOk()
{//CDialogEx::OnOK();StartNewGame();DrawBoard(&m_objBoard);SetTimer(1, 10, NULL);
}void CtestDlg::OnTimer(UINT_PTR nIDEvent)
{char strFileName[256] = { 0 };static int nFileIndex = 1;switch (nIDEvent){case 1:if (!SetPieceByAIAndShow(&m_objBoard)){AfxMessageBox(_T("积分不足或网络问题,请确保网络畅通且积分充足(若是积分不足,充值后可继续本次对局)"));return;}if (IsGameOver()){KillTimer(1);if (GetWinner()){sprintf(strFileName, "%d.txt", nFileIndex++);SaveSteps(strFileName);}//OnBnClickedOk();}break;case 2:break;}CDialogEx::OnTimer(nIDEvent);
}

神经网络井字棋AI对战版的开发与测试相关推荐

  1. java 井字棋 人机_井字棋(人机对战版)

    1 #include 2 #include 3 4 const int ROW = 3;5 const int COL = 3;6 intchessboard[ROW][COL];7 intscore ...

  2. 利用Minmax搜索设计井字棋AI(python)(带UI)

    利用Minmax搜索设计井字棋AI(python)(带UI) 博弈无处不在,对抗搜索也是人工智能领域一个热点话题,而Minmax搜索也是最基础的对抗搜索方法.闲暇之余小编利用Minmax对抗搜索方法做 ...

  3. python井字棋ai,python 井字棋(Tic Tac Toe)

    说明 用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意.另外,90%+的代码也是本人逐字逐句敲的. minimax算法还没完全理解,所以参考了这里的代码,并作了修改. 特点 可以选 ...

  4. java井字棋ai_简单的井字棋 AI DEMO | Minimax 算法

    在"类与对象"实训课上,有一道附加题让我们用 OOP 做一个的井字棋模拟程序,要求中电脑是随机落子的,这样显然不是很优雅.回忆起以前学的对抗搜索(这里叫 MaxMin 算法),我继 ...

  5. [游戏学习22] MFC 井字棋 双人对战

    >_<:太多啦,感觉用英语说的太慢啦,没想到一年做的东西竟然这么多.....接下来要加速啦! >_<:注意这里必须用MFC和前面的Win32不一样啦! >_<:这也 ...

  6. C++游戏game | 井字棋游戏坤坤版(配资源+视频)【赋源码,双人对战】

    博主主页:Yu·仙笙

  7. 第6-3课:博弈树与井字棋(Tic-Tac-Toe)

    上一课简单介绍了博弈树,从编程实现算法的角度看,博弈树是三种树中最简单的一种,无论是原理还是实现都不复杂.这一课,我们就以简单的井字棋(Tic-Tac-Toe)游戏为例,介绍一下如何用博弈树实现一个简 ...

  8. 通过游戏编程学Python(7)— 井字棋(下)

    通过游戏编程学Python 通过游戏编程学Python(7)- 井字棋(上) 通过游戏编程学Python(番外篇)- 单词小测验 通过游戏编程学Python(6)- 英汉词典.背单词 文章目录 通过游 ...

  9. java井字游戏_java井字棋源代码(双人对战版)

    [实例简介] [实例截图] [核心代码] package com.pan.ttt; import java.awt.*; import java.awt.event.*; import javax.s ...

  10. Tic-Tac-Toe游戏简介(AI井字棋游戏)

    本章游戏项目将介绍如何使用AI(Artificial Intelligence,人工智能)来创建计算机对手.在该游戏中,玩家和计算机进行一场高赌注的人机Tic-Tac-Toe决战.计算机的棋艺令人生畏 ...

最新文章

  1. 自己动手实现操作系统引导程序(OS bootloader)——借助QEMU/GDB/losetup/dd等工具
  2. MVC 3.0 Html.ActionLink
  3. android学习的一点点网站资料
  4. 上周并发题的解题思路以及介绍Go语言调度器
  5. yield return 和 Func
  6. 简单的ideatomcat热加载
  7. html js input fileupload,简单 js fileUpload控件
  8. 看单片机原理图-外部FLASHW25Q64
  9. 圆跳动基础知识(几何公差)
  10. java调用手机截屏_android实现手机截屏并保存截图功能
  11. android BKS
  12. Bit-M Accelerator全新上线
  13. 在线网络打字系统_打字比赛系统软件
  14. 【JavaSE系列】基础经典编程题
  15. 小米商城网页制作大全之搜索引擎(input,Font Awesome)
  16. (36个知识点)关于《浏览器基本原理与实践》的读后总结
  17. Legacy引导转UEFI引导(BIOS、Legacy引导、UEFI引导、GPT/MBR分区)
  18. java-net-php-python-jspm购物商城网站演示录像2019计算机毕业设计程序
  19. 武汉防水资质办理-办理全流程解析
  20. 财政收入的各种统计口径

热门文章

  1. Python爬取网易云音乐歌手歌曲和歌单!推荐好听的歌吗?
  2. 【搜索排序】预训练综述Pre-training Methods in Information Retrieval
  3. 快手,抖音,美拍打造个人IP精准引流!
  4. 前端找实习岗的7条建议
  5. 2022/12/11创建openai账号(chatgpt)
  6. R语言【箱线图和茎叶图】
  7. 怎么把蓝狐上的代码转为html,Ajax动态调用用户控件输出html
  8. Macintosh30周年回顾视频 ---转自36kr
  9. 电脑调分辨率黑屏了怎么办_调显示器分辨率黑屏怎么办
  10. 慕课网-哒哒租车系统