课程设计扫雷小游戏
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告课程名称:面向对象程序设计C++
设计题目:扫雷小游戏
专业:计算机科学与技术
姓名:
学号:
指导教师:李晓虹
2016 年 1 月 6日
目录
一、系统需求分析 (2)
1.1功能需求分析 (2)
1.2 运行环境需求 (2)
1.3硬件需求 (2)
1.4基本素材需求 (3)
二、总体设计 (3)
三、详细设计 (3)
3.1 具体要求如下: (3)
3.2游戏流程 (4)
四、系统调试 (4)
五、结果分析 (5)
六、总结 (5)
一、系统需求分析
随着现在生活节奏的加快,人们在工作学习之余需要一个轻松娱乐的放松环境。
因此我编写此软件的目的,一方面作为初学者来了解C++环境下的小程序开发,另一方面使用户能在娱乐休闲的同时拓展思维能力。
1.1功能需求分析
功能简介
随机布雷可以由电脑进行随机布雷
自定义雷的数量可以由用户自定义雷的数量
计时有计时装置,可以自开始扫雷后自动记
时
难度级别选项各个级别的难度对应雷的数量的不同游戏结束提示在游戏结束时会出现提示对话框,并停
止计时
自定义雷的数量界面自定义雷的数量界面
程序主界面游戏运行的界面
1.2 运行环境需求
基本操作系统:win7,win XP
1.3硬件需求
a.处理器型号:奔腾III及同等型号以上处理器
b.内存容量:512MB以上内存(可运行数据库管理系统)
c.外存容量:5G以上硬盘空间
d.联机或脱机:脱机
e.输入及输出设备的型号和数量:鼠标、彩色显示器
1.4基本素材需求
二、总体设计
扫雷是单人计算机游戏。
游戏的用户界面由小方格组成的战场构成。
当游戏开始时,计算机将固定的地雷数随机的放到战场的方格。
此游戏还允许玩家指定战场中的地雷数。
参考Windows 操作系统提供的扫雷游戏,改进扫雷游戏程序,增加以下功能:在主界面中添加一个菜单栏,菜单栏中包括游戏和帮助两个菜单,其中游戏菜单中设置初级、中级、高级、自定义、声音、扫雷英雄榜这几个菜单项,帮助菜单中设置游戏规则和制作人员两个菜单项。
背景说明:
a.软件名称:扫雷
b.用户:所有扫雷游戏爱好者
三、详细设计
3.1 具体要求如下:
(1)扫雷游戏分为初级、中级和高级三个级别。
单击游戏菜单可以选择“初级”、“中级”和“高级”。
三个等级的区别在于,其雷的总数不一样,分别为40、80、120个雷,在相同数目的格子中,雷的数目愈多,其难度自然就愈大。
(2)选择级别后将出现相应级别的扫雷区域,这时用户使用鼠标左键单击‘“开始”便启动计时器。
(3)用户要揭开某个方块,可左键单击它。
若所揭方块下有雷,用户便输了这一局,若所揭方块下无雷,则显示一个数字,该数字代表方块的周围的8个方块中共有多少颗雷。
(4)如果用户认为某个方块下埋着雷,单击右键可以在方块上标识一个用户认为是雷的图标,即给出一个扫雷标记。
用户每标记出一个扫雷标记(无论用户的标记是否正确),程序将显示的剩余雷数减少一个。
(5)当用户点中雷时,将有提示出现,胜利时,也有提示出现。
游戏的基本步骤为:
开始:按左键开始游戏,单击表情按钮或菜单重新开始;
左键:按下时,是雷则结束,非雷则显示数字;
数字:表示此数字周围一圈八个格子中雷的数目;
右键:奇数次按下,则用小红旗标记,表示此处是雷;偶数次按下,表示对上 次的否定;
结束:左键单击到雷则结束,标记出所有的雷则结束;
3.2游戏流程
运行截图
游戏开始时截图,点击游戏菜单下的“开始”可以运行,或者点击开始。
右边有计时器,
左边是分数。
这是游戏中途的截图 这是游戏失败的截图
四、系统调试
在编写程序时,不免会出现这样那样的错误,这时需要我们从各个方向来解决。
在调试这个游戏时,遇到一些语法和逻辑方面的问题。
但是都得到了解决。
开始游戏
选择游戏难易程度
中级
低级
高级
游戏是否胜利
失败
胜利
游戏结束
五、结果分析
能够顺利地运行程序
六、总结
1.通过设计实验,能综合运用了所学知识,编程解决实际问题,是所学知识掌握得更系统扎实。
2.现自己的知识的欠缺和能力的不足,使我们能够了解自己的不足,能及时补救,使自己得到不断完善。
3.通过设计实验,对所学知识有了更深的理解,了解所学知识在实际生活中的运用。
4.通过这次设计的总结,我会在以后的学习中增强自己理论与实践相结合的能力。
附件:
部分程序源代码:
DlgCustom.cpp:
#include "stdafx.h"
#include "mine.h"
#include "DlgHero.h"
#include "MineWnd.h"
#include "MineDefs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
CDlgHero::CDlgHero(CWnd* pParent /*=NULL*/)
: CDialog(CDlgHero::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgHero)
m_szBHolder = _T("");
m_szEHolder = _T("");
m_szBRecord = _T("");
m_szERecord = _T("");
m_szIHolder = _T("");
m_szIRecord = _T("");
//}}AFX_DATA_INIT
}
void CDlgHero::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgHero)
DDX_Text(pDX, IDC_B_H, m_szBHolder);
DDX_Text(pDX, IDC_E_H, m_szEHolder);
DDX_Text(pDX, IDC_B_R, m_szBRecord);
DDX_Text(pDX, IDC_E_R, m_szERecord);
DDX_Text(pDX, IDC_I_H, m_szIHolder);
DDX_Text(pDX, IDC_I_R, m_szIRecord);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgHero, CDialog)
//{{AFX_MSG_MAP(CDlgHero)
ON_BN_CLICKED(IDC_RESET, OnReset)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// void CDlgHero::SetBHolder(CString holder)
{
m_szBHolder = holder;
}
void CDlgHero::SetBRecord(UINT record)
{
m_szBRecord.Format("%d秒", record);
}
void CDlgHero::SetIHolder(CString holder)
{
m_szIHolder = holder;
}
void CDlgHero::SetIRecord(UINT record)
{
m_szIRecord.Format("%d秒", record);
}
void CDlgHero::SetEHolder(CString holder)
{
m_szEHolder = holder;
}
void CDlgHero::SetERecord(UINT record)
{
m_szERecord.Format("%d秒", record);
}
void CDlgHero::OnReset()
{
CMineWnd *pMine = (CMineWnd*)AfxGetMainWnd();
pMine->ResetRecord();
m_szBHolder = DEFAULT_HOLDER;
m_szBRecord.Format("%d秒", DEFAULT_RECORD);
m_szIHolder = DEFAULT_HOLDER;
m_szIRecord.Format("%d秒", DEFAULT_RECORD);
m_szEHolder = DEFAULT_HOLDER;
m_szERecord.Format("%d秒", DEFAULT_RECORD);
UpdateData(FALSE);
}
DlgCustom.cpp
#include "stdafx.h"
#include "mine.h"
#include "DlgCustom.h"
#include "MineWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDlgCustom dialog
CDlgCustom::CDlgCustom(CWnd* pParent /*=NULL*/) : CDialog(CDlgCustom::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgCustom)
m_uHeight = 0;
m_uNumber = 0;
m_uWidth = 0;
//}}AFX_DATA_INIT
}
void CDlgCustom::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgCustom)
DDX_Text(pDX, IDC_HEIGHT, m_uHeight);
DDX_Text(pDX, IDC_NUMBER, m_uNumber);
DDX_Text(pDX, IDC_WIDTH, m_uWidth);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgCustom, CDialog)
//{{AFX_MSG_MAP(CDlgCustom)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
void CDlgCustom::OnOK()
{
UpdateData();
if (m_uWidth < 9) m_uWidth = 9;
if (m_uWidth > 30) m_uWidth = 30;
if (m_uHeight < 9) m_uHeight = 9;
if (m_uHeight > 24) m_uHeight = 24;
if (m_uNumber < 10) m_uNumber = 10;
if (m_uNumber > m_uWidth * m_uHeight) m_uNumber = m_uWidth * m_uHeight - 1;
CMineWnd *pMine = (CMineWnd*)AfxGetMainWnd();
pMine->SetCustom(m_uWidth, m_uHeight, m_uNumber);
CDialog::OnOK();
}
void CDlgCustom::InitData(UINT xNum, UINT yNum, UINT mNum)
{
m_uWidth = xNum;
m_uHeight = yNum;
m_uNumber = mNum;
}
DlgNewRecord.cpp
#include "stdafx.h"
#include "mine.h"
#include "DlgNewRecord.h"
#include "MineDefs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
CDlgNewRecord::CDlgNewRecord(CWnd* pParent /*=NULL*/)
: CDialog(CDlgNewRecord::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgNewRecord)
m_szName = _T("匿名");
m_szDesc = _T("");
//}}AFX_DATA_INIT
}
void CDlgNewRecord::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgNewRecord)
DDX_Text(pDX, IDC_EDIT_NAME, m_szName);
DDX_Text(pDX, IDC_DESCRIBE, m_szDesc);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgNewRecord, CDialog)
//{{AFX_MSG_MAP(CDlgNewRecord)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
void CDlgNewRecord::SetLevel(UINT level)
{
CString szLevel;
if (level == LEVEL_PRIMARY) szLevel = "初级";
else if (level == LEVEL_SECONDRY) szLevel = "中级";
else if (level == LEVEL_ADV ANCE) szLevel = "高级";
m_szDesc.Format("已破%s记录\n\r请留尊姓大名", szLevel); }
CString CDlgNewRecord::GetName()
{
return m_szName;
}
Mine.cpp
#include "stdafx.h"
#include "Mine.h"
#include "MineDefs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CMineApp, CWinApp)
//{{AFX_MSG_MAP(CMineApp)
//}}AFX_MSG
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// CMineApp::CMineApp()
{
}
/////////////////////////////////////////////////////////////////////////////
CMineApp theApp;
const CString className = _T("MineClass");
/////////////////////////////////////////////////////////////////////////////
BOOL CMineApp::InitInstance()
{
SetRegistryKey("CSER_513_2");
m_uXMineNum = GetProfileInt(GAME_SETTING, CUSTOM_XNUM, PRIMARY_XNUM);
m_uYMineNum = GetProfileInt(GAME_SETTING, CUSTOM_YNUM, PRIMARY_YNUM);
//定义并注册MineWnd窗口
m_pMineWnd = new CMineWnd();
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.hInstance = AfxGetInstanceHandle();
wc.lpfnWndProc = ::DefWindowProc;
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(IDC_ARROW);
wc.hIcon = LoadIcon(IDR_MAINFRAME);
wc.lpszClassName = className;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
// register the minewnd class
//注册窗口
if (!AfxRegisterClass(&wc))
{
AfxMessageBox("注册类失败!");
return FALSE;
}
// get the minewnd coordinates, width and height
UINT uWidth = DEFAULT_FRAME_X + m_uXMineNum * MINE_WIDTH +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1;
UINT uHeight = DEFAULT_FRAME_Y + m_uYMineNum * MINE_HEIGHT +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H;
UINT uXPos = GetSystemMetrics(SM_CXSCREEN) / 2 - uWidth / 2;
UINT uYPos = GetSystemMetrics(SM_CYSCREEN) / 2 - uHeight / 2;
//创建窗口
if ( !m_pMineWnd->CreateEx( NULL, className, _T("扫雷"),
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
uXPos, uYPos, uWidth, uHeight,
NULL, NULL) )
{
AfxMessageBox("创建主窗口失败!");
return FALSE;
}
// 绑定该窗口为主窗口
m_pMainWnd = m_pMineWnd;
//显示窗口
m_pMineWnd->ShowWindow(SW_NORMAL);
return TRUE;
}
int CMineApp::ExitInstance()
{
delete m_pMineWnd;
return CWinApp::ExitInstance();
}
Mines.cpp
#include "stdafx.h"
#include "Mine.h"
#include "MineDefs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CMineApp, CWinApp)
//{{AFX_MSG_MAP(CMineApp)
//}}AFX_MSG
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
CMineApp::CMineApp()
{
}
/////////////////////////////////////////////////////////////////////////////
CMineApp theApp;
const CString className = _T("MineClass");
/////////////////////////////////////////////////////////////////////////////
BOOL CMineApp::InitInstance()
{
SetRegistryKey("CSER_513_2");
m_uXMineNum = GetProfileInt(GAME_SETTING, CUSTOM_XNUM, PRIMARY_XNUM);
m_uYMineNum = GetProfileInt(GAME_SETTING, CUSTOM_YNUM, PRIMARY_YNUM);
//定义并注册MineWnd窗口
m_pMineWnd = new CMineWnd();
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.hInstance = AfxGetInstanceHandle();
wc.lpfnWndProc = ::DefWindowProc;
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(IDC_ARROW);
wc.hIcon = LoadIcon(IDR_MAINFRAME);
wc.lpszClassName = className;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
// register the minewnd class
//注册窗口
if (!AfxRegisterClass(&wc))
{
AfxMessageBox("注册类失败!");
return FALSE;
}
// get the minewnd coordinates, width and height
UINT uWidth = DEFAULT_FRAME_X + m_uXMineNum * MINE_WIDTH +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1;
UINT uHeight = DEFAULT_FRAME_Y + m_uYMineNum * MINE_HEIGHT +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H;
UINT uXPos = GetSystemMetrics(SM_CXSCREEN) / 2 - uWidth / 2;
UINT uYPos = GetSystemMetrics(SM_CYSCREEN) / 2 - uHeight / 2;
//创建窗口
if ( !m_pMineWnd->CreateEx( NULL, className, _T("扫雷"),
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
uXPos, uYPos, uWidth, uHeight,
NULL, NULL) )
{
AfxMessageBox("创建主窗口失败!");
return FALSE;
}
// 绑定该窗口为主窗口
m_pMainWnd = m_pMineWnd;
//显示窗口
m_pMineWnd->ShowWindow(SW_NORMAL);
return TRUE;
}
int CMineApp::ExitInstance()
{
AfxMessageBox("A");
delete m_pMineWnd;
return CWinApp::ExitInstance();
}
MineWnds.cpp
#include "stdafx.h"
#include "Mine.h"
#include "MineWnd.h"
#include "MineDefs.h"
#include "Mmsystem.h"
#include "DlgNewRecord.h"
#include "DlgHero.h"
#include "DlgCustom.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CMineApp theApp;
#define ID_TIMER_EVENT WM_USER + 1
///////////////////////////////////////////////////////////////////////////// CMineWnd::CMineWnd()
{
m_pSndDead = NULL;
m_pSndVictory = NULL;
m_pSndClock = NULL;
m_uTimer = 0;
m_brsBG.CreateSolidBrush(COLOR_GRAY);
LoadConfig();
if (m_bSoundful) LoadWaveSrc();
InitGame();
}
CMineWnd::~CMineWnd()
{
FreeMines();
FreeWaveSrc();
SaveConfig();
}
BEGIN_MESSAGE_MAP(CMineWnd, CWnd)
//{{AFX_MSG_MAP(CMineWnd)
ON_WM_PAINT()
ON_WM_SHOWWINDOW()
ON_WM_TIMER()
ON_WM_LBUTTONUP()
ON_WM_RBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_COMMAND(IDM_START, OnMemuStart)
ON_COMMAND(IDM_PRIMARY, OnMemuPrimary)
ON_COMMAND(IDM_SECOND, OnMemuSecond)
ON_COMMAND(IDM_ADV ANCE, OnMemuAdvance)
ON_COMMAND(IDM_CUSTOM, OnMemuCustom)
ON_COMMAND(IDM_MARK, OnMemuMark)
ON_COMMAND(IDM_COLOR, OnMemuColor)
ON_COMMAND(IDM_SOUND, OnMemuSound)
ON_COMMAND(IDM_EXIT, OnMemuExit)
ON_COMMAND(IDM_HELP_LIST, OnMemuHelpList)
ON_COMMAND(IDM_HELP_FIND, OnMemuHelpFind)
ON_COMMAND(IDM_HELP_USE, OnMemuHelpUse)
ON_COMMAND(IDM_ABOUT, OnMemuAbout)
ON_WM_KEYDOWN()
ON_WM_INITMENU()
ON_WM_CLOSE()
ON_COMMAND(IDM_HERO, OnMemuHero)
ON_COMMAND(IDM_CHEAT, OnMemuCheat)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
//载入配置
//
void CMineWnd::LoadConfig()
{
//----------获取本地目录-------------*/
char exeFullPath[MAX_PA TH];
CString strPath;
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
strPath = CString(exeFullPath);
strPath = strPath.Left(strPath.ReverseFind('\\'));
//-----------------------------------*/
strPath += "\\config.ini";
char strPrimary[80];
char strSecond[80];
char strAdvance[80];
m_uXNum = GetPrivateProfileInt("WINDOW","XNum", 10,strPath);
m_uYNum = GetPrivateProfileInt("WINDOW","YNum", 10,strPath);
m_uMineNum = GetPrivateProfileInt("MINE","MineNum", 10,strPath);
m_uLevel = GetPrivateProfileInt("MINE","Level", 0,strPath);
m_uPrimary = GetPrivateProfileInt("SCORE","Primary", 999,strPath);
m_uSecond = GetPrivateProfileInt("SCORE","Second", 999,strPath);
m_uAdvance = GetPrivateProfileInt("SCORE","Advance", 999,strPath);
GetPrivateProfileString("HOLDER","PrimaryHolder", "匿名",strPrimary,80,strPath);
GetPrivateProfileString("HOLDER","SecondHolder", "匿名",strSecond,80,strPath);
GetPrivateProfileString("HOLDER","AdvanceHolder", "匿名",strAdvance,80,strPath);
m_szPrimary = strPrimary;
m_szSecond = strSecond;
m_szAdvance = strAdvance;
m_bMarkful = GetPrivateProfileInt("CONFIG","Markful", 0,strPath);
m_bColorful = GetPrivateProfileInt("CONFIG","Colorful", 1,strPath);
m_bSoundful = GetPrivateProfileInt("CONFIG","Soundful", 1,strPath);
}
//
// 保存
//
void CMineWnd::SaveConfig()
{
//----------获取本地目录-------------*/
char exeFullPath[MAX_PA TH];
CString strPath;
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
strPath = CString(exeFullPath);
strPath = strPath.Left(strPath.ReverseFind('\\'));
//-----------------------------------*/
strPath += "\\config.ini";
//雷区行列数
CString strXNum,strYNum;
//雷数选择级别
CString strMineNum,strLevel;
//记录保持分数
CString strPrimary,strSecond,strAdvance;
//记录保持者
CString strPrimaryHolder,strSecondHolder,strAdvanceHolder;
//其他配置
CString strMarkful,strColorful,strSoundful;
strXNum.Format("%u",m_uXNum);
strYNum.Format("%u",m_uYNum);
strMineNum.Format("%u",m_uMineNum);
strLevel.Format("%u",m_uLevel);
strPrimary.Format("%u",m_uPrimary);
strSecond.Format("%u",m_uSecond);
strAdvance.Format("%u",m_uAdvance);
strPrimaryHolder.Format("%s",m_szPrimary);
strSecondHolder.Format("%s",m_szSecond);
strAdvanceHolder.Format("%s",m_szAdvance);
strMarkful.Format("%d",m_bMarkful);
strColorful.Format("%d",m_bColorful);
strSoundful.Format("%d",m_bSoundful);
WritePrivateProfileString("WINDOW","XNum", strXNum,strPath);
WritePrivateProfileString("WINDOW","YNum", strYNum,strPath);
WritePrivateProfileString("MINE","MineNum", strMineNum,strPath);
WritePrivateProfileString("MINE","Level", strLevel,strPath);
WritePrivateProfileString("SCORE","Primary", strPrimary,strPath);
WritePrivateProfileString("SCORE","Second", strSecond,strPath);
WritePrivateProfileString("SCORE","Advance", strAdvance,strPath);
WritePrivateProfileString("HOLDER","PrimaryHolder", strPrimaryHolder,strPath);
WritePrivateProfileString("HOLDER","SecondHolder", strSecondHolder,strPath);
WritePrivateProfileString("HOLDER","AdvanceHolder", strAdvanceHolder,strPath);
WritePrivateProfileString("CONFIG","Markful", strMarkful,strPath);
WritePrivateProfileString("CONFIG","Colorful", strColorful,strPath);
WritePrivateProfileString("CONFIG","Soundful", strSoundful,strPath);
}
//
//载入位图
//
void CMineWnd::LoadBitmap()
{
if (m_bColorful)
{
m_clrDark = COLOR_DARK_GRAY;
m_bmpMine.DeleteObject();
m_bmpMine.LoadBitmap(IDB_MINE_COLOR);
m_bmpNumber.DeleteObject();
m_bmpNumber.LoadBitmap(IDB_NUM_COLOR);
m_bmpButton.DeleteObject();
m_bmpButton.LoadBitmap(IDB_BTN_COLOR);
}
else
{
m_clrDark = COLOR_BLACK;
m_bmpMine.DeleteObject();
m_bmpMine.LoadBitmap(IDB_MINE_GRAY);
m_bmpNumber.DeleteObject();
m_bmpNumber.LoadBitmap(IDB_NUM_GRAY);
m_bmpButton.DeleteObject();
m_bmpButton.LoadBitmap(IDB_BTN_GRAY);
}
}
//
// 游戏的初始化
//
void CMineWnd::InitGame()
{
//位图的初始化
LoadBitmap();
m_nLeaveNum = m_uMineNum;
m_uSpendTime = 0;
m_uBtnState = BUTTON_NORMAL;
m_uGameState = GS_W AIT;
if (m_uTimer)
{
KillTimer(ID_TIMER_EVENT);
m_uTimer = 0;
}
m_pNewMine = NULL;
m_pOldMine = NULL;
FreeMines();
//初始化地图
for (UINT i = 0; i<m_uYNum; i++)
{
for (UINT j = 0; j<m_uXNum; j++)
{
m_pMines[i][j].uRow = i;
m_pMines[i][j].uCol = j;
m_pMines[i][j].uState = STA TE_NORMAL;
m_pMines[i][j].uAttrib = ATTRIB_EMPTY;
m_pMines[i][j].uOldState = STA TE_NORMAL;
}
}
}
//
// 布雷
//
void CMineWnd::LayMines(UINT row, UINT col)
{
//埋下随机种子
srand( (unsigned)time( NULL ) );
UINT i, j;
for(UINT index = 0; index < m_uMineNum;)
{
//取随即数
i = rand() % m_uYNum;
j = rand() % m_uXNum;
if (i == row && j == col) continue;
if(m_pMines[i][j].uAttrib != ATTRIB_MINE)
{
m_pMines[i][j].uAttrib = ATTRIB_MINE;//修改属性为雷
index++;
}
}
}
//
//雷方块拓展(对于周围无雷的空白区域)
//
void CMineWnd::ExpandMines(UINT row, UINT col)
{
UINT i, j;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
UINT around = GetAroundNum(row, col);
m_pMines[row][col].uState = 15 - around;
m_pMines[row][col].uOldState = 15 - around;
// “打开”该区域,重绘
DrawSpecialMine(row, col);
//对周围一个雷都没有的空白区域
if (around == 0)
{
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{//对于周围可以拓展的区域进行的规拓展
if (!(i == row && j == col) &&
m_pMines[i][j].uState == STATE_NORMAL
&& m_pMines[i][j].uAttrib != ATTRIB_MINE)
{
if (!IsInMineArea(i, j)) continue;
ExpandMines(i, j);
}
}
}
}
}
//
// 获取某个小方块区域相邻8个区域的雷个数
//
UINT CMineWnd::GetAroundNum(UINT row, UINT col)
{
UINT i, j;
UINT around = 0;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uAttrib == ATTRIB_MINE) around++;
}
}
return around;
}
//
// 获取某个小方块区域相邻8个区域的已标志状态数
//
UINT CMineWnd::GetAroundFlags(UINT row, UINT col)
{
UINT i, j;
UINT flags = 0;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uState == STATE_FLAG) flags++;
}
}
return flags;
}
//
//判断是否为雷
//
BOOL CMineWnd::IsMine(UINT row, UINT col)
{
return (m_pMines[row][col].uAttrib == ATTRIB_MINE);
}
//判断是否在雷区域
BOOL CMineWnd::IsInMineArea(UINT row, UINT col)
{
return (row >= 0 && row < m_uYNum && col >= 0 && col < m_uXNum); }
//
// 失败处理
//
void CMineWnd::Dead(UINT row, UINT col)
{
//按钮所在的区域
CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
//雷区所在的区域
CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP,
MINE_AREA_LEFT + m_uXNum * MINE_WIDTH,
MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
UINT i, j;
if (m_pMines[row][col].uAttrib == ATTRIB_MINE)
{//失败--点中雷
for (i = 0; i < m_uYNum; i++)
{
for (j = 0; j < m_uXNum; j++)
{
m_pMines[row][col].uState = STA TE_BLAST;
m_pMines[row][col].uOldState = STA TE_BLAST;
if (m_pMines[i][j].uAttrib == ATTRIB_MINE
&& m_pMines[i][j].uState != STA TE_FLAG)
{
m_pMines[i][j].uState = STA TE_MINE;
m_pMines[i][j].uOldState = STA TE_MINE;
}
}
}
}
else {//失败--错误雷
for (i = 0; i < m_uYNum; i++)
{
for (j = 0; j < m_uXNum; j++)
{
m_pMines[row][col].uState = STA TE_ERROR;
m_pMines[row][col].uOldState = STA TE_ERROR;
if (m_pMines[i][j].uAttrib == ATTRIB_MINE
&& m_pMines[i][j].uState != STA TE_FLAG)
{
m_pMines[i][j].uState = STA TE_MINE;
m_pMines[i][j].uOldState = STA TE_MINE;
}
}
}
}
//失败处理
InvalidateRect(rcMineArea);
m_uBtnState = BUTTON_DEAD;
InvalidateRect(rcBtn);
m_uGameState = GS_DEAD;
if (m_uTimer != 0)
{//将定时器去激活
KillTimer(ID_TIMER_EVENT);
m_uTimer = 0;
}
if (m_bSoundful)
{//失败声音播放
sndPlaySound((LPCTSTR)LockResource(m_pSndDead), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
}
}
//
// 胜利判断并处理
//
BOOL CMineWnd::Victory()
{
UINT i, j;
CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
// 检测是否胜利
for (i = 0; i < m_uYNum; i++)
{
for (j = 0; j < m_uXNum; j++)
{
if (m_pMines[i][j].uState == STATE_NORMAL) return FALSE;
if (m_pMines[i][j].uState == STATE_DICEY) return FALSE;
}
}
//胜利则作胜利处理
m_uBtnState = BUTTON_VICTORY;
m_uGameState = GS_VICTORY;
Invalidate();
if (m_uTimer != 0)
{//将定时器去激活
KillTimer(ID_TIMER_EVENT);
m_uTimer = 0;
}
//胜利声音
if (m_bSoundful)
{
sndPlaySound((LPCTSTR)LockResource(m_pSndVictory),
SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
}
//英雄榜
UINT uRecord;
if (m_uLevel == LEVEL_PRIMARY) uRecord = m_uPrimary;
else if (m_uLevel == LEVEL_SECONDRY) uRecord = m_uSecond;
else if (m_uLevel == LEVEL_ADV ANCE) uRecord = m_uAdvance;
if (uRecord > m_uSpendTime)
{
CDlgNewRecord dlg;
dlg.SetLevel(m_uLevel);
dlg.DoModal();
switch(m_uLevel)
{
case LEVEL_PRIMARY:
m_uPrimary = m_uSpendTime;
m_szPrimary = dlg.GetName();
break;
case LEVEL_SECONDRY:
m_uSecond = m_uSpendTime;
m_szSecond = dlg.GetName();
break;
case LEVEL_ADV ANCE:
m_uAdvance = m_uSpendTime;
m_szAdvance = dlg.GetName();
break;
case LEVEL_CUSTOM:
return TRUE;
default:
break;
}
OnMemuHero();
}
return TRUE;
}
//
// 鼠标右键,根据原先不同的标记作状态循环修改
// 以便用户可以修改其原先标志
//
void CMineWnd::OnLRBtnDown(UINT row, UINT col)
{
UINT i, j;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
// if (i == row && j == col) continue;
if (m_pMines[i][j].uState == STATE_NORMAL)
{
m_pMines[i][j].uState = STA TE_EMPTY;
}
else if (m_pMines[i][j].uState == STA TE_DICEY)
{
m_pMines[i][j].uState = STA TE_DICEY_DOWN;
}
}
}
}
void CMineWnd::OnLRBtnUp(UINT row, UINT col)
{
UINT i, j;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
// if (i == row && j == col) continue;
if (m_pMines[i][j].uOldState == STATE_NORMAL)
{
m_pMines[i][j].uState = STA TE_NORMAL;
}
else if (m_pMines[i][j].uOldState == STA TE_DICEY)
{
m_pMines[i][j].uState = STA TE_DICEY;
}
}
}
// Invalidate();
}
//展开拓展周围8个方向
void CMineWnd::OpenAround(UINT row, UINT col)
{
//如果周围相邻的标志雷数!= 周围相邻的雷数则返回
if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return;
UINT i, j;
UINT around = 0;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uState == STATE_NORMAL)
{//如果该区域为正常区域
//拓展该雷区
ExpandMines(i, j);
around = GetAroundNum(i, j);
m_pMines[i][j].uState = 15 - around;
m_pMines[i][j].uOldState = 15 - around;
}
}
}
// 判断是否胜利,是则将地图中所有雷标识出来
if (Victory())
{
for (i = 0; i < m_uYNum; i++)
{
for (j = 0; j < m_uXNum; j++)
{
if (m_pMines[i][j].uAttrib == ATTRIB_MINE)
{
m_pMines[i][j].uState = STA TE_FLAG;
m_pMines[i][j].uOldState = STA TE_FLAG;
}
}
}
m_nLeaveNum = 0;
Invalidate();
}
}
BOOL CMineWnd::ErrorAroundFlag(UINT row, UINT col)
{
//如果周围相邻的标志雷数!= 周围相邻的雷数则返回if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return FALSE;
UINT i, j;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{
for (j = minCol; j < maxCol; j++)
{
if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uState == STATE_FLAG)
{
if (m_pMines[i][j].uAttrib != ATTRIB_MINE)
{
Dead(i, j);
return TRUE;
}
}
}
}
return FALSE;
}
void CMineWnd::OpenByCheat()
{
UINT i, j;
for (i = 0; i < m_uYNum; i++)
{
for (j = 0; j < m_uXNum; j++)
{
if (m_pMines[i][j].uState == STATE_FLAG) continue;
OpenAround(i, j);
}
}
}
void CMineWnd::FreeMines()
{
// if (m_pMines) {
// delete[] m_pMines;
// m_pMines = NULL;
// }
// for (UINT row = 0; row<m_uYNum; row++) {
// if (m_pMines[row]) {
// delete []m_pMines[m_uXNum];
// delete m_pMines[row];
// }
// }
}
void CMineWnd::SizeWindow( void )
{
UINT uWidth = DEFAULT_FRAME_X + m_uXNum * MINE_WIDTH +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1;
UINT uHeight = DEFAULT_FRAME_Y + m_uYNum * MINE_HEIGHT +
LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H;
SetWindowPos(&wndTopMost, 0, 0, uWidth, uHeight,
SWP_NOZORDER | SWP_NOMOVE | SWP_NOCOPYBITS); //
SWP_NOCOPYBITS does not do function???
GetClientRect(&m_rcClient);
// Button Position
m_uBtnRect[0] = m_rcClient.right / 2 - 12; // the left side of the start(state) button without 3d border
m_uBtnRect[1] = m_rcClient.right / 2 - 13; // the left side of the start(state) button with 3d border
m_uBtnRect[2] = m_rcClient.right / 2 + 12; // the right side of the start(state) button
// Number Position
m_uNumRect[0] = m_rcClient.right - 55; // the left side of the spend time rect with 3d border
m_uNumRect[1] = m_rcClient.right - 15; // the right side of the spend time rect
m_uNumRect[2] = m_rcClient.right - 54; // the left side of the spend time rect without 3d border
// m_uNumRect[3] = m_rcClient.right - 41;
// m_uNumRect[4] = m_rcClient.right - 28;
// Shell Position
m_uShellRcX[0] = m_rcClient.right; //。