MineWnd.cpp
上传用户:hbrsgg1
上传日期:2014-05-08
资源大小:2826k
文件大小:38k
源码类别:

其他智力游戏

开发平台:

C/C++

  1. /*++
  2. Copyright (c) 2004-2005  Micro-soft
  3. Module Name:
  4.     MineWnd.cpp
  5. Abstract:
  6.        the mian Frame of the Mine-Game, we should do the most draw-work here,
  7. surely,the size and style of the window should set here too. 
  8. Author:
  9. Microsoft's Engineer - Unknown Name
  10.     improved by Weijian Luo (Arthur Luo)   15-Jun-2005
  11. E-mail: skybluehacker@yahoo.com.cn
  12. Revision History:      1.0
  13. --*/
  14. #include "stdafx.h"
  15. #include "Mine.h"
  16. #include "MineWnd.h"
  17. #include "MineDefs.h"
  18. #include "Mmsystem.h"
  19. #include "DlgNewRecord.h"
  20. #include "DlgHero.h"
  21. #include "DlgCustom.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. extern CMineApp theApp;
  28. #define ID_TIMER_EVENT WM_USER + 1
  29. /////////////////////////////////////////////////////////////////////////////
  30. CMineWnd::CMineWnd()
  31. {
  32. m_pSndDead = NULL;
  33. m_pSndVictory = NULL;
  34. m_pSndClock = NULL;
  35. m_uTimer = 0;
  36. m_brsBG.CreateSolidBrush(COLOR_GRAY);
  37. LoadConfig();
  38. if (m_bSoundful) LoadWaveSrc();
  39. InitGame();
  40. }
  41. CMineWnd::~CMineWnd()
  42. {
  43. FreeMines();
  44. FreeWaveSrc();
  45. SaveConfig();
  46. }
  47. BEGIN_MESSAGE_MAP(CMineWnd, CWnd)
  48. //{{AFX_MSG_MAP(CMineWnd)
  49. ON_WM_PAINT()
  50. ON_WM_SHOWWINDOW()
  51. ON_WM_TIMER()
  52. ON_WM_LBUTTONUP()
  53. ON_WM_RBUTTONUP()
  54. ON_WM_LBUTTONDOWN()
  55. ON_WM_RBUTTONDOWN()
  56. ON_WM_MOUSEMOVE()
  57. ON_COMMAND(IDM_START, OnMemuStart)
  58. ON_COMMAND(IDM_PRIMARY, OnMemuPrimary)
  59. ON_COMMAND(IDM_SECOND, OnMemuSecond)
  60. ON_COMMAND(IDM_ADVANCE, OnMemuAdvance)
  61. ON_COMMAND(IDM_CUSTOM, OnMemuCustom)
  62. ON_COMMAND(IDM_MARK, OnMemuMark)
  63. ON_COMMAND(IDM_COLOR, OnMemuColor)
  64. ON_COMMAND(IDM_SOUND, OnMemuSound)
  65. ON_COMMAND(IDM_EXIT, OnMemuExit)
  66. ON_COMMAND(IDM_HELP_LIST, OnMemuHelpList)
  67. ON_COMMAND(IDM_HELP_FIND, OnMemuHelpFind)
  68. ON_COMMAND(IDM_HELP_USE, OnMemuHelpUse)
  69. ON_COMMAND(IDM_ABOUT, OnMemuAbout)
  70. ON_WM_KEYDOWN()
  71. ON_WM_INITMENU()
  72. ON_WM_CLOSE()
  73. ON_COMMAND(IDM_HERO, OnMemuHero)
  74. ON_COMMAND(IDM_CHEAT, OnMemuCheat)
  75. //}}AFX_MSG_MAP
  76. END_MESSAGE_MAP()
  77. /////////////////////////////////////////////////////////////////////////////
  78. //
  79. //载入配置
  80. //
  81. void CMineWnd::LoadConfig()
  82. {
  83. //----------获取本地目录-------------*/
  84. char exeFullPath[MAX_PATH];
  85. CString strPath;
  86. GetModuleFileName(NULL, exeFullPath, MAX_PATH);
  87. strPath = CString(exeFullPath);
  88. strPath = strPath.Left(strPath.ReverseFind('\'));
  89. //-----------------------------------*/
  90. strPath += "\config.ini";
  91. char strPrimary[80];
  92. char strSecond[80];
  93. char strAdvance[80];
  94. m_uXNum = GetPrivateProfileInt("WINDOW","XNum", 10,strPath);
  95. m_uYNum = GetPrivateProfileInt("WINDOW","YNum", 10,strPath);
  96. m_uMineNum = GetPrivateProfileInt("MINE","MineNum", 10,strPath);
  97. m_uLevel = GetPrivateProfileInt("MINE","Level", 0,strPath);
  98. m_uPrimary = GetPrivateProfileInt("SCORE","Primary", 999,strPath);
  99. m_uSecond  = GetPrivateProfileInt("SCORE","Second", 999,strPath);
  100. m_uAdvance = GetPrivateProfileInt("SCORE","Advance", 999,strPath);
  101. GetPrivateProfileString("HOLDER","PrimaryHolder", "匿名",strPrimary,80,strPath);
  102. GetPrivateProfileString("HOLDER","SecondHolder", "匿名",strSecond,80,strPath);
  103. GetPrivateProfileString("HOLDER","AdvanceHolder", "匿名",strAdvance,80,strPath);
  104. m_szPrimary = strPrimary;
  105. m_szSecond = strSecond;
  106. m_szAdvance  = strAdvance;
  107. m_bMarkful = GetPrivateProfileInt("CONFIG","Markful", 0,strPath);
  108. m_bColorful = GetPrivateProfileInt("CONFIG","Colorful", 1,strPath);
  109. m_bSoundful = GetPrivateProfileInt("CONFIG","Soundful", 1,strPath);
  110. }
  111. //
  112. // 保存
  113. //
  114. void CMineWnd::SaveConfig()
  115. {
  116. //----------获取本地目录-------------*/
  117. char exeFullPath[MAX_PATH];
  118. CString strPath;
  119. GetModuleFileName(NULL, exeFullPath, MAX_PATH);
  120. strPath = CString(exeFullPath);
  121. strPath = strPath.Left(strPath.ReverseFind('\'));
  122. //-----------------------------------*/
  123. strPath += "\config.ini";
  124. //雷区行列数
  125.    CString strXNum,strYNum;
  126.    //雷数 选择级别
  127.    CString strMineNum,strLevel;
  128.    //记录保持分数
  129.    CString strPrimary,strSecond,strAdvance;
  130.    //记录保持者
  131.    CString strPrimaryHolder,strSecondHolder,strAdvanceHolder;
  132.    //其他配置
  133.    CString strMarkful,strColorful,strSoundful;
  134.    
  135.    
  136.    strXNum.Format("%u",m_uXNum);
  137.    strYNum.Format("%u",m_uYNum);
  138.    
  139.    strMineNum.Format("%u",m_uMineNum);
  140.    strLevel.Format("%u",m_uLevel);
  141.    
  142.    strPrimary.Format("%u",m_uPrimary);
  143.    strSecond.Format("%u",m_uSecond);
  144.    strAdvance.Format("%u",m_uAdvance);
  145.    
  146.    strPrimaryHolder.Format("%s",m_szPrimary);
  147.    strSecondHolder.Format("%s",m_szSecond);
  148.    strAdvanceHolder.Format("%s",m_szAdvance);
  149.    
  150.    strMarkful.Format("%d",m_bMarkful);
  151.    strColorful.Format("%d",m_bColorful);
  152.    strSoundful.Format("%d",m_bSoundful);
  153.    
  154.    
  155.    WritePrivateProfileString("WINDOW","XNum", strXNum,strPath);
  156.    WritePrivateProfileString("WINDOW","YNum", strYNum,strPath);
  157.    
  158.    WritePrivateProfileString("MINE","MineNum", strMineNum,strPath);
  159.    WritePrivateProfileString("MINE","Level", strLevel,strPath);
  160.    
  161.    WritePrivateProfileString("SCORE","Primary", strPrimary,strPath);
  162.    WritePrivateProfileString("SCORE","Second", strSecond,strPath);
  163.    WritePrivateProfileString("SCORE","Advance", strAdvance,strPath);
  164.    
  165.    WritePrivateProfileString("HOLDER","PrimaryHolder", strPrimaryHolder,strPath);
  166.    WritePrivateProfileString("HOLDER","SecondHolder", strSecondHolder,strPath);
  167.    WritePrivateProfileString("HOLDER","AdvanceHolder", strAdvanceHolder,strPath);
  168.    
  169.    WritePrivateProfileString("CONFIG","Markful", strMarkful,strPath);
  170.    WritePrivateProfileString("CONFIG","Colorful", strColorful,strPath);
  171.    WritePrivateProfileString("CONFIG","Soundful", strSoundful,strPath);
  172.    
  173. }
  174. //
  175. //载入位图
  176. //
  177. void CMineWnd::LoadBitmap()
  178. {
  179. if (m_bColorful)
  180. {
  181. m_clrDark = COLOR_DARK_GRAY;
  182. m_bmpMine.DeleteObject();
  183. m_bmpMine.LoadBitmap(IDB_MINE_COLOR);
  184. m_bmpNumber.DeleteObject();
  185. m_bmpNumber.LoadBitmap(IDB_NUM_COLOR);
  186. m_bmpButton.DeleteObject();
  187. m_bmpButton.LoadBitmap(IDB_BTN_COLOR);
  188. }
  189. else 
  190. {
  191. m_clrDark = COLOR_BLACK;
  192. m_bmpMine.DeleteObject();
  193. m_bmpMine.LoadBitmap(IDB_MINE_GRAY);
  194. m_bmpNumber.DeleteObject();
  195. m_bmpNumber.LoadBitmap(IDB_NUM_GRAY);
  196. m_bmpButton.DeleteObject();
  197. m_bmpButton.LoadBitmap(IDB_BTN_GRAY);
  198. }
  199. }
  200. //
  201. //  游戏的初始化
  202. //
  203. void CMineWnd::InitGame()
  204. {
  205. //位图的初始化
  206. LoadBitmap();
  207. m_nLeaveNum = m_uMineNum;
  208. m_uSpendTime = 0;
  209. m_uBtnState = BUTTON_NORMAL;
  210. m_uGameState = GS_WAIT;
  211. if (m_uTimer) 
  212. {
  213. KillTimer(ID_TIMER_EVENT);
  214. m_uTimer = 0;
  215. }
  216. m_pNewMine = NULL;
  217. m_pOldMine = NULL;
  218. FreeMines();
  219. //初始化地图
  220. for (UINT i = 0; i<m_uYNum; i++) 
  221. {
  222. for (UINT j = 0; j<m_uXNum; j++)
  223. {
  224. m_pMines[i][j].uRow = i;
  225. m_pMines[i][j].uCol = j;
  226. m_pMines[i][j].uState = STATE_NORMAL;
  227. m_pMines[i][j].uAttrib = ATTRIB_EMPTY;
  228. m_pMines[i][j].uOldState = STATE_NORMAL;
  229. }
  230. }
  231. }
  232. //
  233. // 布雷
  234. //
  235. void CMineWnd::LayMines(UINT row, UINT col)
  236. {
  237. //埋下随机种子
  238. srand( (unsigned)time( NULL ) );
  239. UINT i, j;
  240. for(UINT index = 0; index < m_uMineNum;) 
  241. {
  242. //取随即数
  243. i = rand() % m_uYNum;
  244. j = rand() % m_uXNum;
  245. if (i == row && j == col) continue;
  246. if(m_pMines[i][j].uAttrib != ATTRIB_MINE) 
  247. {
  248. m_pMines[i][j].uAttrib = ATTRIB_MINE;//修改属性为雷
  249. index++;
  250. }
  251. }
  252. }
  253. //
  254. //雷方块拓展(对于周围无雷的空白区域)
  255. //
  256. void CMineWnd::ExpandMines(UINT row, UINT col)
  257. {
  258. UINT i, j;
  259. UINT minRow = (row == 0) ? 0 : row - 1;
  260. UINT maxRow = row + 2;
  261. UINT minCol = (col == 0) ? 0 : col - 1;
  262. UINT maxCol = col + 2;
  263. UINT around = GetAroundNum(row, col);
  264. m_pMines[row][col].uState = 15 - around;
  265. m_pMines[row][col].uOldState = 15 - around;
  266. // “打开”该区域,重绘
  267. DrawSpecialMine(row, col);
  268. //对周围一个雷都没有的空白区域
  269. if (around == 0)
  270. {
  271. for (i = minRow; i < maxRow; i++) 
  272. {
  273. for (j = minCol; j < maxCol; j++) 
  274. {//对于周围可以拓展的区域进行的规拓展
  275. if (!(i == row && j == col) && 
  276. m_pMines[i][j].uState == STATE_NORMAL
  277. && m_pMines[i][j].uAttrib != ATTRIB_MINE) 
  278. {
  279. if (!IsInMineArea(i, j)) continue;
  280. ExpandMines(i, j);
  281. }
  282. }
  283. }
  284. }
  285. }
  286. //
  287. //  获取某个小方块区域相邻8个区域的雷个数
  288. //
  289. UINT CMineWnd::GetAroundNum(UINT row, UINT col)
  290. {
  291. UINT i, j;
  292. UINT around = 0;
  293. UINT minRow = (row == 0) ? 0 : row - 1;
  294. UINT maxRow = row + 2;
  295. UINT minCol = (col == 0) ? 0 : col - 1;
  296. UINT maxCol = col + 2;
  297. for (i = minRow; i < maxRow; i++) 
  298. {
  299. for (j = minCol; j < maxCol; j++)
  300. {
  301. if (!IsInMineArea(i, j)) continue;
  302. if (m_pMines[i][j].uAttrib == ATTRIB_MINE) around++;
  303. }
  304. }
  305. return around;
  306. }
  307. //
  308. //  获取某个小方块区域相邻8个区域的已标志状态数
  309. //
  310. UINT CMineWnd::GetAroundFlags(UINT row, UINT col)
  311. {
  312. UINT i, j;
  313. UINT flags = 0;
  314. UINT minRow = (row == 0) ? 0 : row - 1;
  315. UINT maxRow = row + 2;
  316. UINT minCol = (col == 0) ? 0 : col - 1;
  317. UINT maxCol = col + 2;
  318. for (i = minRow; i < maxRow; i++) 
  319. {
  320. for (j = minCol; j < maxCol; j++)
  321. {
  322. if (!IsInMineArea(i, j)) continue;
  323. if (m_pMines[i][j].uState == STATE_FLAG) flags++;
  324. }
  325. }
  326. return flags;
  327. }
  328. //
  329. //判断是否为雷
  330. //
  331. BOOL CMineWnd::IsMine(UINT row, UINT col)
  332. {
  333. return (m_pMines[row][col].uAttrib == ATTRIB_MINE);
  334. }
  335. //判断是否在雷区域
  336. BOOL CMineWnd::IsInMineArea(UINT row, UINT col)
  337. {
  338. return (row >= 0 && row < m_uYNum && col >= 0 && col < m_uXNum);
  339. }
  340. //
  341. //  失败处理
  342. //
  343. void CMineWnd::Dead(UINT row, UINT col)
  344. {
  345. //按钮所在的区域
  346. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  347. //雷区所在的区域
  348. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  349. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, 
  350. MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  351. UINT i, j;
  352. if (m_pMines[row][col].uAttrib == ATTRIB_MINE) 
  353. {//失败--点中雷
  354. for (i = 0; i < m_uYNum; i++)
  355. {
  356. for (j = 0; j < m_uXNum; j++)
  357. {
  358. m_pMines[row][col].uState = STATE_BLAST;
  359. m_pMines[row][col].uOldState = STATE_BLAST;
  360. if (m_pMines[i][j].uAttrib == ATTRIB_MINE
  361. && m_pMines[i][j].uState != STATE_FLAG) 
  362. {
  363. m_pMines[i][j].uState = STATE_MINE;
  364. m_pMines[i][j].uOldState = STATE_MINE;
  365. }
  366. }
  367. }
  368. }
  369. else {//失败--错误雷
  370. for (i = 0; i < m_uYNum; i++)
  371. {
  372. for (j = 0; j < m_uXNum; j++) 
  373. {
  374. m_pMines[row][col].uState = STATE_ERROR;
  375. m_pMines[row][col].uOldState = STATE_ERROR;
  376. if (m_pMines[i][j].uAttrib == ATTRIB_MINE
  377. && m_pMines[i][j].uState != STATE_FLAG)
  378. {
  379. m_pMines[i][j].uState = STATE_MINE;
  380. m_pMines[i][j].uOldState = STATE_MINE;
  381. }
  382. }
  383. }
  384. }
  385. //失败处理
  386. InvalidateRect(rcMineArea);
  387. m_uBtnState = BUTTON_DEAD;
  388. InvalidateRect(rcBtn);
  389. m_uGameState = GS_DEAD;
  390. if (m_uTimer != 0) 
  391. {//将定时器去激活
  392. KillTimer(ID_TIMER_EVENT);
  393. m_uTimer = 0;
  394. }
  395. if (m_bSoundful) 
  396. {//失败声音播放
  397. sndPlaySound((LPCTSTR)LockResource(m_pSndDead), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
  398. }
  399. }
  400. //
  401. //  胜利判断并处理
  402. //
  403. BOOL CMineWnd::Victory()
  404. {
  405. UINT i, j;
  406. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  407. // 检测是否胜利
  408. for (i = 0; i < m_uYNum; i++)
  409. {
  410. for (j = 0; j < m_uXNum; j++) 
  411. {
  412. if (m_pMines[i][j].uState == STATE_NORMAL) return FALSE;
  413. if (m_pMines[i][j].uState == STATE_DICEY) return FALSE;
  414. }
  415. }
  416. //胜利则作胜利处理
  417. m_uBtnState = BUTTON_VICTORY;
  418. m_uGameState = GS_VICTORY;
  419. Invalidate();
  420. if (m_uTimer != 0) 
  421. {//将定时器去激活
  422. KillTimer(ID_TIMER_EVENT);
  423. m_uTimer = 0;
  424. }
  425. //胜利声音
  426. if (m_bSoundful)
  427. {
  428. sndPlaySound((LPCTSTR)LockResource(m_pSndVictory), 
  429. SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
  430. }
  431. //英雄榜
  432. UINT uRecord;
  433. if (m_uLevel == LEVEL_PRIMARY) uRecord = m_uPrimary;
  434. else if (m_uLevel == LEVEL_SECONDRY) uRecord = m_uSecond;
  435. else if (m_uLevel == LEVEL_ADVANCE) uRecord = m_uAdvance;
  436. if (uRecord > m_uSpendTime) 
  437. {
  438. CDlgNewRecord dlg;
  439. dlg.SetLevel(m_uLevel);
  440. dlg.DoModal();
  441. switch(m_uLevel)
  442. {
  443. case LEVEL_PRIMARY:
  444. m_uPrimary = m_uSpendTime;
  445. m_szPrimary = dlg.GetName();
  446. break;
  447. case LEVEL_SECONDRY:
  448. m_uSecond = m_uSpendTime;
  449. m_szSecond = dlg.GetName();
  450. break;
  451. case LEVEL_ADVANCE:
  452. m_uAdvance = m_uSpendTime;
  453. m_szAdvance = dlg.GetName();
  454. break;
  455. case LEVEL_CUSTOM:
  456. return TRUE;
  457. default: 
  458. break;
  459. }
  460. OnMemuHero();
  461. }
  462. return TRUE;
  463. }
  464. //
  465. // 鼠标右键,根据原先不同的标记作状态循环修改
  466. // 以便用户可以修改其原先标志
  467. //
  468. void CMineWnd::OnLRBtnDown(UINT row, UINT col)
  469. {
  470. UINT i, j;
  471. UINT minRow = (row == 0) ? 0 : row - 1;
  472. UINT maxRow = row + 2;
  473. UINT minCol = (col == 0) ? 0 : col - 1;
  474. UINT maxCol = col + 2;
  475. for (i = minRow; i < maxRow; i++) 
  476. {
  477. for (j = minCol; j < maxCol; j++) 
  478. {
  479. if (!IsInMineArea(i, j)) continue;
  480. // if (i == row && j == col) continue;
  481. if (m_pMines[i][j].uState == STATE_NORMAL) 
  482. {
  483. m_pMines[i][j].uState = STATE_EMPTY;
  484. }
  485. else if (m_pMines[i][j].uState == STATE_DICEY)
  486. {
  487. m_pMines[i][j].uState = STATE_DICEY_DOWN;
  488. }
  489. }
  490. }
  491. }
  492. void CMineWnd::OnLRBtnUp(UINT row, UINT col)
  493. {
  494. UINT i, j;
  495. UINT minRow = (row == 0) ? 0 : row - 1;
  496. UINT maxRow = row + 2;
  497. UINT minCol = (col == 0) ? 0 : col - 1;
  498. UINT maxCol = col + 2;
  499. for (i = minRow; i < maxRow; i++) 
  500. {
  501. for (j = minCol; j < maxCol; j++)
  502. {
  503. if (!IsInMineArea(i, j)) continue;
  504. // if (i == row && j == col) continue;
  505. if (m_pMines[i][j].uOldState == STATE_NORMAL) 
  506. {
  507. m_pMines[i][j].uState = STATE_NORMAL;
  508. }
  509. else if (m_pMines[i][j].uOldState == STATE_DICEY) 
  510. {
  511. m_pMines[i][j].uState = STATE_DICEY;
  512. }
  513. }
  514. }
  515. // Invalidate();
  516. }
  517. //展开拓展周围8个方向
  518. void CMineWnd::OpenAround(UINT row, UINT col)
  519. {
  520. //如果周围相邻的标志雷数 != 周围相邻的雷数 则返回
  521. if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return;
  522. UINT i, j;
  523. UINT around = 0;
  524. UINT minRow = (row == 0) ? 0 : row - 1;
  525. UINT maxRow = row + 2;
  526. UINT minCol = (col == 0) ? 0 : col - 1;
  527. UINT maxCol = col + 2;
  528. for (i = minRow; i < maxRow; i++) 
  529. {
  530. for (j = minCol; j < maxCol; j++) 
  531. {
  532. if (!IsInMineArea(i, j)) continue;
  533. if (m_pMines[i][j].uState == STATE_NORMAL) 
  534. {//如果该区域为正常区域
  535. //拓展该雷区
  536. ExpandMines(i, j);
  537. around = GetAroundNum(i, j);
  538. m_pMines[i][j].uState = 15 - around;
  539. m_pMines[i][j].uOldState = 15 - around;
  540. }
  541. }
  542. }
  543. // 判断是否胜利,是则将地图中所有雷标识出来
  544. if (Victory())
  545. {
  546. for (i = 0; i < m_uYNum; i++) 
  547. {
  548. for (j = 0; j < m_uXNum; j++)
  549. {
  550. if (m_pMines[i][j].uAttrib == ATTRIB_MINE)
  551. {
  552. m_pMines[i][j].uState = STATE_FLAG;
  553. m_pMines[i][j].uOldState = STATE_FLAG;
  554. }
  555. }
  556. }
  557. m_nLeaveNum = 0;
  558. Invalidate();
  559. }
  560. }
  561. BOOL CMineWnd::ErrorAroundFlag(UINT row, UINT col)
  562. {
  563. //如果周围相邻的标志雷数 != 周围相邻的雷数 则返回
  564. if (GetAroundFlags(row, col) != GetAroundNum(row, col)) return FALSE;
  565. UINT i, j;
  566. UINT minRow = (row == 0) ? 0 : row - 1;
  567. UINT maxRow = row + 2;
  568. UINT minCol = (col == 0) ? 0 : col - 1;
  569. UINT maxCol = col + 2;
  570. for (i = minRow; i < maxRow; i++) 
  571. {
  572. for (j = minCol; j < maxCol; j++) 
  573. {
  574. if (!IsInMineArea(i, j)) continue;
  575. if (m_pMines[i][j].uState == STATE_FLAG)
  576. {
  577. if (m_pMines[i][j].uAttrib != ATTRIB_MINE)
  578. {
  579. Dead(i, j);
  580. return TRUE;
  581. }
  582. }
  583. }
  584. }
  585. return FALSE;
  586. }
  587. void CMineWnd::OpenByCheat()
  588. {
  589. UINT i, j;
  590. for (i = 0; i < m_uYNum; i++)
  591. {
  592. for (j = 0; j < m_uXNum; j++)
  593. {
  594. if (m_pMines[i][j].uState == STATE_FLAG) continue;
  595. OpenAround(i, j);
  596. }
  597. }
  598. }
  599. void CMineWnd::FreeMines()
  600. {
  601. // if (m_pMines) {
  602. // delete[] m_pMines;
  603. // m_pMines = NULL;
  604. // }
  605. // for (UINT row = 0; row<m_uYNum; row++) {
  606. // if (m_pMines[row]) {
  607. // delete []m_pMines[m_uXNum];
  608. // delete m_pMines[row];
  609. // }
  610. // }
  611. }
  612. void CMineWnd::SizeWindow( void )
  613. {
  614. UINT uWidth = DEFAULT_FRAME_X + m_uXNum * MINE_WIDTH +
  615. LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 + SIDE_WIDTH_1; 
  616. UINT uHeight = DEFAULT_FRAME_Y + m_uYNum * MINE_HEIGHT + 
  617. LINE_WIDTH_0 * 3 + SIDE_WIDTH_0 * 2 + SIDE_WIDTH_1 + SHELL_S_H;
  618. SetWindowPos(&wndTopMost, 0, 0, uWidth, uHeight, 
  619. SWP_NOZORDER | SWP_NOMOVE | SWP_NOCOPYBITS); // SWP_NOCOPYBITS does not do function???
  620. GetClientRect(&m_rcClient);
  621. // Button Position
  622. m_uBtnRect[0] = m_rcClient.right / 2 - 12; // the left side of the start(state) button without 3d border
  623. m_uBtnRect[1] = m_rcClient.right / 2 - 13; // the left side of the start(state) button with 3d border
  624. m_uBtnRect[2] = m_rcClient.right / 2 + 12; // the right side of the start(state) button 
  625. // Number Position
  626. m_uNumRect[0] = m_rcClient.right - 55; // the left side of the spend time rect with 3d border
  627. m_uNumRect[1] = m_rcClient.right - 15; // the right side of the spend time rect
  628. m_uNumRect[2] = m_rcClient.right - 54; // the left side of the spend time rect without 3d border
  629. // m_uNumRect[3] = m_rcClient.right - 41;
  630. // m_uNumRect[4] = m_rcClient.right - 28;
  631. // Shell Position
  632. m_uShellRcX[0] = m_rcClient.right; //
  633. m_uShellRcX[1] = m_rcClient.right - 14; // the width of the small(big) shell
  634. m_uShellRcY[0] = m_rcClient.bottom; // 
  635. m_uShellRcY[1] = m_rcClient.bottom - SHELL_L_START_Y - 5; // the height of the big shell
  636. }
  637. //
  638. // 绘制笑脸按钮图
  639. //
  640. void CMineWnd::DrawButton(CPaintDC &dc)
  641. {
  642. CDC cdc;
  643. cdc.CreateCompatibleDC(&dc);
  644. cdc.SelectObject(m_bmpButton);
  645. dc.StretchBlt(m_uBtnRect[0], 16, 24, 24, &cdc, 0, 24 * m_uBtnState, 24, 24, SRCCOPY);
  646. dc.Draw3dRect(m_uBtnRect[1], 15, 26, 26, m_clrDark, m_clrDark);
  647. }
  648. //
  649. // 绘制数字
  650. //
  651. void CMineWnd::DrawNumber(CPaintDC &dc)
  652. {
  653. CDC dcMemory;
  654. dcMemory.CreateCompatibleDC(&dc);
  655. dcMemory.SelectObject(m_bmpNumber);
  656. dc.Draw3dRect(16, 15, 41, 25, m_clrDark, COLOR_WHITE);
  657. dc.Draw3dRect(m_uNumRect[0], 15, 41, 25, m_clrDark, COLOR_WHITE);
  658. int num;
  659. // draw remaining mine numbers
  660. num = (m_nLeaveNum<0) ? 11 : m_nLeaveNum/100;
  661. dc.StretchBlt(17, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  662. num = (m_nLeaveNum < 0) ? -(m_nLeaveNum-num*100)/10 : (m_nLeaveNum-num*100)/10;
  663. dc.StretchBlt(30, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  664. num = (m_nLeaveNum<0) ? -m_nLeaveNum%10 : m_nLeaveNum%10;
  665. dc.StretchBlt(43, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  666. // draw take seconds
  667. num = m_uSpendTime / 100;
  668. dc.StretchBlt(m_uNumRect[0], 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  669. num = (m_uSpendTime-num*100)/10;
  670. dc.StretchBlt(m_uNumRect[0] + 13, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  671. num = m_uSpendTime%10;
  672. dc.StretchBlt(m_uNumRect[0]+26, 16, 13, 23, &dcMemory, 0, 276-23*(num+1), 13, 23, SRCCOPY);
  673. }
  674. //
  675. // 绘制外壳
  676. //
  677. void CMineWnd::DrawShell(CPaintDC &dc)
  678. {
  679. // 绘画2条白条
  680. dc.FillSolidRect(0, 0, m_uShellRcX[0], LINE_WIDTH_0, COLOR_WHITE);
  681. dc.FillSolidRect(0, 0, LINE_WIDTH_0, m_uShellRcY[0], COLOR_WHITE);
  682. // 画小的外壳
  683. dc.Draw3dRect(SHELL_S_START_X, SHELL_S_START_Y, 
  684. m_uShellRcX[1], SHELL_S_H, m_clrDark, COLOR_WHITE);
  685. dc.Draw3dRect(SHELL_S_START_X + 1, SHELL_S_START_Y + 1, 
  686. m_uShellRcX[1] - 2, SHELL_S_H - 2, m_clrDark, COLOR_WHITE);
  687. // 画大的外壳
  688. dc.Draw3dRect(SHELL_L_START_X, SHELL_L_START_Y,
  689. m_uShellRcX[1], m_uShellRcY[1], m_clrDark, COLOR_WHITE);
  690. dc.Draw3dRect(SHELL_L_START_X + 1, SHELL_L_START_Y + 1,
  691. m_uShellRcX[1] - 2, m_uShellRcY[1] - 2, m_clrDark, COLOR_WHITE);
  692. dc.Draw3dRect(SHELL_L_START_X + 2, SHELL_L_START_Y + 2, 
  693. m_uShellRcX[1] - 4, m_uShellRcY[1] - 4, m_clrDark, COLOR_WHITE);
  694. }
  695. //
  696. // 绘制雷区
  697. //
  698. void CMineWnd::DrawMineArea(CPaintDC &dc)
  699. {
  700. CDC dcMemory; //用作内存设备
  701. dcMemory.CreateCompatibleDC(&dc); //使得这个设备与dc兼容
  702. dcMemory.SelectObject(m_bmpMine); //将内存设备与位图资源关联
  703. for (UINT i = 0; i<m_uYNum; i++) 
  704. {
  705. for (UINT j = 0; j<m_uXNum; j++) 
  706. {//根据[i][j]区域的雷方块状态拷贝相应的图像到[i][j]雷区的特定区域
  707. dc.StretchBlt(MINEAREA_FRAME_X+16*j, MINEAREA_FRAME_Y+16*i, 
  708. 16, 16, &dcMemory, 0, 16*m_pMines[i][j].uState, 16, 16, SRCCOPY);
  709. }
  710. }
  711. }
  712. //
  713. // 绘制按下扫雷后的数字
  714. //
  715. void CMineWnd::DrawDownNum(MINEWND* mine, UINT num)
  716. {
  717. mine->uState = 15 - num;
  718. mine->uOldState = 15 - num;
  719. CRect rcMine(mine->uCol * 16, mine->uRow * 16, (mine->uCol+1) *16, (mine->uRow+1) * 16);
  720. InvalidateRect(rcMine);
  721. }
  722. //重新绘制雷区域的某个方块
  723. void CMineWnd::DrawSpecialMine(UINT row, UINT col)
  724. {
  725. CRect rcMine(col * 16, row * 16, (col+1) * 16, (row+1) * 16);
  726. InvalidateRect(rcMine);
  727. }
  728. //
  729. //  获取体图中(x,y)区域的雷信息
  730. //
  731. MINEWND* CMineWnd::GetMine(long x, long y)
  732. {
  733. //保证参数合格
  734. if (x < MINEAREA_FRAME_X || y < MINEAREA_FRAME_Y) 
  735. {
  736. return NULL;
  737. }
  738. //根据坐标值算出该小方块所在地图的行和列
  739. UINT uCol = (UINT)(x-MINEAREA_FRAME_X) / 16;
  740. UINT uRow = (UINT)(y-MINEAREA_FRAME_Y) / 16;
  741. //返回该区域的雷信息
  742. return &m_pMines[uRow][uCol];
  743. }
  744. void CMineWnd::SetCheckedLevel()
  745. {
  746. if (m_pSubMenu)
  747. {
  748. m_pSubMenu->CheckMenuItem(IDM_PRIMARY, MF_UNCHECKED | MF_BYCOMMAND);
  749. m_pSubMenu->CheckMenuItem(IDM_SECOND, MF_UNCHECKED | MF_BYCOMMAND);
  750. m_pSubMenu->CheckMenuItem(IDM_ADVANCE, MF_UNCHECKED | MF_BYCOMMAND);
  751. m_pSubMenu->CheckMenuItem(IDM_CUSTOM, MF_UNCHECKED | MF_BYCOMMAND);
  752. switch(m_uLevel)
  753. {
  754. case LEVEL_PRIMARY:
  755. m_pSubMenu->CheckMenuItem(IDM_PRIMARY, MF_CHECKED | MF_BYCOMMAND);
  756. break;
  757. case LEVEL_SECONDRY:
  758. m_pSubMenu->CheckMenuItem(IDM_SECOND, MF_CHECKED | MF_BYCOMMAND);
  759. break;
  760. case LEVEL_ADVANCE:
  761. m_pSubMenu->CheckMenuItem(IDM_ADVANCE, MF_CHECKED | MF_BYCOMMAND);
  762. break;
  763. case LEVEL_CUSTOM:
  764. m_pSubMenu->CheckMenuItem(IDM_CUSTOM, MF_CHECKED | MF_BYCOMMAND);
  765. break;
  766. default: 
  767. break;
  768. }
  769. }
  770. }
  771. void CMineWnd::SetCheckedMark()
  772. {
  773. if (m_pSubMenu) {
  774. if (m_bMarkful) {
  775. m_pSubMenu->CheckMenuItem(IDM_MARK, MF_CHECKED | MF_BYCOMMAND);
  776. }
  777. else {
  778. m_pSubMenu->CheckMenuItem(IDM_MARK, MF_UNCHECKED | MF_BYCOMMAND);
  779. }
  780. }
  781. }
  782. void CMineWnd::SetCheckedColor()
  783. {
  784. if (m_pSubMenu)
  785. {
  786. if (m_bColorful)
  787. {
  788. m_pSubMenu->CheckMenuItem(IDM_COLOR, MF_CHECKED | MF_BYCOMMAND);
  789. }
  790. else 
  791. {
  792. m_pSubMenu->CheckMenuItem(IDM_COLOR, MF_UNCHECKED | MF_BYCOMMAND);
  793. }
  794. }
  795. }
  796. void CMineWnd::SetCheckedSound()
  797. {
  798. if (m_pSubMenu)
  799. {
  800. if (m_bSoundful) 
  801. {
  802. m_pSubMenu->CheckMenuItem(IDM_SOUND, MF_CHECKED | MF_BYCOMMAND);
  803. }
  804. else 
  805. {
  806. m_pSubMenu->CheckMenuItem(IDM_SOUND, MF_UNCHECKED | MF_BYCOMMAND);
  807. }
  808. }
  809. }
  810. void CMineWnd::SetCheckedCheat()
  811. {
  812. if (m_pSubMenu)
  813. {
  814. // if (m_bCheat) 
  815. // {
  816. // m_pSubMenu->CheckMenuItem(IDM_CHEAT, MF_CHECKED | MF_BYCOMMAND);
  817. // }
  818. // else 
  819. // {
  820. m_pSubMenu->CheckMenuItem(IDM_CHEAT, MF_UNCHECKED | MF_BYCOMMAND);
  821. // }
  822. }
  823. }
  824. void CMineWnd::LoadWaveSrc()
  825. {
  826. HMODULE hMdl;
  827. hMdl = AfxGetResourceHandle();
  828. HRSRC hSrc;
  829. hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_DEAD), _T("WAVE"));
  830. m_pSndDead = LoadResource(hMdl, hSrc);
  831. hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_VICTORY), _T("WAVE"));
  832. m_pSndVictory = LoadResource(hMdl, hSrc);
  833. hSrc = FindResource(hMdl, MAKEINTRESOURCE(IDR_WAVE_CLOCK), _T("WAVE"));
  834. m_pSndClock = LoadResource(hMdl, hSrc);
  835. }
  836. void CMineWnd::FreeWaveSrc()
  837. {
  838. if (m_pSndDead)
  839. {
  840. FreeResource(m_pSndDead);
  841. m_pSndDead = NULL;
  842. }
  843. if (m_pSndVictory) 
  844. {
  845. FreeResource(m_pSndVictory);
  846. m_pSndVictory = NULL;
  847. }
  848. if (m_pSndClock)
  849. {
  850. FreeResource(m_pSndClock);
  851. m_pSndClock = NULL;
  852. }
  853. }
  854. void CMineWnd::ResetRecord()
  855. {
  856. m_uPrimary = DEFAULT_RECORD;
  857. m_szPrimary = DEFAULT_HOLDER;
  858. m_uSecond= DEFAULT_RECORD;
  859. m_szSecond = DEFAULT_HOLDER;
  860. m_uAdvance = DEFAULT_RECORD;
  861. m_szAdvance = DEFAULT_HOLDER;
  862. }
  863. void CMineWnd::SetCustom(UINT xNum, UINT yNum, UINT mNum)
  864. {
  865. m_uXNum = xNum;
  866. m_uYNum = yNum;
  867. m_uMineNum = mNum;
  868. }
  869. void CMineWnd::OnPaint() 
  870. {
  871. CPaintDC dc(this);    // 用以屏幕显示的设备
  872. CDC dcMemory;  // 内存设备
  873. CBitmap bitmap;
  874. if (!dc.IsPrinting()) 
  875. {
  876. // 与dc设备兼容
  877. if (dcMemory.CreateCompatibleDC(&dc))
  878. {
  879. // 使得bitmap与实际显示的设备兼容
  880. if (bitmap.CreateCompatibleBitmap(&dc, m_rcClient.right, m_rcClient.bottom))
  881. {
  882. // 内存设备选择物件-位图
  883. dcMemory.SelectObject(&bitmap);
  884. //绘制背景框
  885. dcMemory.FillRect(&m_rcClient, &m_brsBG);
  886. DrawButton((CPaintDC&) dcMemory);//笑脸按钮绘图
  887. DrawNumber((CPaintDC&) dcMemory);//文字绘图(计时器文字和剩余雷数文字)
  888. DrawShell((CPaintDC&) dcMemory);//3D效果外壳绘图
  889. DrawMineArea((CPaintDC&) dcMemory);//雷区绘图
  890. // 将内存设备的内容拷贝到实际屏幕显示的设备
  891. dc.BitBlt(m_rcClient.left, m_rcClient.top, m_rcClient.right, m_rcClient.bottom, &dcMemory, 0, 0, SRCCOPY);
  892. bitmap.DeleteObject();
  893. }
  894. }
  895. }
  896. }
  897. void CMineWnd::OnShowWindow(BOOL bShow, UINT nStatus) 
  898. {
  899. SizeWindow();
  900. CWnd::OnShowWindow(bShow, nStatus);
  901. }
  902. void CMineWnd::OnTimer(UINT nIDEvent) 
  903. {
  904. if (nIDEvent == ID_TIMER_EVENT)
  905. {
  906. if (m_bSoundful) 
  907. {
  908. sndPlaySound((LPCTSTR)LockResource(m_pSndClock), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
  909. }
  910. m_uSpendTime++;
  911. CRect rcNum(m_uNumRect[0], 15, m_uNumRect[1], 39);
  912. // InvalidateRect(rcNum);
  913. Invalidate();
  914. if (m_uSpendTime >= DEFAULT_RECORD) 
  915. {
  916. KillTimer(ID_TIMER_EVENT);
  917. m_uTimer = 0;
  918. }
  919. }
  920. CWnd::OnTimer(nIDEvent);
  921. }
  922. void CMineWnd::OnLButtonDown(UINT nFlags, CPoint point) 
  923. {
  924. //按钮所在的区域
  925. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  926. //雷区所在的区域
  927. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  928. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  929. SetCapture(); // capture the mouse cursor
  930. m_bClickBtn = FALSE;
  931. m_bLRBtnDown = FALSE;
  932. if (rcBtn.PtInRect(point)) 
  933. {// click in the button area
  934. m_bClickBtn = TRUE;
  935. m_uBtnState = BUTTON_DOWN;
  936. InvalidateRect(rcBtn);
  937. }
  938. else if (rcMineArea.PtInRect(point))
  939. {// click in the mine area
  940. // change mine state by gamestate
  941. switch(m_uGameState) 
  942. {
  943. case GS_WAIT: case GS_RUN:
  944. m_pNewMine = GetMine(point.x, point.y);
  945. if (!m_pNewMine) return;
  946. if (m_pNewMine->uState == STATE_NORMAL)
  947. {
  948. m_pNewMine->uState = STATE_EMPTY;
  949. }
  950. if (m_pNewMine->uState == STATE_DICEY)
  951. {
  952. m_pNewMine->uState = STATE_DICEY_DOWN;
  953. }
  954. m_pOldMine = m_pNewMine;
  955. break;
  956. case GS_DEAD: case GS_VICTORY:
  957. return;
  958. break;
  959. default :
  960. break;
  961. }
  962. m_uBtnState = BUTTON_CLICK;
  963. InvalidateRect(rcBtn);
  964. // both of the left button and the right button are pushing down 
  965. if (nFlags == (MK_LBUTTON | MK_RBUTTON)) 
  966. {
  967. m_bLRBtnDown = TRUE;
  968. OnLRBtnDown(m_pOldMine->uRow, m_pOldMine->uCol);
  969. }
  970. InvalidateRect(rcMineArea);
  971. }
  972. else 
  973. { // click in other area
  974. if (m_uGameState == GS_WAIT || m_uGameState == GS_RUN)
  975. {
  976. m_uBtnState = BUTTON_CLICK;
  977. InvalidateRect(rcBtn);
  978. }
  979. }
  980. CWnd::OnLButtonDown(nFlags, point);
  981. }
  982. void CMineWnd::OnLButtonUp(UINT nFlags, CPoint point) 
  983. {
  984. //笑脸图按钮所在的区域
  985. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  986. //雷区所在的区域
  987. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  988. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, 
  989. MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  990. if (rcBtn.PtInRect(point)) 
  991. {// 点击笑脸图
  992. Invalidate();
  993. InitGame();
  994. }
  995. else if (rcMineArea.PtInRect(point)) 
  996. {//点击雷区域
  997. CString value;
  998. UINT around = 0;
  999. //根据不同的游戏状态作处理
  1000. switch(m_uGameState) 
  1001. {
  1002. //游戏进行状态
  1003. case GS_WAIT: case GS_RUN:
  1004. // first get the MINEWND which if pushing down
  1005. m_pOldMine = GetMine(point.x, point.y);
  1006. if (!m_pOldMine) 
  1007. {
  1008. ReleaseCapture();
  1009. return;
  1010. }
  1011. // do normal process
  1012. // judge whether the lr button are both pushed down
  1013. //检测判断当前状态是否为左右鼠标同时按下
  1014. if (m_bLRBtnDown) 
  1015. {
  1016. m_bLRBtnDown = FALSE;
  1017. OnLRBtnUp(m_pOldMine->uRow, m_pOldMine->uCol);
  1018. if (m_uGameState == GS_WAIT)
  1019. {
  1020. m_uBtnState = BUTTON_NORMAL;
  1021. Invalidate();
  1022. ReleaseCapture();
  1023. return;
  1024. }
  1025. // if the around flags number equal to the around mines number, expand.
  1026. //假若周围已经标识的雷=周围真正的雷数,拓展
  1027. if (m_pOldMine->uState != STATE_FLAG)
  1028. {
  1029. OpenAround(m_pOldMine->uRow, m_pOldMine->uCol);
  1030. }
  1031. // check whether the MINEWND around the special MINEWND is a mine, if it is then dead.
  1032. if (ErrorAroundFlag(m_pOldMine->uRow, m_pOldMine->uCol))
  1033. {
  1034. Dead(m_pOldMine->uRow, m_pOldMine->uCol);
  1035. ReleaseCapture();
  1036. return;
  1037. }
  1038. }
  1039. else 
  1040. {
  1041. // start the game, init the mines area
  1042. //如果游戏尚未开始,点击左键启动游戏
  1043. if (m_uGameState == GS_WAIT) 
  1044. {
  1045. if (m_uTimer)
  1046. {
  1047. KillTimer(ID_TIMER_EVENT);
  1048. m_uTimer = 0;
  1049. }
  1050. // the following five lines refresh the remining mine num rect immediately 
  1051. // when click in the mine area at the first time
  1052. m_uSpendTime = 1;
  1053. Invalidate();
  1054. if (m_bSoundful) 
  1055. {
  1056. sndPlaySound((LPCTSTR)LockResource(m_pSndClock), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
  1057. }
  1058. //启动定时器
  1059. m_uTimer = SetTimer(ID_TIMER_EVENT, 1000, NULL);
  1060. //布雷
  1061. LayMines(m_pOldMine->uRow, m_pOldMine->uCol); // lay all the mines down 
  1062. //改变游戏状态为"运行/GS_RUN"
  1063. m_uGameState = GS_RUN;
  1064. }
  1065. if (m_pOldMine->uOldState == STATE_NORMAL)
  1066. {//当该雷区域为正常未作标记才打开
  1067. // first judge if the special MINEWND is a mine
  1068. //如果该区域为雷,则死亡
  1069. if (IsMine(m_pOldMine->uRow, m_pOldMine->uCol)) 
  1070. {
  1071. Dead(m_pOldMine->uRow, m_pOldMine->uCol);
  1072. ReleaseCapture();
  1073. return;
  1074. }
  1075. // the special MINEWND is not a mine 
  1076. //不是雷的时候,获取其周围的雷数目
  1077. around = GetAroundNum(m_pOldMine->uRow, m_pOldMine->uCol);
  1078. // 如果为空白区域,拓展,否则打开该区域(显示周围有多少雷数)
  1079. if (around == 0) ExpandMines(m_pOldMine->uRow, m_pOldMine->uCol);
  1080. else DrawDownNum(m_pOldMine, around);
  1081. }
  1082. else if (m_pOldMine->uOldState == STATE_DICEY)
  1083. {//标志为“?”问号的时候
  1084. m_pOldMine->uState = STATE_DICEY;
  1085. }
  1086. //判断是否为胜利
  1087. if (Victory())
  1088. {
  1089. Invalidate();
  1090. ReleaseCapture();
  1091. return;
  1092. }
  1093. }
  1094. break;
  1095. case GS_VICTORY:
  1096. case GS_DEAD:
  1097. ReleaseCapture(); // release the cursor
  1098. return;
  1099. default :
  1100. break;
  1101. }
  1102. m_uBtnState = BUTTON_NORMAL;
  1103. Invalidate();
  1104. }
  1105. else 
  1106. {//点击非雷区域
  1107. if (m_uGameState == GS_WAIT || m_uGameState == GS_RUN)
  1108. {
  1109. m_uBtnState = BUTTON_NORMAL;
  1110. InvalidateRect(rcBtn);
  1111. }
  1112. }
  1113. ReleaseCapture(); // release the cursor
  1114. CWnd::OnLButtonUp(nFlags, point);
  1115. }
  1116. void CMineWnd::OnRButtonDown(UINT nFlags, CPoint point) 
  1117. {
  1118. //笑脸图按钮所在的区域
  1119. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  1120. //雷区所在的区域
  1121. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  1122. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, 
  1123. MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  1124. m_bLRBtnDown = FALSE;
  1125. if (rcMineArea.PtInRect(point)) 
  1126. {//点击雷区域
  1127. if (m_uGameState == GS_WAIT || m_uGameState == GS_RUN) 
  1128. {
  1129. m_pNewMine = GetMine(point.x, point.y);
  1130. if (!m_pNewMine) return;
  1131. // both of the left button and the right button are pushing down 
  1132. if (nFlags == (MK_LBUTTON | MK_RBUTTON))
  1133. {
  1134. m_bLRBtnDown = TRUE;
  1135. OnLRBtnDown(m_pNewMine->uRow, m_pNewMine->uCol);
  1136. }
  1137. else
  1138. {
  1139. switch(m_pNewMine->uState) 
  1140. {
  1141. case STATE_NORMAL:
  1142. m_pNewMine->uState = STATE_FLAG;
  1143. m_pNewMine->uOldState = STATE_FLAG;
  1144. m_nLeaveNum--;
  1145. break;
  1146. case STATE_FLAG:
  1147. m_pNewMine->uState = STATE_DICEY;
  1148. m_pNewMine->uOldState = STATE_DICEY;
  1149. m_nLeaveNum++;
  1150. break;
  1151. case STATE_DICEY:
  1152. m_pNewMine->uState = STATE_NORMAL;
  1153. m_pNewMine->uOldState = STATE_NORMAL;
  1154. break;
  1155. default: 
  1156. break;
  1157. }
  1158. }
  1159. Invalidate();
  1160. }
  1161. }
  1162. CWnd::OnRButtonDown(nFlags, point);
  1163. }
  1164. void CMineWnd::OnRButtonUp(UINT nFlags, CPoint point) 
  1165. {
  1166. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  1167. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  1168. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  1169. m_pOldMine = GetMine(point.x, point.y);
  1170. if (!m_pOldMine) return;
  1171. // judge whether the lr button are both pushed down
  1172. if (m_bLRBtnDown) 
  1173. {
  1174. m_bLRBtnDown = FALSE;
  1175. OnLRBtnUp(m_pOldMine->uRow, m_pOldMine->uCol);
  1176. if (m_uGameState == GS_WAIT) 
  1177. {
  1178. m_uBtnState = BUTTON_NORMAL;
  1179. Invalidate();
  1180. return;
  1181. }
  1182. // if the around flags number equal to the around mines number, expand.
  1183. if (m_pOldMine->uState != STATE_FLAG)
  1184. {
  1185. OpenAround(m_pOldMine->uRow, m_pOldMine->uCol);
  1186. }
  1187. // check whether the MINEWND around the special MINEWND is a mine, if it is then dead.
  1188. if (ErrorAroundFlag(m_pOldMine->uRow, m_pOldMine->uCol))
  1189. {
  1190. // Dead(m_pOldMine->uRow, m_pOldMine->uCol);
  1191. // ReleaseCapture();
  1192. return;
  1193. }
  1194. }
  1195. else
  1196. {
  1197. Victory();
  1198. }
  1199. CWnd::OnRButtonUp(nFlags, point);
  1200. }
  1201. void CMineWnd::OnMouseMove(UINT nFlags, CPoint point) 
  1202. {
  1203. if (nFlags == MK_LBUTTON || nFlags == (MK_LBUTTON | MK_RBUTTON))
  1204. {
  1205. CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
  1206. CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP, 
  1207. MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
  1208. if (rcBtn.PtInRect(point)) 
  1209. { // point in button area
  1210. switch(m_uGameState)
  1211. {
  1212. case GS_RUN:
  1213. m_uBtnState = (m_bClickBtn) ? BUTTON_DOWN : BUTTON_CLICK;
  1214. break;
  1215. case GS_DEAD: case GS_VICTORY:
  1216. if (m_bClickBtn) m_uBtnState = BUTTON_DOWN;
  1217. break;
  1218. default: 
  1219. break;
  1220. }
  1221. InvalidateRect(rcBtn);
  1222. }
  1223. else if (rcMineArea.PtInRect(point)) 
  1224. { // point in mine area
  1225. switch(m_uGameState) 
  1226. {
  1227. case GS_RUN:
  1228. m_pNewMine = GetMine(point.x, point.y);
  1229. if (!m_pNewMine || !m_pOldMine) return;
  1230. if (m_pNewMine->uCol != m_pOldMine->uCol ||
  1231. m_pNewMine->uRow != m_pOldMine->uRow) 
  1232. {
  1233. // change the new mine rect state
  1234. switch(m_pNewMine->uState)
  1235. {
  1236. case STATE_NORMAL:
  1237. m_pNewMine->uState = STATE_EMPTY;
  1238. break;
  1239. case STATE_DICEY:
  1240. m_pNewMine->uState = STATE_DICEY_DOWN;
  1241. break;
  1242. }
  1243. // resume the old mine rect state
  1244. switch(m_pOldMine->uOldState) 
  1245. {
  1246. case STATE_NORMAL:
  1247. m_pOldMine->uState = STATE_NORMAL;
  1248. break;
  1249. case STATE_DICEY:
  1250. m_pOldMine->uState = STATE_DICEY;
  1251. break;
  1252. default :
  1253. break;
  1254. }
  1255. // judge whether the lr button are pushed down
  1256. if (m_bLRBtnDown) 
  1257. {
  1258. OnLRBtnUp(m_pOldMine->uRow, m_pOldMine->uCol);
  1259. OnLRBtnDown(m_pNewMine->uRow, m_pNewMine->uCol);
  1260. }
  1261. m_pOldMine = m_pNewMine;
  1262. }
  1263. InvalidateRect(rcMineArea);
  1264. break;
  1265. case GS_VICTORY: case GS_DEAD:
  1266. return;
  1267. default: 
  1268. break;
  1269. }
  1270. }
  1271. else
  1272. { // point in other area
  1273. switch(m_uGameState) 
  1274. {
  1275.  case GS_RUN:
  1276. m_uBtnState = (m_bClickBtn) ? BUTTON_NORMAL : BUTTON_CLICK;
  1277. if (m_pNewMine) 
  1278. {
  1279. if (m_pNewMine->uOldState == STATE_NORMAL)
  1280. {
  1281. m_pNewMine->uState = STATE_NORMAL;
  1282. }
  1283. else if (m_pNewMine->uOldState == STATE_DICEY)
  1284. {
  1285. m_pNewMine->uState = STATE_DICEY;
  1286. }
  1287. }
  1288. break;
  1289. case GS_DEAD: 
  1290. m_uBtnState = BUTTON_DEAD;
  1291. break;
  1292. case GS_VICTORY:
  1293. m_uBtnState = BUTTON_VICTORY;
  1294. break;
  1295. default: 
  1296. break;
  1297. }
  1298. Invalidate();
  1299. }
  1300. }
  1301. CWnd::OnMouseMove(nFlags, point);
  1302. }
  1303. void CMineWnd::OnMemuStart() 
  1304. {
  1305. InitGame();
  1306. Invalidate();
  1307. }
  1308. void CMineWnd::OnMemuPrimary() 
  1309. {
  1310. m_uLevel = LEVEL_PRIMARY;
  1311. m_uXNum = PRIMARY_XNUM;
  1312. m_uYNum = PRIMARY_YNUM;
  1313. m_uMineNum = PRIMARY_MINENUM;
  1314. SetCheckedLevel();
  1315. InitGame();
  1316. Invalidate();
  1317. SizeWindow();
  1318. }
  1319. void CMineWnd::OnMemuSecond() 
  1320. {
  1321. m_uLevel = LEVEL_SECONDRY;
  1322. m_uXNum = SECONDRY_XNUM;
  1323. m_uYNum = SECONDRY_YNUM;
  1324. m_uMineNum = SECONDRY_MINENUM;
  1325. SetCheckedLevel();
  1326. InitGame();
  1327. Invalidate();
  1328. SizeWindow();
  1329. }
  1330. void CMineWnd::OnMemuAdvance() 
  1331. {
  1332. m_uLevel = LEVEL_ADVANCE;
  1333. m_uXNum = ADVANCE_XNUM;
  1334. m_uYNum = ADVANCE_YNUM;
  1335. m_uMineNum = ADVANCE_MINENUM;
  1336. SetCheckedLevel();
  1337. InitGame();
  1338. Invalidate();
  1339. SizeWindow();
  1340. }
  1341. void CMineWnd::OnMemuCustom() 
  1342. {
  1343. m_uLevel = LEVEL_CUSTOM;
  1344. SetCheckedLevel();
  1345. CDlgCustom dlg;
  1346. dlg.InitData(m_uXNum, m_uYNum, m_uMineNum);
  1347. dlg.DoModal();
  1348. InitGame();
  1349. Invalidate();
  1350. SizeWindow();
  1351. }
  1352. void CMineWnd::OnMemuCheat() 
  1353. {
  1354. // m_bCheat = !m_bCheat;
  1355. // SetCheckedCheat();
  1356. // Invalidate();
  1357. }
  1358. void CMineWnd::OnMemuMark() 
  1359. {
  1360. m_bMarkful = !m_bMarkful;
  1361. SetCheckedMark();
  1362. Invalidate();
  1363. }
  1364. void CMineWnd::OnMemuColor() 
  1365. {
  1366. m_bColorful = !m_bColorful;
  1367. LoadBitmap();
  1368. SetCheckedColor();
  1369. Invalidate();
  1370. }
  1371. void CMineWnd::OnMemuSound() 
  1372. {
  1373. m_bSoundful = !m_bSoundful;
  1374. SetCheckedSound();
  1375. if (m_bSoundful) 
  1376. {
  1377. LoadWaveSrc();
  1378. }
  1379. else
  1380. {
  1381. FreeWaveSrc();
  1382. }
  1383. }
  1384. void CMineWnd::OnMemuHero() 
  1385. {
  1386. CDlgHero dlg;
  1387. dlg.SetBRecord(m_uPrimary);
  1388. dlg.SetBHolder(m_szPrimary);
  1389. dlg.SetIRecord(m_uSecond);
  1390. dlg.SetIHolder(m_szSecond);
  1391. dlg.SetERecord(m_uAdvance);
  1392. dlg.SetEHolder(m_szAdvance);
  1393. dlg.DoModal();
  1394. }
  1395. void CMineWnd::OnMemuExit() 
  1396. {
  1397. PostQuitMessage(0);
  1398. }
  1399. void CMineWnd::OnMemuHelpList() 
  1400. {
  1401. ::WinExec("HH WINMINE.CHM", SW_SHOW);
  1402. }
  1403. void CMineWnd::OnMemuHelpFind() 
  1404. {
  1405. ::WinExec("HH WINMINE.CHM", SW_SHOW);
  1406. }
  1407. void CMineWnd::OnMemuHelpUse() 
  1408. {
  1409. ::WinExec("HH NTHelp.CHM", SW_SHOW);
  1410. }
  1411. void CMineWnd::OnMemuAbout() 
  1412. {
  1413. ShellAbout(this->m_hWnd, "扫雷", "skybluehacker@yahoo.com.cn",NULL);
  1414. }
  1415. void CMineWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  1416. {
  1417. switch(nChar)
  1418. {
  1419. case VK_F1:
  1420. OnMemuHelpList();
  1421. break;
  1422. case VK_F2:
  1423. OnMemuStart();
  1424. break;
  1425. default: 
  1426. break;
  1427. }
  1428. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  1429. }
  1430. void CMineWnd::OnInitMenu(CMenu* pMenu) 
  1431. {
  1432. CWnd::OnInitMenu(pMenu);
  1433. if ((m_pSubMenu = pMenu->GetSubMenu(0)) == 0) 
  1434. {
  1435. AfxMessageBox("初始化菜单失败!");
  1436. PostQuitMessage(0);
  1437. }
  1438. else
  1439. {
  1440. SetCheckedLevel();
  1441. SetCheckedMark();
  1442. SetCheckedColor();
  1443. SetCheckedSound();
  1444. // SetCheckedCheat();
  1445. }
  1446. }
  1447. void CMineWnd::OnMemuClose() 
  1448. {
  1449. SaveConfig();
  1450. KillTimer(ID_TIMER_EVENT);
  1451. CWnd::OnClose();
  1452. }