本篇继续上篇的未完部分。前面介绍完了软件的背景、设计、实现,本篇主要做一些总结。
4. 测试
前面已经完成了编码工作,可以运行起来进行测试:
选择相应的评估等级,然后点击“开始评测”按钮:
输入用户名和密码并点击“登录”按钮进行登录,用户名和密码如果没有的话,可以点击“注册”按钮先注册用户,然后再登录。登录成功后即可正式开始评测:
当本局对弈结束后可点击“开始新游戏”进入下一局,若感觉本局无望获胜也可点击“开始新游戏”按钮来放弃本局并直接进入下一局 。
5. 文中所提的SDK(及案例的完整代码)可在如下地址下载:
官网下载:www.gnxxkj.com
github下载:https://github.com/wangdechang119
gitlab下载:https://gitlab.com/wangdechang119
gitee下载:https://gitee.com/wangdechang119
6. 完整代码如下
// testDlg.h : 头文件
//
#pragma once
// CtestDlg 对话框
class CtestDlg : public CDialogEx
{
// 构造
public:
CtestDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TEST_DIALOG };
#endif
protected:
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 OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedBtnStart();
afx_msg void OnBnClickedBtnNew();
afx_msg void OnCbnSelchangeLevel();
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
public:
void Show();
void ShowResult(); //显示评估结果
void ShowWin(); //显示胜负
void ShowGameOver(); //显示游戏结束
public:
CStatic m_objBoard; //画图控件
CComboBox m_objLevel; //用于选择“评估等级”的下拉框
int m_nCurSel; //当前选中的等级索引
bool m_bLogged; //是否已登录
bool m_bStarted; //游戏是否已经开始
bool m_bHumanPlay; //是否该人/挑战者落子
int m_nNumTotal; //五子棋水平等级评估时的总局数:即每次评估需和AI对战m_nNumTotal局
int m_nNumLeft; //剩余局数
int m_nNumWin; //已胜的局数
int m_nDepth; //思维深度:N等级对应的标准深度为2N(合格,6),7和8为2N+1,9和10为2N+2,3、4、5为2N-1,0、1、2为2N-2
double m_fConcern; //专注度:百分比,参考基准为10局对弈中AI总耗时,人工总耗时/AI总耗时>=1时专注度100%,向下需考虑等级难度
};
// testDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "test.h"
#include "testDlg.h"
#include "afxdialogex.h"
#include "Login.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include "Inter.h"
#pragma comment(lib, "AIWZQDll.lib")
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
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_LEVEL, m_objLevel);
DDX_Control(pDX, IDC_BOARD, m_objBoard);
}
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
ON_BN_CLICKED(IDC_BTN_START, &CtestDlg::OnBnClickedBtnStart)
ON_BN_CLICKED(IDC_BTN_NEW, &CtestDlg::OnBnClickedBtnNew)
ON_CBN_SELCHANGE(IDC_LEVEL, &CtestDlg::OnCbnSelchangeLevel)
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
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: 在此添加额外的初始化代码
if (!InitFromModelFile("model.mod")) //使用模型文件初始化
{
AfxMessageBox(_T("找不到网络模型,请确定考评用的标准模型存在且未经擅自修改"));
PostQuitMessage(0);
}
GetDlgItem(IDC_BTN_START)->EnableWindow(true);
GetDlgItem(IDC_BTN_NEW)->EnableWindow(false);
GetDlgItem(IDC_NUM_TOTAL)->SetWindowTextW(_T("10"));
GetDlgItem(IDC_NUM_LEFT)->SetWindowTextW(_T("10"));
GetDlgItem(IDC_RATIO)->SetWindowTextW(_T("0/10"));
GetDlgItem(IDC_DEPTH)->SetWindowTextW(_T(""));
GetDlgItem(IDC_CONCERN)->SetWindowTextW(_T(""));
m_objLevel.InsertString(0, _T("一级"));
m_objLevel.InsertString(1, _T("二级"));
m_objLevel.InsertString(2, _T("三级"));
m_objLevel.InsertString(3, _T("四级"));
m_objLevel.InsertString(4, _T("五级"));
m_objLevel.InsertString(5, _T("六级"));
m_objLevel.InsertString(6, _T("七级"));
m_objLevel.InsertString(7, _T("八级"));
m_objLevel.InsertString(8, _T("九级"));
m_objLevel.InsertString(9, _T("十级"));
m_nCurSel = 0;
m_objLevel.SetCurSel(m_nCurSel);
m_bLogged = false;
m_bStarted = false;
m_bHumanPlay = false;
m_nNumTotal = 10;
m_nNumLeft = 10;
m_nNumWin = 0;
m_nDepth = -1;
m_fConcern = -1.;
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();
Show();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CtestDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CtestDlg::Show()
{
CRect rect; //对话框区域大小
CRect rc; //按钮区域大小
CRect rc2; //文本标签区域大小
CRect rc3; //复选框区域大小
GetClientRect(&rect);
CWnd* pBtn = GetDlgItem(IDC_BTN_START);
if (pBtn != NULL)
{
pBtn->GetClientRect(&rc);
GetDlgItem(IDC_LB_LEVEL)->GetClientRect(&rc2);
GetDlgItem(IDC_LEVEL)->GetClientRect(&rc3);
CRect rcd; //调整后的按钮区域大小、文本标签区域大小
rcd.left = rect.right - rc.Width()*1.25;
rcd.right = rcd.left + rc.Width();
rcd.top = rc.Height();
rcd.bottom = rcd.top + rc.Height();
pBtn->MoveWindow(&rcd); //开始评测按钮
rcd.top = rcd.bottom + rc.Height()*0.5;
rcd.bottom = rcd.top + rc.Height();
GetDlgItem(IDC_BTN_NEW)->MoveWindow(&rcd); //开始新游戏按钮
rcd.top = rcd.bottom + rc.Height();
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_LEVEL)->MoveWindow(&rcd); //评估等级标签
CRect rcd2; //调整后的值标签区域大小
rcd2.left = rcd.left + rcd.Width()*0.2;
rcd2.right = rcd2.left + rc3.Width();
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc3.Height();
GetDlgItem(IDC_LEVEL)->MoveWindow(&rcd2); //评估等级复选框
rcd.top = rcd2.bottom + rcd.Height()*0.5;
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_NUM_TOTAL)->MoveWindow(&rcd); //评估局数标签
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc2.Height();
GetDlgItem(IDC_NUM_TOTAL)->MoveWindow(&rcd2); //评估局数值
rcd.top = rcd2.bottom + rcd.Height()*0.5;
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_NUM_LEFT)->MoveWindow(&rcd); //剩余局数标签
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc2.Height();
GetDlgItem(IDC_NUM_LEFT)->MoveWindow(&rcd2); //剩余局数值
rcd.top = rcd2.bottom + rcd.Height()*0.5;
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_RATIO)->MoveWindow(&rcd); //胜率标签
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc2.Height();
GetDlgItem(IDC_RATIO)->MoveWindow(&rcd2); //胜率值
rcd.top = rcd2.bottom + rcd.Height()*0.5;
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_DEPTH)->MoveWindow(&rcd); //思维深度标签
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc2.Height();
GetDlgItem(IDC_DEPTH)->MoveWindow(&rcd2); //思维深度值
rcd.top = rcd2.bottom + rcd.Height()*0.5;
rcd.bottom = rcd.top + rc2.Height();
GetDlgItem(IDC_LB_CONCERN)->MoveWindow(&rcd); //专注度标签
rcd2.top = rcd.bottom + rcd.Height()*0.4;
rcd2.bottom = rcd2.top + rc2.Height();
GetDlgItem(IDC_CONCERN)->MoveWindow(&rcd2); //专注度值
}
rect.right -= rc.Width()*1.5;
CWnd* pBoard = GetDlgItem(IDC_BOARD);
if (pBoard != NULL)
pBoard->MoveWindow(&rect); //棋盘区域
DrawBoard(&m_objBoard); //绘制棋盘
DrawPieces(&m_objBoard); //绘制棋子
}
void CtestDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
Show();
}
void CtestDlg::OnBnClickedBtnStart()
{
if (!m_bLogged) //判断是否已有用户登录
{
CLogin objLogin;
if (objLogin.DoModal() != IDOK)
{
MessageBox(_T("请先登录"), _T("温馨提醒"));
return;
}
m_bLogged = true;
}
char strTemp[10] = { 0 };
m_nNumLeft = m_nNumTotal;
sprintf(strTemp, "%d", m_nNumLeft);
SetDlgItemText(IDC_NUM_LEFT, CA2CT(strTemp)); //重置剩余局数
m_nNumWin = 0;
sprintf(strTemp, "%d/%d", m_nNumWin, m_nNumTotal);
SetDlgItemText(IDC_RATIO, CA2CT(strTemp)); //重置胜率
m_nDepth = -1;
m_fConcern = -1.;
SetDlgItemText(IDC_DEPTH, _T("")); //重置思维深度
SetDlgItemText(IDC_CONCERN, _T("")); //重置专注度
GetDlgItem(IDC_BTN_START)->EnableWindow(false);
GetDlgItem(IDC_BTN_NEW)->EnableWindow(true);
StartNewGame();
Invalidate(TRUE);
m_bStarted = true;
m_bHumanPlay = true; //被测者(人)先落子
}
void CtestDlg::OnBnClickedBtnNew()
{
m_nNumLeft -= m_bStarted ? 1 : 0; //直接放弃当前未结束的局时减1,若当前局已结束则开始新局不再减1(因为在一局结束时已经减过了)
char strTemp[10] = { 0 };
sprintf(strTemp, "%d", m_nNumLeft);
SetDlgItemText(IDC_NUM_LEFT, CA2CT(strTemp)); //更新剩余局数
if (m_nNumLeft <= 1) //还剩最后一局
{
GetDlgItem(IDC_BTN_NEW)->EnableWindow(false);
}
StartNewGame();
Invalidate(TRUE);
m_bStarted = true;
m_bHumanPlay = true;
}
void CtestDlg::OnCbnSelchangeLevel()
{
int nCurSel = m_objLevel.GetCurSel();
if (nCurSel == m_nCurSel)
return;
if (m_bStarted && MessageBox(_T("确定要更换评测等级重新进行评测吗?这将会中止当前的操作"), _T("温馨提示"), MB_OKCANCEL) == IDCANCEL)
{
m_objLevel.SetCurSel(m_nCurSel);
return; //选择了取消更换
}
m_nCurSel = nCurSel;
SetLayers4Pred((m_nCurSel + 1) * 2); //第N等级:设置为使用2N层网络;即一级、二级、三级等依次使用两层、四层、六层等网络
char strTemp[10] = { 0 };
m_nNumLeft = m_nNumTotal;
sprintf(strTemp, "%d", m_nNumLeft);
SetDlgItemText(IDC_NUM_LEFT, CA2CT(strTemp)); //重置剩余局数
m_nNumWin = 0;
sprintf(strTemp, "%d/%d", m_nNumWin, m_nNumTotal);
SetDlgItemText(IDC_RATIO, CA2CT(strTemp)); //重置胜率
m_nDepth = -1;
m_fConcern = -1.;
SetDlgItemText(IDC_DEPTH, _T("")); //重置思维深度
SetDlgItemText(IDC_CONCERN, _T("")); //重置专注度
GetDlgItem(IDC_BTN_START)->EnableWindow(true); //启用“开始评测”按钮
GetDlgItem(IDC_BTN_NEW)->EnableWindow(false); //禁用“开始新游戏”按钮
m_bStarted = false;
}
BOOL CtestDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
CPoint pos;
GetCursorPos(&pos); //在整个屏幕上的坐标
CRect rc;
GetDlgItem(IDC_BOARD)->GetWindowRect(&rc); //在整个屏幕上的坐标
if (rc.PtInRect(pos))
{
if (m_bStarted && m_bHumanPlay)
{
SetCursor(LoadCursor(NULL, IDC_HAND)); //设置成手状
}
else
{
SetCursor(LoadCursor(NULL, IDC_NO)); //设置成禁用
}
return TRUE;
}
return CDialogEx::OnSetCursor(pWnd, nHitTest, message);
}
void CtestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rect;
m_objBoard.GetClientRect(&rect);
if (rect.PtInRect(point))
{
if (!m_bStarted)
{
if (m_nNumLeft == m_nNumTotal)
MessageBox(_T("请先点击开始评测按钮"), _T("温馨提示"), MB_OK | MB_ICONHAND);
else
MessageBox(_T("请先点击开始新游戏按钮"), _T("温馨提示"), MB_OK | MB_ICONHAND);
}
else if (m_bHumanPlay)
{
if (SetPieceWithGUI(&m_objBoard, point.x, point.y))
{
m_bHumanPlay = false;
if (IsGameOver())
{
ShowGameOver();
}
else
{
if (!SetPieceByAIAndShow(&m_objBoard))
{
AfxMessageBox(_T("积分不足或网络问题,请确保网络畅通且积分充足(若是积分不足,充值后可继续本次对局)"));
}
else
{
m_bHumanPlay = true;
if (IsGameOver())
{
ShowGameOver();
}
}
}
}
}
}
CDialogEx::OnLButtonDown(nFlags, point);
}
void CtestDlg::ShowResult()
{
switch (m_nNumWin)
{
case 0:
case 1:
case 2:
MessageBox(_T("不合格!建议去更低一级评估"), _T("评估结束"), MB_OK | MB_ICONINFORMATION);
m_nDepth = (m_nCurSel + 1) * 2 - 2;
break;
case 3:
case 4:
case 5:
MessageBox(_T("不合格!"), _T("评估结束"), MB_OK | MB_ICONINFORMATION);
m_nDepth = (m_nCurSel + 1) * 2 - 1;
break;
case 6:
MessageBox(_T("合格!"), _T("评估结束"), MB_OK | MB_ICONINFORMATION);
m_nDepth = (m_nCurSel + 1) * 2;
break;
case 7:
case 8:
MessageBox(_T("良好!"), _T("评估结束"), MB_OK | MB_ICONINFORMATION);
m_nDepth = (m_nCurSel + 1) * 2 + 1;
break;
case 9:
case 10:
MessageBox(_T("优秀!建议去更高一级评估"), _T("评估结束"), MB_OK | MB_ICONINFORMATION);
m_nDepth = (m_nCurSel + 1) * 2 + 2;
break;
}
}
void CtestDlg::ShowWin()
{
switch (GetWinner())
{
case 1:
MessageBox(_T("很遗憾,您输了"), _T("温馨提示"), MB_OK | MB_ICONINFORMATION);
break;
case -1:
m_nNumWin++;
MessageBox(_T("恭喜,您赢了"), _T("温馨提示"), MB_OK | MB_ICONINFORMATION);
break;
default: //0
AfxMessageBox(_T("平局"));
break;
}
}
void CtestDlg::ShowGameOver()
{
m_bStarted = false; //本次对弈结束
m_nNumLeft--; //本次对弈已结束,剩余局数减一
ShowWin(); //显示本局的输赢,并重新计算获胜局数
char strTemp[10] = { 0 };
sprintf(strTemp, "%d", m_nNumLeft);
SetDlgItemText(IDC_NUM_LEFT, CA2CT(strTemp)); //更新剩余局数
sprintf(strTemp, "%d/%d", m_nNumWin, m_nNumTotal);
SetDlgItemText(IDC_RATIO, CA2CT(strTemp)); //更新胜率
if (m_nNumLeft <= 0)
{
ShowResult(); //评估思维深度并显示结果
sprintf(strTemp, "%d 层", m_nDepth);
SetDlgItemText(IDC_DEPTH, CA2CT(strTemp)); //更新思维深度
GetDlgItem(IDC_BTN_START)->EnableWindow(true); //启用开始评测
}
}
#pragma once
//Login.h
// CLogin 对话框
class CLogin : public CDialogEx
{
DECLARE_DYNAMIC(CLogin)
public:
CLogin(CWnd* pParent = NULL); // 标准构造函数
virtual ~CLogin();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG1 };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
afx_msg void OnBnClickedBtnLogin();
afx_msg void OnBnClickedBtnRegist();
DECLARE_MESSAGE_MAP()
public:
CEdit m_objEditLoginName;
CEdit m_objEditLoginPassword;
};
// Login.cpp : 实现文件
//
#include "stdafx.h"
#include "test.h"
#include "Login.h"
#include "afxdialogex.h"
#include "Inter.h"
#pragma comment(lib, "AIWZQDll.lib")
// CLogin 对话框
IMPLEMENT_DYNAMIC(CLogin, CDialogEx)
CLogin::CLogin(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_DIALOG1, pParent)
{
}
CLogin::~CLogin()
{
}
void CLogin::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_USER, m_objEditLoginName);
DDX_Control(pDX, IDC_PASSWORD, m_objEditLoginPassword);
}
BEGIN_MESSAGE_MAP(CLogin, CDialogEx)
ON_BN_CLICKED(IDOK, &CLogin::OnBnClickedBtnLogin)
ON_BN_CLICKED(IDC_BTN_REGIST, &CLogin::OnBnClickedBtnRegist)
END_MESSAGE_MAP()
// CLogin 消息处理程序
BOOL CLogin::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_objEditLoginName.SetLimitText(32);
m_objEditLoginPassword.SetLimitText(32);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CLogin::OnBnClickedBtnLogin()
{
CString strName, strPsw;
m_objEditLoginName.GetWindowText(strName);
m_objEditLoginPassword.GetWindowText(strPsw);
strName.Trim();
strPsw.Trim();
if (strName.IsEmpty() || strName.Find(_T("&")) >= 0 || strName.Find(_T("=")) >= 0 || strName.Find(_T("+")) >= 0)
{
MessageBox(_T("用户名错误"), _T("温馨提示"), MB_OK | MB_ICONINFORMATION);
return;
}
if (strPsw.IsEmpty() || strPsw.Find(_T("&")) >= 0 || strPsw.Find(_T("=")) >= 0 || strPsw.Find(_T("+")) >= 0)
{
MessageBox(_T("密码错误"), _T("温馨提示"), MB_OK | MB_ICONINFORMATION);
return;
}
char cstrName[255] = { 0 };
char cstrPsw[255] = { 0 };
int nLen = 0;
nLen = WideCharToMultiByte(CP_ACP, 0, strName, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, strName, -1, cstrName, nLen, NULL, NULL);
nLen = WideCharToMultiByte(CP_ACP, 0, strPsw, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, strPsw, -1, cstrPsw, nLen, NULL, NULL);
if (!Login(cstrName, cstrPsw))
{
MessageBox(_T("用户名或密码错误,请在网络畅通的情况下重新输入"), _T("温馨提示"), MB_OK | MB_ICONINFORMATION);
return;
}
CDialog::OnOK();
}
void CLogin::OnBnClickedBtnRegist()
{
char strURL[1024] = { 0 };
sprintf(strURL, "http://www.gnxxkj.com/app/wuziqi/register.php");
CString wstrURL(strURL);
ShellExecute(0, NULL, wstrURL, NULL, NULL, SW_NORMAL); //在外部打开网页
}
//Inter.h
typedef signed char TBOARD;
//以下函数在程序运行开始的时候调用,仅调用一次
extern "C" __declspec(dllexport) bool Login(char* strLoginName, char* strPassword); //登录
extern "C" __declspec(dllexport) bool InitFromModelFile(char* strModelFileName); //使用模型文件初始化
extern "C" __declspec(dllexport) bool InitWithoutModelFile(int nBoardWidth, int nBoardHeight, int nWinLen); //无模型文件时初始化
//以下函数在每局游戏开始的时候调用,每局游戏调用一次
extern "C" __declspec(dllexport) bool StartNewGame(); //开始游戏,并重置相关数据
//以下函数在每步落子的时候调用,每步落子调用一次
extern "C" __declspec(dllexport) bool SetPieceWithCoord(int nX, int nY); //根据坐标落子
extern "C" __declspec(dllexport) bool SetPieceWithGUI(CStatic* pCtrlBoard, int nCursorXInCtrl, int nCursorYInCtrl); //根据界面组件及屏幕鼠标位置落子
extern "C" __declspec(dllexport) bool SetPieceByAI(void); //AI落子,该函数返回失败表示所登录的用户积分不足
extern "C" __declspec(dllexport) bool SetPieceByAIAndShow(CStatic* pCtrlBoard); //AI落子并在界面上显示
extern "C" __declspec(dllexport) bool IsGameOver(); //游戏是否已经结束
extern "C" __declspec(dllexport) int GetWinner(); //获胜者
extern "C" __declspec(dllexport) bool DrawBoard(CStatic* pCtrlBoard); //绘制棋盘
extern "C" __declspec(dllexport) bool DrawPieces(CStatic* pCtrlBoard); //绘制所有棋子
//以下函数在需要的时候调用,非必须调用
extern "C" __declspec(dllexport) TBOARD* GetBoardData(int* pnBoardWidth, int* pnBoardHeight); //获得当前棋局数组的内存区首地址(及矩阵的宽和高,如果需要的话)
extern "C" __declspec(dllexport) int GetPoint();
extern "C" __declspec(dllexport) bool SaveSteps(char* strDataFileName); //保存棋局数据
extern "C" __declspec(dllexport) bool SaveModel(char* strModelFileName); //保存模型数据
//以下函数用于“五子棋水平等级评估”
extern "C" __declspec(dllexport) bool SetLayers4Pred(int nLayers); //设置用于预测的层数,与之同时,将禁止神经网络的学习进化,仅使用指定的模型进行预测,可保证公平性