skyblue_RectView.cpp
上传用户:szfskj
上传日期:2022-03-28
资源大小:3962k
文件大小:40k
源码类别:

其他游戏

开发平台:

Visual C++

  1. // skyblue_RectView.cpp : implementation of the CSkyblue_RectView class
  2. //
  3. #include "stdafx.h"
  4. #include "skyblue_Rect.h"
  5. #include "skyblue_RectDoc.h"
  6. #include "skyblue_RectView.h"
  7. #include "OptionDlg.h"
  8. //音乐播放
  9. #include "mmsystem.h"
  10. #pragma comment(lib,"Winmm.lib")
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CSkyblue_RectView
  18. IMPLEMENT_DYNCREATE(CSkyblue_RectView, CView)
  19. BEGIN_MESSAGE_MAP(CSkyblue_RectView, CView)
  20. //{{AFX_MSG_MAP(CSkyblue_RectView)
  21. ON_COMMAND(ID_GAME_EXIT, OnGameExit)
  22. ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
  23. //}}AFX_MSG_MAP
  24. // Standard printing commands
  25. ON_WM_KEYDOWN()
  26. ON_WM_TIMER()
  27. ON_COMMAND(ID_GAME_START, OnGameStart)
  28. ON_COMMAND(ID_GAME_END, OnGameEnd)
  29. ON_COMMAND(ID_GAME_OPTION, OnGameOption)
  30. ON_UPDATE_COMMAND_UI(ID_GAME_START, OnUpdateGameStart)
  31. ON_UPDATE_COMMAND_UI(ID_GAME_OPTION, OnUpdateGameOption)
  32. ON_UPDATE_COMMAND_UI(ID_GAME_END, OnUpdateGameEnd)
  33. ON_UPDATE_COMMAND_UI(ID_GAME_EXIT, OnUpdateGameExit)
  34. ON_UPDATE_COMMAND_UI(ID_HELP_ABOUT, OnUpdateHelpAbout)
  35. ON_UPDATE_COMMAND_UI(ID_HELP_HELP, OnUpdateHelpHelp)
  36. ON_WM_CREATE()
  37. ON_COMMAND(ID_HELP_HELP, OnHelpHelp)
  38. ON_UPDATE_COMMAND_UI(ID_OPTION_AREA1, OnUpdateOptionArea1)
  39. ON_UPDATE_COMMAND_UI(ID_OPTION_AREA2, OnUpdateOptionArea2)
  40. ON_UPDATE_COMMAND_UI(ID_OPTION_AREA3, OnUpdateOptionArea3)
  41. ON_UPDATE_COMMAND_UI(ID_OPTION_AREA4, OnUpdateOptionArea4)
  42. ON_COMMAND(ID_OPTION_AREA1, OnOptionArea1)
  43. ON_COMMAND(ID_OPTION_AREA2, OnOptionArea2)
  44. ON_COMMAND(ID_OPTION_AREA3, OnOptionArea3)
  45. ON_COMMAND(ID_OPTION_AREA4, OnOptionArea4)
  46. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL1, OnUpdateOptionLevel1)
  47. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL2, OnUpdateOptionLevel2)
  48. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL3, OnUpdateOptionLevel3)
  49. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL4, OnUpdateOptionLevel4)
  50. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL5, OnUpdateOptionLevel5)
  51. ON_UPDATE_COMMAND_UI(ID_OPTION_LEVEL6, OnUpdateOptionLevel6)
  52. ON_COMMAND(ID_OPTION_LEVEL1, OnOptionLevel1)
  53. ON_COMMAND(ID_OPTION_LEVEL2, OnOptionLevel2)
  54. ON_COMMAND(ID_OPTION_LEVEL3, OnOptionLevel3)
  55. ON_COMMAND(ID_OPTION_LEVEL4, OnOptionLevel4)
  56. ON_COMMAND(ID_OPTION_LEVEL5, OnOptionLevel5)
  57. ON_COMMAND(ID_OPTION_LEVEL6, OnOptionLevel6)
  58. ON_UPDATE_COMMAND_UI(ID_OPTION_GRID, OnUpdateOptionGrid)
  59. ON_COMMAND(ID_OPTION_GRID, OnOptionGrid)
  60. ON_UPDATE_COMMAND_UI(ID_OPTION_MUSIC, OnUpdateOptionMusic)
  61. ON_COMMAND(ID_OPTION_MUSIC, OnOptionMusic)
  62. ON_UPDATE_COMMAND_UI(ID_GAME_PAUSH, OnUpdateGamePaush)
  63. ON_COMMAND(ID_GAME_PAUSH, OnGamePaush)
  64. END_MESSAGE_MAP()
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CSkyblue_RectView construction/destruction
  67. CSkyblue_RectView::CSkyblue_RectView()
  68. {
  69. //第一次开始游戏
  70. m_bFistPlay = TRUE;
  71. //缺省为不是游戏暂停状态
  72. m_bGamePaush = FALSE;
  73. //缺省为不插放背景音乐
  74. m_bMusic = FALSE;
  75. //缺省为画网格线
  76. m_bDrawGrid = TRUE;
  77. //总分值清零
  78. m_iPerformance = 0;
  79. //测试值:为12行,10列
  80. m_iRow = 12;
  81. m_iCol = 10;
  82. //左上角X,Y坐标
  83. m_iStartX = 10;
  84. m_iStartY = 10;
  85. //缺省级别为3级
  86. m_iLevel = 2;
  87. //第一种样式
  88. m_iBlockSytle = 0;
  89. //缺省方块大小为m_iLarge个象素
  90. m_iLarge = 30;
  91. //缺省游戏是结束的
  92. m_bGameEnd = TRUE;
  93. int i,j;
  94. //赋初值
  95. for (i=0;i<100;i++)
  96. for (j=0;j<100;j++)
  97. GameStatus[i][j]=0;
  98. //各种形状方块的接触面数据,参见设计书的接触面表格, 
  99. //如果某种形状的方块没有4个接触面,则后面的数据填-1
  100. for (i=0;i<74;i++)
  101. for (j=0;j<4;j++)
  102. InterFace[i][j] = -1;
  103. /*
  104. 1  ----
  105. */
  106. InterFace[1][0] = 3;
  107. InterFace[11][0] = 0; InterFace[11][1] = 1; InterFace[11][2] = 2; InterFace[11][3] = 3;
  108. /*
  109. 2 --
  110. --
  111. */  
  112. InterFace[2][0] = 1; InterFace[2][1] = 3;
  113. /*
  114. 3   -
  115.    ---
  116. */
  117. InterFace[3][0] = 0; InterFace[3][1] = 2; InterFace[3][2] = 3;
  118. InterFace[31][0] = 2; InterFace[31][1] = 3;
  119. InterFace[32][0] = 0; InterFace[32][1] = 2; InterFace[32][2] = 3;
  120. InterFace[33][0] = 0; InterFace[33][1] = 3;
  121. /*
  122. 4  --
  123.   --
  124. */
  125. InterFace[4][0] = 1; InterFace[4][1] = 3;
  126. InterFace[41][0] = 0; InterFace[41][1] = 2; InterFace[41][2] = 3;
  127. /*
  128. 5  --
  129.     --
  130. */
  131. InterFace[5][0] = 1; InterFace[5][1] = 3;
  132. InterFace[51][0] = 0; InterFace[51][1] = 2; InterFace[51][2] = 3;
  133. /*
  134. 6  --
  135.     -
  136. -
  137. */
  138. InterFace[6][0] = 0; InterFace[6][1] = 3;
  139. InterFace[61][0] = 1; InterFace[61][1] = 2; InterFace[61][2] = 3;
  140. InterFace[62][0] = 2; InterFace[62][1] = 3;
  141. InterFace[63][0] = 0; InterFace[63][1] = 1; InterFace[63][2] = 3;
  142. /*
  143. 7  --
  144.    -
  145.    -
  146. */
  147. InterFace[7][0] = 2; InterFace[7][1] = 3;
  148. InterFace[71][0] = 1; InterFace[71][1] = 2; InterFace[71][2] = 3;
  149. InterFace[72][0] = 0; InterFace[72][1] = 3;
  150. InterFace[73][0] = 0; InterFace[73][1] = 1; InterFace[73][2] = 3;
  151. }
  152. CSkyblue_RectView::~CSkyblue_RectView()
  153. {
  154. }
  155. BOOL CSkyblue_RectView::PreCreateWindow(CREATESTRUCT& cs)
  156. {
  157. // TODO: Modify the Window class or styles here by modifying
  158. //  the CREATESTRUCT cs
  159. return CView::PreCreateWindow(cs);
  160. }
  161. /////////////////////////////////////////////////////////////////////////////
  162. // CSkyblue_RectView drawing
  163. //创建一些设备
  164. int CSkyblue_RectView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  165. {
  166. if (CView::OnCreate(lpCreateStruct) == -1)
  167. return -1;
  168. //决定第一次掉下来的方块的样式
  169. m_inextStatus = Random(7);
  170. return 0;
  171. }
  172. /* * * * * * * * * * * * * * * * * * * * * * * * *
  173. *
  174. *  名称:OnDraw
  175. *
  176. *  功能:承担所有绘制屏幕工作
  177. *
  178. *  最后修改时间:2005.8.6
  179. *
  180. * * * * * * * * * * * * * * * * * * * * * * * * */
  181. void CSkyblue_RectView::OnDraw(CDC* pDC)
  182. {
  183. DcEnvInitial();
  184. DrawGame(&m_memDC);  //在内存位图的游戏区域绘制
  185. pDC->BitBlt(0,0,m_nWidth,m_nHeight,&m_memDC,0,0,SRCCOPY);
  186. }
  187. //
  188. //绘图设备环境的初始化
  189. //
  190. void CSkyblue_RectView::DcEnvInitial(void)
  191. {
  192. if(m_bFistPlay)
  193. {
  194. m_bFistPlay = FALSE;
  195. //用默认的参数,获取当前屏幕设备环境
  196. CDC *pWindowDC = GetDC();
  197. //1.用于映射屏幕的内存设备环境
  198. //获取游戏窗口的大小用于下面设置内存位图的尺寸
  199. CRect windowRect;
  200. GetClientRect(&windowRect);
  201. m_nWidth = windowRect.Width();
  202. m_nHeight = windowRect.Height();
  203. //内存设备环境与屏幕设备环境关联(兼容)
  204. m_memDC.CreateCompatibleDC(pWindowDC);
  205. //内存位图与与屏幕关联(兼容),大小为游戏窗口的尺寸
  206. m_memBmp.CreateCompatibleBitmap(pWindowDC,m_nWidth,m_nHeight);
  207. //内存设备环境与内存位图关联,以便通过m_memDC在内存位图上作画
  208. m_memDC.SelectObject(&m_memBmp);
  209. //2.存储方块位图的内存资源
  210. //内存设备环境与屏幕设备环境关联(兼容)
  211. m_memRectDC.CreateCompatibleDC(pWindowDC);
  212. //相当于将外部位图rect.bmp动态载入m_hMemRectBmp中
  213. m_hMemRectBmp=(HBITMAP)LoadImage(NULL,"rect.bmp",IMAGE_BITMAP,150,30,LR_LOADFROMFILE);
  214. //内存设备环境与内存位图关联,以便通过m_memDC在内存位图上作画
  215. SelectObject(m_memRectDC.m_hDC, m_hMemRectBmp);
  216. //黑色的黑笔
  217. m_pBlackPen  = new CPen(PS_SOLID,1,BLACK);
  218. //画刷
  219. m_pGrayBrush  = new CBrush(RGB(66,66,66));
  220. m_pBlackBrush  = new CBrush(BLACK);
  221. }
  222. }
  223. void CSkyblue_RectView::DCEnvClear(void)
  224. {
  225. //设备环境
  226. m_memDC.DeleteDC();
  227. m_memRectDC.DeleteDC();
  228. //位图资源
  229. DeleteObject(m_memBmp);
  230. DeleteObject(m_hMemRectBmp);
  231. delete(m_pBlackPen);
  232. delete(m_pGrayBrush);
  233. delete(m_pBlackBrush);
  234. }
  235. void CSkyblue_RectView::DrawGame(CDC *pDC)
  236. {
  237. int i,j;
  238. //选用黑色画刷,绘制整个游戏所在窗口的背景
  239. pDC -> SelectObject(m_pBlackBrush);
  240. CRect rect;
  241. GetClientRect(&rect);
  242. pDC -> Rectangle(rect);
  243. //选用灰色画刷,绘制游戏区域的背景
  244. pDC -> SelectObject(m_pGrayBrush);
  245. pDC -> Rectangle(m_iStartY ,m_iStartX, m_iStartY + 301, m_iStartX + 360);
  246. pDC->SelectObject(m_pBlackPen);
  247. //画网格线
  248. if (m_bDrawGrid)
  249. {
  250. //画横线
  251. for (i=0;i<m_iRow;i++)
  252. {
  253. pDC->MoveTo(m_iStartY, m_iStartX + i*m_iLarge);
  254. pDC->LineTo(m_iStartY+300, m_iStartX +i*m_iLarge);
  255. }
  256. //画竖线
  257. for (i=0;i<m_iCol;i++)
  258. {
  259. pDC->MoveTo(m_iStartY+i*m_iLarge, m_iStartX);
  260. pDC->LineTo(m_iStartY+i*m_iLarge, m_iStartX+360);
  261. }
  262. }
  263. int x,y,nW,nH;
  264. //小方块的绘制
  265. for (i=0;i<m_iRow;i++)
  266. for (j=0;j<m_iCol;j++)
  267. {
  268. if (GameStatus[i][j]==MAP_STATE_NOT_EMPTY)
  269. {
  270. //在游戏区域中状态为被占用状态的区域绘制小方块
  271. x = m_iStartY+j*m_iLarge +2;
  272. y = m_iStartX+i*m_iLarge +2;
  273. nW = m_iLarge-4;
  274. nH = m_iLarge-4;
  275. pDC->BitBlt(x,y,nW,nH,&m_memRectDC,m_iBlockSytle*30,0,SRCCOPY);
  276. }
  277. }
  278. //显示游戏区域及游戏级别的汉字描述
  279. if (!m_bGameEnd)
  280. {
  281. pDC -> SetBkColor(BLACK);
  282. pDC -> SetTextColor(WHITE);
  283. pDC -> TextOut(m_iStartY+320, m_iStartX+220, "游戏区域大小:");
  284. pDC -> TextOut(m_iStartY+320, m_iStartX+240,m_strArea);
  285. pDC -> TextOut(m_iStartY+320, m_iStartX+280, "游戏级别:");
  286. pDC -> TextOut(m_iStartY+320, m_iStartX+300,m_strLevel);
  287. }
  288. //显示总分
  289. if (!m_bGameEnd)
  290. {
  291. CString lsStr;
  292. lsStr.Format("总分为:%d 分",m_iPerformance);
  293. pDC -> SetBkColor(BLACK);
  294. pDC -> SetTextColor(WHITE);
  295. pDC -> TextOut(m_iStartY+320, m_iStartX+180,lsStr);
  296. }
  297. //画下一次将要出现的方块,用于提示用户
  298. if (!m_bGameEnd)
  299. {
  300. pDC -> SetBkColor(BLACK);
  301. pDC -> SetTextColor(WHITE);
  302. pDC -> TextOut(m_iStartY+320, m_iStartX,"下一个方块:");
  303. int x,y,nW,nH;
  304. for (UINT k=0;k<4;k++)
  305. {
  306. i = NextStatus[k][0];
  307.     j = NextStatus[k][1];
  308. x = m_iStartY+j*30 +2+320;
  309. y = m_iStartX+i*30 +2+30;
  310. nW = m_iLarge-4;
  311. nH = m_iLarge-4;
  312. pDC->BitBlt(x,y,nW,nH,&m_memRectDC,m_iBlockSytle*30,0,SRCCOPY);
  313. }
  314. }
  315. }
  316. /* * * * * * * * * * * * * * * * * * * * * * * * *
  317. *
  318. *  名称:OnTimer
  319. *
  320. *  功能:承担所有驱动工作
  321. *
  322. *  最后修改时间:2005.8.6
  323. *
  324. * * * * * * * * * * * * * * * * * * * * * * * * */
  325. void CSkyblue_RectView::OnTimer(UINT nIDEvent) 
  326. {
  327. //如果原来的方块已到底或游戏刚开始,则掉下一个新的方块
  328. int i,j,k;
  329. if (m_isBottom)
  330. {
  331. //1.产生下一个随机下坠物
  332. m_icurrentStatus = m_inextStatus;
  333. m_inextStatus = Random(7);  //得到下一次的方块样式
  334. // if (m_inextStatus==0) m_inextStatus++;
  335. //2.修改新的“下一下坠物”
  336. RectStatusToNextStatus( m_inextStatus );
  337. // CRect rect(m_iStartY+320, m_iStartX, m_iStartY+440, m_iStartX+160);
  338. // InvalidateRect(&rect);
  339. // Invalidate(FALSE);
  340. //3.将旧的“下一下坠物”用作当前使用
  341. m_currentRect = m_icurrentStatus;   
  342. //根据当前下坠物的形状去初始化激活状态下的下坠物坐标
  343. RectStatusToActiveStatus( m_icurrentStatus );
  344. //将当前动态数组中的数据反映到大数组中
  345. ActiveStatusToGameStatus();
  346. m_isBottom = FALSE;
  347. //4.判断当前方块是否已到底
  348. IsBottom();
  349.      //5.判断游戏是否已结束: 碰了底,且第1行有小方块
  350. if (m_isBottom)
  351. for (i=0;i<m_iCol;i++)
  352. if (GameStatus[0][i])
  353. {
  354. KillTimer(1);
  355. AfxMessageBox("游戏已结束!");
  356. for (j=0;j<m_iRow;j++)
  357. for (k=0;k<m_iCol;k++)
  358. GameStatus[j][k]=0;
  359. Invalidate(FALSE);
  360. m_bGameEnd = TRUE;
  361. break;
  362. }
  363. }
  364. else  //当前方块下降
  365. {
  366. RectDown();
  367. }
  368. CView::OnTimer(nIDEvent);
  369. }
  370. /* * * * * * * * * * * * * * * * * * * * * *
  371. * 函数:产生一个最大值不大于指定值的随机正整数(Random)
  372. *
  373. * 参数:MaxNumber : 随机数的上限
  374. * 返回值: 产生的随机数
  375. *
  376. * 最后修改日期:2005.8.6
  377. * * * * * * * * * * * * * * * * * * * * * */
  378. int CSkyblue_RectView::Random(int MaxNumber)
  379. {
  380. //部下随机种子
  381. srand( (unsigned)time( NULL ) );
  382. //产生随机数
  383. int random = rand() % MaxNumber;
  384. //保证非0
  385. if(random == 0 ) random++;
  386. return random;
  387. }
  388. /* * * * * * * * * * * * * * * * * * * * * *
  389. * 内部函数:将当前下坠物的位置映射到游戏区域地图数组中去
  390. *
  391. * 最后修改日期:2005.8.6
  392. * * * * * * * * * * * * * * * * * * * * * */
  393. void CSkyblue_RectView::ActiveStatusToGameStatus()
  394. {
  395. int x1,x2,x3,x4,y1,y2,y3,y4;
  396. x1 = ActiveStatus[0][0];
  397. x2 = ActiveStatus[1][0];
  398. x3 = ActiveStatus[2][0];
  399. x4 = ActiveStatus[3][0];
  400. y1 = ActiveStatus[0][1];
  401. y2 = ActiveStatus[1][1];
  402. y3 = ActiveStatus[2][1];
  403. y4 = ActiveStatus[3][1];
  404. GameStatus[x1][y1]=MAP_STATE_NOT_EMPTY;
  405. GameStatus[x2][y2]=MAP_STATE_NOT_EMPTY;
  406. GameStatus[x3][y3]=MAP_STATE_NOT_EMPTY;
  407. GameStatus[x4][y4]=MAP_STATE_NOT_EMPTY;
  408. }
  409. /* * * * * * * * * * * * * * * * * * * * * *
  410. * 内部函数:初始掉落时,将根据方块的样式决定当前动态数组的值
  411. *
  412. * 最后修改日期:2005.8.6
  413. * * * * * * * * * * * * * * * * * * * * * */
  414. void CSkyblue_RectView::RectStatusToActiveStatus(int m_which)
  415. {
  416. switch(m_which)
  417. {
  418. case 1:   
  419. ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 1; ActiveStatus[1][1] = 5;
  420. ActiveStatus[2][0] = 2; ActiveStatus[2][1] = 5; ActiveStatus[3][0] = 3; ActiveStatus[3][1] = 5;
  421. break;
  422. case 2:    
  423. ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 1; ActiveStatus[1][1] = 5;
  424. ActiveStatus[2][0] = 0; ActiveStatus[2][1] = 6; ActiveStatus[3][0] = 1; ActiveStatus[3][1] = 6;
  425. break;
  426. case 3:
  427. ActiveStatus[0][0] = 1; ActiveStatus[0][1] = 4; ActiveStatus[1][0] = 0; ActiveStatus[1][1] = 5;
  428. ActiveStatus[2][0] = 1; ActiveStatus[2][1] = 5; ActiveStatus[3][0] = 1; ActiveStatus[3][1] = 6;
  429. break;
  430. case 4:
  431. ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 1; ActiveStatus[1][1] = 5;
  432. ActiveStatus[2][0] = 1; ActiveStatus[2][1] = 6; ActiveStatus[3][0] = 2; ActiveStatus[3][1] = 6;
  433. break;
  434. case 5:
  435. ActiveStatus[0][0] = 1; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 2; ActiveStatus[1][1] = 5;
  436. ActiveStatus[2][0] = 0; ActiveStatus[2][1] = 6; ActiveStatus[3][0] = 1; ActiveStatus[3][1] = 6;
  437. break;
  438. case 6:
  439. ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 0; ActiveStatus[1][1] = 6;
  440. ActiveStatus[2][0] = 1; ActiveStatus[2][1] = 6; ActiveStatus[3][0] = 2; ActiveStatus[3][1] = 6;
  441. break;
  442. case 7:
  443. ActiveStatus[0][0] = 0; ActiveStatus[0][1] = 5; ActiveStatus[1][0] = 1; ActiveStatus[1][1] = 5;
  444. ActiveStatus[2][0] = 2; ActiveStatus[2][1] = 5; ActiveStatus[3][0] = 0; ActiveStatus[3][1] = 6;
  445. break;
  446. }
  447. }
  448. /* * * * * * * * * * * * * * * * * * * * * *
  449. * 内部函数:初始掉落时,将根据方块的样式决定下一次将要掉下来的动态数组的值
  450. *
  451. * 最后修改日期:2005.8.6
  452. * * * * * * * * * * * * * * * * * * * * * */
  453. void CSkyblue_RectView::RectStatusToNextStatus(int m_which)
  454. {
  455. switch(m_which)
  456. {
  457. case 1:
  458. NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1;
  459. NextStatus[2][0] = 2; NextStatus[2][1] = 1; NextStatus[3][0] = 3; NextStatus[3][1] = 1;
  460. break;
  461. case 2:
  462. NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1;
  463. NextStatus[2][0] = 0; NextStatus[2][1] = 2; NextStatus[3][0] = 1; NextStatus[3][1] = 2;
  464. break;
  465. case 3:
  466. NextStatus[0][0] = 1; NextStatus[0][1] = 0; NextStatus[1][0] = 0; NextStatus[1][1] = 1;
  467. NextStatus[2][0] = 1; NextStatus[2][1] = 1; NextStatus[3][0] = 1; NextStatus[3][1] = 2;
  468. break;
  469. case 4:
  470. NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1;
  471. NextStatus[2][0] = 1; NextStatus[2][1] = 2; NextStatus[3][0] = 2; NextStatus[3][1] = 2;
  472. break;
  473. case 5:
  474. NextStatus[0][0] = 1; NextStatus[0][1] = 1; NextStatus[1][0] = 2; NextStatus[1][1] = 1;
  475. NextStatus[2][0] = 0; NextStatus[2][1] = 2; NextStatus[3][0] = 1; NextStatus[3][1] = 2;
  476. break;
  477. case 6:
  478. NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 0; NextStatus[1][1] = 2;
  479. NextStatus[2][0] = 1; NextStatus[2][1] = 2; NextStatus[3][0] = 2; NextStatus[3][1] = 2;
  480. break;
  481. case 7:
  482. NextStatus[0][0] = 0; NextStatus[0][1] = 1; NextStatus[1][0] = 1; NextStatus[1][1] = 1;
  483. NextStatus[2][0] = 2; NextStatus[2][1] = 1; NextStatus[3][0] = 0; NextStatus[3][1] = 2;
  484. break;
  485. }
  486. }
  487. /* * * * * * * * * * * * * * * * * * * * * *
  488. * 内部函数:当前方块下降
  489. *
  490. * 最后修改日期:2005.8.6
  491. * * * * * * * * * * * * * * * * * * * * * */
  492. void CSkyblue_RectView::RectDown()
  493. {
  494. IsBottom();
  495. if (!m_isBottom)
  496. {
  497. //清除以前的方块
  498. int x1,x2,x3,x4,y1,y2,y3,y4;
  499. x1 = ActiveStatus[0][0];
  500. x2 = ActiveStatus[1][0];
  501. x3 = ActiveStatus[2][0];
  502. x4 = ActiveStatus[3][0];
  503. y1 = ActiveStatus[0][1];
  504. y2 = ActiveStatus[1][1];
  505. y3 = ActiveStatus[2][1];
  506. y4 = ActiveStatus[3][1];
  507. GameStatus[x1][y1]=MAP_STATE_EMPTY;
  508. GameStatus[x2][y2]=MAP_STATE_EMPTY;
  509. GameStatus[x3][y3]=MAP_STATE_EMPTY;
  510. GameStatus[x4][y4]=MAP_STATE_EMPTY;
  511. InvalidateCurrent();
  512. //方块下落
  513. ActiveStatus[0][0] += 1;
  514. ActiveStatus[1][0] += 1;
  515. ActiveStatus[2][0] += 1;
  516. ActiveStatus[3][0] += 1;
  517. GameStatus[x1+1][y1]=MAP_STATE_NOT_EMPTY;
  518. GameStatus[x2+1][y2]=MAP_STATE_NOT_EMPTY;
  519. GameStatus[x3+1][y3]=MAP_STATE_NOT_EMPTY;
  520. GameStatus[x4+1][y4]=MAP_STATE_NOT_EMPTY;
  521. InvalidateCurrent();
  522. }
  523. }
  524. /* * * * * * * * * * * * * * * * * * * * * *
  525. * 内部函数:当前方块下降加速,左移,右移
  526. *
  527. * 最后修改日期:2005.8.6
  528. * * * * * * * * * * * * * * * * * * * * * */
  529. void CSkyblue_RectView::RectArrow(int m_Type)
  530. {
  531. //获取当前下坠物4个小方块的位置坐标
  532. int x1,x2,x3,x4,y1,y2,y3,y4;
  533. x1 = ActiveStatus[0][0];
  534. x2 = ActiveStatus[1][0];
  535. x3 = ActiveStatus[2][0];
  536. x4 = ActiveStatus[3][0];
  537. y1 = ActiveStatus[0][1];
  538. y2 = ActiveStatus[1][1];
  539. y3 = ActiveStatus[2][1];
  540. y4 = ActiveStatus[3][1];
  541. //对不同的移动命令指示进行分类实现
  542. switch(m_Type)
  543. {
  544. case LEFT:
  545. //对每种不同的移动命令指示特性作相应的可移动分析
  546. if ( (ActiveStatus[0][1]>0) && IsLeftLimit() && !m_isBottom)
  547. {
  548. //清原来的方块
  549. GameStatus[x1][y1]=MAP_STATE_EMPTY;
  550. GameStatus[x2][y2]=MAP_STATE_EMPTY;
  551. GameStatus[x3][y3]=MAP_STATE_EMPTY;
  552. GameStatus[x4][y4]=MAP_STATE_EMPTY;
  553. // InvalidateCurrent();
  554. //添加新的移动后数据状态
  555. ActiveStatus[0][1] -= 1;
  556. ActiveStatus[1][1] -= 1;
  557. ActiveStatus[2][1] -= 1;
  558. ActiveStatus[3][1] -= 1;
  559. GameStatus[x1][y1-1]=MAP_STATE_NOT_EMPTY;
  560. GameStatus[x2][y2-1]=MAP_STATE_NOT_EMPTY;
  561. GameStatus[x3][y3-1]=MAP_STATE_NOT_EMPTY;
  562. GameStatus[x4][y4-1]=MAP_STATE_NOT_EMPTY;
  563. InvalidateCurrent();
  564. }
  565. break;
  566. case RIGHT:
  567. if ( (ActiveStatus[3][1]< m_iCol-1) && IsRightLitmit() && !m_isBottom)
  568. {
  569. //清原来的方块
  570. GameStatus[x1][y1]=MAP_STATE_EMPTY;
  571. GameStatus[x2][y2]=MAP_STATE_EMPTY;
  572. GameStatus[x3][y3]=MAP_STATE_EMPTY;
  573. GameStatus[x4][y4]=MAP_STATE_EMPTY;
  574. // InvalidateCurrent();
  575. //添加新的移动后数据状态
  576. ActiveStatus[0][1] += 1;
  577. ActiveStatus[1][1] += 1;
  578. ActiveStatus[2][1] += 1;
  579. ActiveStatus[3][1] += 1;
  580. GameStatus[x1][y1+1]=MAP_STATE_NOT_EMPTY;
  581. GameStatus[x2][y2+1]=MAP_STATE_NOT_EMPTY;
  582. GameStatus[x3][y3+1]=MAP_STATE_NOT_EMPTY;
  583. GameStatus[x4][y4+1]=MAP_STATE_NOT_EMPTY;
  584. InvalidateCurrent();
  585. }
  586. break;
  587. case DOWN:
  588. RectDown();
  589. break;
  590. }
  591. }
  592. /* * * * * * * * * * * * * * * * * * * * * *
  593. * 内部函数:判断当前方块是否已到底,并且销行等相关的工作
  594. *
  595. * 最后修改日期:2005.8.6
  596. * * * * * * * * * * * * * * * * * * * * * */
  597. void CSkyblue_RectView::IsBottom()
  598. {
  599. //到底有两种概念:1是已到底部,2是下面碰到了另外的方块
  600. int x1,x2,x3,x4;
  601. int x,xx,yy,i;
  602. x1 = ActiveStatus[0][0];
  603. x2 = ActiveStatus[1][0];
  604. x3 = ActiveStatus[2][0];
  605. x4 = ActiveStatus[3][0];
  606. //是否为底部的判断
  607. //1。到达游戏区域的底部
  608. //2。与接触面正下方的小方块区域为被占用状态
  609. if (x1>=m_iRow-1 || x2>=m_iRow-1 || x3>=m_iRow-1 || x4>=m_iRow-1)
  610. m_isBottom = TRUE;
  611. else
  612. {
  613. for (i=0;i<4;i++)
  614. {
  615. if (InterFace[m_currentRect][i] > -1)
  616. {//取当前下坠物有接触面的方块
  617. //获取有接触面的小方块的编号
  618. x=InterFace[m_currentRect][i];
  619. //根据编号获取ActiveStatus中该小方块的整下方的坐标
  620. xx=ActiveStatus[x][0]+1;
  621. yy=ActiveStatus[x][1];
  622. //判断该接触面整下方的小方块区域是否为被占用状态
  623. if (GameStatus[xx][yy]==MAP_STATE_NOT_EMPTY)
  624. m_isBottom = TRUE;
  625. }
  626. }
  627. }
  628. BOOL m_bIsSucced;
  629. int k,j;
  630. int m_iMuch=0; //本次销掉的行数
  631. //计分规则:一次销掉一行,加100分,一次销掉两行,加400分,三行,900分
  632. //例如销掉x行,则分数为:x*(x*100)
  633. if (m_isBottom)
  634. {
  635. //判断是否已得分
  636. for (i=0;i<m_iRow;i++)
  637. {
  638. m_bIsSucced = TRUE;
  639. for (j=0;j<m_iCol;j++)
  640. if (GameStatus[i][j]==MAP_STATE_EMPTY)
  641. m_bIsSucced = FALSE;
  642. //如果得分,则销掉此行
  643. if (m_bIsSucced)
  644. {
  645. for (k=i;k>0;k--)
  646. for (j=0;j<m_iCol;j++)
  647. GameStatus[k][j] = GameStatus[k-1][j];
  648. //第1行清零
  649. for (j=0;j<m_iCol;j++)
  650. GameStatus[0][j]=MAP_STATE_EMPTY;
  651. m_iMuch += 1;
  652. }
  653. }
  654. if (m_iMuch>0)
  655. {
  656. m_iPerformance += m_iMuch * m_iMuch * 100;
  657. //刷新游戏区域
  658. CRect rect1(m_iStartY, m_iStartX, m_iStartY+300, m_iStartX+360);
  659. //InvalidateRect(&rect1);
  660. //刷新分数区域
  661. CRect rect2(m_iStartY+320, m_iStartX+180, m_iStartY+440, m_iStartX+200);
  662. //InvalidateRect(&rect2);
  663. Invalidate(FALSE);
  664. }
  665. }
  666. }
  667. /* * * * * * * * * * * * * * * * * * * * * * * * *
  668. *
  669. *  名称:OnKeyDown
  670. *
  671. *  功能:处理用户的输入,方块的左,右移,加速及变形
  672. *
  673. *  最后修改时间:2005.8.6
  674. *
  675. * * * * * * * * * * * * * * * * * * * * * * * * */
  676. void CSkyblue_RectView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  677. {
  678. switch(nChar)
  679. {
  680. case VK_LEFT:
  681. RectArrow(LEFT);
  682. break;
  683. case VK_RIGHT:
  684. RectArrow(RIGHT);
  685. break;
  686. case VK_UP:
  687. RectChange();
  688. break;
  689. case VK_DOWN:
  690. RectArrow(DOWN);
  691. break;
  692. }
  693. CView::OnKeyDown(nChar, nRepCnt, nFlags);
  694. }
  695. /* * * * * * * * * * * * * * * * * * * * * *
  696. * 内部函数:方块是否还可以左移
  697. *
  698. * 最后修改日期:2005.8.6
  699. * * * * * * * * * * * * * * * * * * * * * */
  700. BOOL CSkyblue_RectView::IsLeftLimit()
  701. {
  702. int x1,x2,x3,x4,y1,y2,y3,y4;
  703. x1 = ActiveStatus[0][0];
  704. x2 = ActiveStatus[1][0];
  705. x3 = ActiveStatus[2][0];
  706. x4 = ActiveStatus[3][0];
  707. y1 = ActiveStatus[0][1];
  708. y2 = ActiveStatus[1][1];
  709. y3 = ActiveStatus[2][1];
  710. y4 = ActiveStatus[3][1];
  711. //根据当前下坠物的具体形态,分析判断其是否有向左移动的空间
  712. switch(m_currentRect)
  713. {
  714. /*
  715. |
  716.    |
  717.        |   "1"字形形态类型,判断其四个方块的正左边都没有任何物件(空间没有被占据)
  718.    |
  719.  */
  720. case 1:
  721. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1])
  722. return FALSE;
  723. break;
  724. case 11:
  725. if (GameStatus[x1][y1-1])
  726. return FALSE;
  727. break;
  728. case 2:
  729. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
  730. return FALSE;
  731. break;
  732. case 3:
  733. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
  734. return FALSE;
  735. break;
  736. case 31:
  737. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
  738. return FALSE;
  739. break;
  740. case 32:
  741. if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
  742. return FALSE;
  743. break;
  744. case 33:
  745. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1])
  746. return FALSE;
  747. break;
  748. case 4:
  749. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x4][y4-1])
  750. return FALSE;
  751. break;
  752. case 41:
  753. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
  754. return FALSE;
  755. break;
  756. case 5:
  757. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
  758. return FALSE;
  759. break;
  760. case 51:
  761. if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
  762. return FALSE;
  763. break;
  764. case 6:
  765. if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1] || GameStatus[x4][y4-1])
  766. return FALSE;
  767. break;
  768. case 61:
  769. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
  770. return FALSE;
  771. break;
  772. case 62:
  773. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
  774. return FALSE;
  775. break;
  776. case 63:
  777. if (GameStatus[x1][y1-1] || GameStatus[x3][y3-1])
  778. return FALSE;
  779. break;
  780. case 7:
  781. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
  782. return FALSE;
  783. break;
  784. case 71:
  785. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1])
  786. return FALSE;
  787. break;
  788. case 72:
  789. if (GameStatus[x1][y1-1] || GameStatus[x2][y2-1] || GameStatus[x3][y3-1])
  790. return FALSE;
  791. break;
  792. case 73:
  793. if (GameStatus[x1][y1-1] || GameStatus[x4][y4-1])
  794. return FALSE;
  795. break;
  796. }
  797. return TRUE;
  798. }
  799. /* * * * * * * * * * * * * * * * * * * * * *
  800. * 内部函数:方块是否还可以右移
  801. *
  802. * 最后修改日期:2005.8.6
  803. * * * * * * * * * * * * * * * * * * * * * */
  804. BOOL CSkyblue_RectView::IsRightLitmit()
  805. {
  806. int x1,x2,x3,x4,y1,y2,y3,y4;
  807. x1 = ActiveStatus[0][0];
  808. x2 = ActiveStatus[1][0];
  809. x3 = ActiveStatus[2][0];
  810. x4 = ActiveStatus[3][0];
  811. y1 = ActiveStatus[0][1];
  812. y2 = ActiveStatus[1][1];
  813. y3 = ActiveStatus[2][1];
  814. y4 = ActiveStatus[3][1];
  815. switch(m_currentRect)
  816. {
  817. case 1:
  818. if (GameStatus[x1][y1+1] || GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  819. return FALSE;
  820. break;
  821. case 11:
  822. if (GameStatus[x4][y4+1])
  823. return FALSE;
  824. break;
  825. case 2:
  826. if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  827. return FALSE;
  828. break;
  829. case 3:
  830. if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
  831. return FALSE;
  832. break;
  833. case 31:
  834. if (GameStatus[x1][y1+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  835. return FALSE;
  836. break;
  837. case 32:
  838. if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  839. return FALSE;
  840. break;
  841. case 33:
  842. if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  843. return FALSE;
  844. break;
  845. case 4:
  846. if (GameStatus[x1][y1+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  847. return FALSE;
  848. break;
  849. case 41:
  850. if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  851. return FALSE;
  852. break;
  853. case 5:
  854. if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  855. return FALSE;
  856. break;
  857. case 51:
  858. if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
  859. return FALSE;
  860. break;
  861. case 6:
  862. if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  863. return FALSE;
  864. break;
  865. case 61:
  866. if (GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
  867. return FALSE;
  868. break;
  869. case 62:
  870. if (GameStatus[x1][y1+1] || GameStatus[x2][y2+1] || GameStatus[x4][y4+1])
  871. return FALSE;
  872. break;
  873. case 63:
  874. if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  875. return FALSE;
  876. break;
  877. case 7:
  878. if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  879. return FALSE;
  880. break;
  881. case 71:
  882. if (GameStatus[x1][y1+1] || GameStatus[x4][y4+1])
  883. return FALSE;
  884. break;
  885. case 72:
  886. if (GameStatus[x2][y2+1] || GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  887. return FALSE;
  888. break;
  889. case 73:
  890. if (GameStatus[x3][y3+1] || GameStatus[x4][y4+1])
  891. return FALSE;
  892. break;
  893. }
  894. return TRUE;
  895. }
  896. /* * * * * * * * * * * * * * * * * * * * * *
  897. * 内部函数:方块的变形
  898. *
  899. * 最后修改日期:2005.8.6
  900. * * * * * * * * * * * * * * * * * * * * * */
  901. void CSkyblue_RectView::RectChange()
  902. {
  903. //先预先变形,然后判断变形后的方块是否有空间,如有足够空间,则进行实际变形,否则不变
  904. int xx1,xx2,xx3,xx4,yy1,yy2,yy3,yy4;
  905. int m_lscurrentRect;
  906. CString lsStr;
  907. int x1,x2,x3,x4,y1,y2,y3,y4;
  908. x1 = ActiveStatus[0][0];
  909. x2 = ActiveStatus[1][0];
  910. x3 = ActiveStatus[2][0];
  911. x4 = ActiveStatus[3][0];
  912. y1 = ActiveStatus[0][1];
  913. y2 = ActiveStatus[1][1];
  914. y3 = ActiveStatus[2][1];
  915. y4 = ActiveStatus[3][1];
  916. //变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下
  917. xx1=x1; xx2=x2; xx3=x3; xx4=x4; yy1=y1; yy2=y2; yy3=y3; yy4=y4;
  918. switch(m_currentRect)
  919. {
  920. case 1:
  921. xx1=x1+1; yy1=y1-1; xx3=x3-1; yy3=y3+1; xx4=x4-2; yy4=y4+2;
  922. m_lscurrentRect = 11;
  923. break;
  924. case 11:
  925. xx1=x1-1; yy1=y1+1; xx3=x3+1; yy3=y3-1; xx4=x4+2; yy4=y4-2;
  926. m_lscurrentRect = 1;
  927. break;
  928. case 2:
  929. m_lscurrentRect=2; 
  930. break;
  931. case 3:
  932. xx1=x1-2; yy1=y1+1; xx4=x4-1; yy4=y4;
  933. m_lscurrentRect = 31;
  934. break;
  935. case 31:
  936. xx1=x1+1; yy1=y1-1; 
  937. m_lscurrentRect = 32;
  938. break;
  939. case 32:
  940. xx1=x1+1; yy1=y1; xx4=x4+2; yy4=y4-1;
  941. m_lscurrentRect=33;
  942. break;
  943. case 33:
  944. xx4=x4-1; yy4=y4+1;
  945. m_lscurrentRect=3;
  946. break;
  947. case 4:
  948. xx1=x1+2; yy1=y1-1; xx3=x3+1; yy3=y3-1; xx4=x4-1;
  949. m_lscurrentRect = 41;
  950. break;
  951. case 41:
  952. xx1=x1-2; yy1=y1+1; xx3=x3-1; yy3=y3+1; xx4=x4+1;
  953. m_lscurrentRect = 4;
  954. break;
  955. case 5:
  956. xx1=x1-1; xx2=x2-2; yy2=y2+1; xx3=x3+1; yy4=y4+1;
  957. m_lscurrentRect = 51;
  958. break;
  959. case 51:
  960. xx1=x1+1; xx2=x2+2; yy2=y2-1; xx3=x3-1; yy4=y4-1;
  961. m_lscurrentRect = 5;
  962. break;
  963. case 6:
  964. xx2=x1+1; yy2=y2-1; xx3=x3-1; xx4=x4-2; yy4 = yy4+1;
  965. m_lscurrentRect = 61;
  966. break;
  967. case 61:
  968. xx3=x3+2; yy3=y3-1; xx4=x4+2; yy4=y4-1;
  969. m_lscurrentRect = 62;
  970. break;
  971. case 62:
  972. xx1=x1+1; yy1=y1-1; xx3=x3-2; yy3=y3+1; xx4=x4-1;
  973. m_lscurrentRect = 63;
  974. break;
  975. case 63:
  976. xx1=x1-2; yy1=y1+1; xx2=x2-2; yy2=y2+1;
  977. m_lscurrentRect = 6;
  978. break;
  979. case 7:
  980. xx3=x3-1; yy3=y3+1; xx4=x4+1; yy4=y4+1;
  981. m_lscurrentRect = 71;
  982. break;
  983. case 71:
  984. xx1=x1+2; xx2=x2-1; yy2=y2+1; xx4=x4+1; yy4=y4-1;
  985. m_lscurrentRect = 72;
  986. break;
  987. case 72:
  988. xx1=x1-2; xx3=x3-1; yy3=y3+1; xx4=x4-1; yy4=y4+1;
  989. m_lscurrentRect = 73;
  990. break;
  991. case 73:
  992. xx2=x2+1; yy2=y2-1; xx3=x3+2; yy3=y3-2; xx4=x4-1; yy4=y4-1;
  993. m_lscurrentRect = 7;
  994. break;
  995. }
  996. //如果变形后所在的区域内无其他方块,则表示有足够空间,可以变形
  997. //且不能超越边界
  998. GameStatus[x1][y1] = MAP_STATE_EMPTY;
  999. GameStatus[x2][y2] = MAP_STATE_EMPTY;
  1000. GameStatus[x3][y3] = MAP_STATE_EMPTY;
  1001. GameStatus[x4][y4] = MAP_STATE_EMPTY;
  1002. if (GameStatus[xx1][yy1]==MAP_STATE_EMPTY &&
  1003. GameStatus[xx2][yy2]==MAP_STATE_EMPTY &&
  1004. GameStatus[xx3][yy3]==MAP_STATE_EMPTY && 
  1005. GameStatus[xx4][yy4]==MAP_STATE_EMPTY 
  1006. && yy1>=0 && yy4<=m_iCol-1 
  1007. && !(xx1<0 || xx2<0 || xx3<0 || xx4<0) 
  1008. && !(xx1>m_iRow-1 || xx2>m_iRow-1 || xx3>m_iRow-1 || xx4>m_iRow-1) )
  1009. {
  1010. InvalidateCurrent();
  1011. ActiveStatus[0][0]=xx1;
  1012. ActiveStatus[1][0]=xx2;
  1013. ActiveStatus[2][0]=xx3;
  1014. ActiveStatus[3][0]=xx4;
  1015. ActiveStatus[0][1]=yy1;
  1016. ActiveStatus[1][1]=yy2;
  1017. ActiveStatus[2][1]=yy3;
  1018. ActiveStatus[3][1]=yy4;
  1019. GameStatus[xx1][yy1] = MAP_STATE_NOT_EMPTY;
  1020. GameStatus[xx2][yy2] = MAP_STATE_NOT_EMPTY;
  1021. GameStatus[xx3][yy3] = MAP_STATE_NOT_EMPTY;
  1022. GameStatus[xx4][yy4] = MAP_STATE_NOT_EMPTY;
  1023. InvalidateCurrent();
  1024. //改变形状代码
  1025. m_currentRect = m_lscurrentRect;
  1026. }
  1027. else
  1028. {//恢复原来状态
  1029. GameStatus[x1][y1] = MAP_STATE_NOT_EMPTY;
  1030. GameStatus[x2][y2] = MAP_STATE_NOT_EMPTY;
  1031. GameStatus[x3][y3] = MAP_STATE_NOT_EMPTY;
  1032. GameStatus[x4][y4] = MAP_STATE_NOT_EMPTY;
  1033. }
  1034. //判断是否已到底
  1035. IsBottom();
  1036. }
  1037. /* * * * * * * * * * * * * * * * * * * * * *
  1038. * 内部函数:游戏开始
  1039. *
  1040. * 最后修改日期:2005.8.6
  1041. * * * * * * * * * * * * * * * * * * * * * */
  1042. void CSkyblue_RectView::OnGameStart() 
  1043. {
  1044. if (!m_bGamePaush)  //如果不是游戏暂停状态,则必须作些初始工作
  1045. {
  1046. m_bGameEnd = FALSE;
  1047. //总分值清零, 并显示总分记分牌
  1048. m_iPerformance = 0;
  1049. //显示当前的区域及游戏级别的汉字描述
  1050. CurrentAreaAndLevel();
  1051. CRect rect(m_iStartY, m_iStartX, m_iStartY+440, m_iStartX+370);
  1052. InvalidateRect(&rect);
  1053. }
  1054. m_bGamePaush = FALSE;
  1055. SetTimer(1,1500-250*m_iLevel,NULL);
  1056. }
  1057. //游戏暂停
  1058. void CSkyblue_RectView::OnGamePaush() 
  1059. {
  1060. m_bGamePaush = TRUE;
  1061. KillTimer(1);
  1062. }
  1063. /* * * * * * * * * * * * * * * * * * * * * *
  1064. * 内部函数:游戏结束
  1065. *
  1066. * 最后修改日期:2005.8.6
  1067. * * * * * * * * * * * * * * * * * * * * * */
  1068. void CSkyblue_RectView::OnGameEnd() 
  1069. {
  1070. m_bGameEnd = TRUE;
  1071. int i,j;
  1072. for (i=0;i<m_iRow;i++)
  1073. for (j=0;j<m_iCol;j++)
  1074. GameStatus[i][j]=0;
  1075. CRect rect(m_iStartY, m_iStartX, m_iStartY+440, m_iStartX+370);
  1076. InvalidateRect(&rect);
  1077. m_bGamePaush = FALSE;  //清除游戏暂停状态
  1078. KillTimer(1);
  1079. }
  1080. /* * * * * * * * * * * * * * * * * * * * * *
  1081. * 内部函数:刷新当前的区域
  1082. *
  1083. * 只刷新需要刷新的四个小方块区域,防止屏幕抖动情况发生
  1084. *
  1085. * 最后修改日期:2005.8.6
  1086. * * * * * * * * * * * * * * * * * * * * * */
  1087. void CSkyblue_RectView::InvalidateCurrent()
  1088. {
  1089. int i;
  1090. for (i=0;i<4;i++)
  1091. {
  1092. CRect rect(m_iStartX+ActiveStatus[i][1]*m_iLarge, 
  1093. m_iStartY+ActiveStatus[i][0]*m_iLarge,
  1094. m_iStartX+(ActiveStatus[i][1]+1)*m_iLarge+5,
  1095. m_iStartY+(ActiveStatus[i][0]+1)*m_iLarge);
  1096. //InvalidateRect(&rect);
  1097. Invalidate(FALSE);
  1098. }
  1099. }
  1100. /* * * * * * * * * * * * * * * * * * * * * *
  1101. * 内部函数:游戏设置
  1102. *
  1103. * 最后修改日期:2005.8.6
  1104. * * * * * * * * * * * * * * * * * * * * * */
  1105. void CSkyblue_RectView::OnGameOption() 
  1106. {
  1107. //参数顺序: 区域大小代码:0-3,分别为:12X10,18X15,24X20,m_iLargeX25
  1108. //级别:0-5,分别为:1500,1200,1000,800,600,400
  1109. //背景音乐:TRUE 或者 FALSE
  1110. int m_lsArea;
  1111. switch(m_iRow)
  1112. {
  1113. case 12:
  1114. m_lsArea = 0;
  1115. break;
  1116. case 18:
  1117. m_lsArea = 1;
  1118. break;
  1119. case 24:
  1120. m_lsArea = 2;
  1121. break;
  1122. case 30:
  1123. m_lsArea = 3;
  1124. break;
  1125. }
  1126. COptionDlg dlg(m_lsArea,m_iLevel,m_iBlockSytle,m_bMusic,m_bDrawGrid);
  1127. if (dlg.DoModal()==IDOK)
  1128. {
  1129. //确定区域的大小
  1130. switch(dlg.m_iArea)
  1131. {
  1132. case 0:
  1133. m_iRow = 12;
  1134. m_iCol = 10;
  1135. m_iLarge = 30;
  1136. break;
  1137. case 1:
  1138. m_iRow = 18;
  1139. m_iCol = 15;
  1140. m_iLarge = 20;
  1141. break;
  1142. case 2:
  1143. m_iRow = 24;
  1144. m_iCol = 20;
  1145. m_iLarge = 15;
  1146. break;
  1147. case 3:
  1148. m_iRow = 30;
  1149. m_iCol = 25;
  1150. m_iLarge = 12;
  1151. break;
  1152. }
  1153. //确定级别
  1154. m_iLevel = dlg.m_iLevel;
  1155. //选择的样式
  1156. m_iBlockSytle = dlg.m_iBlockStyle;
  1157. //确定是否绘网格背景
  1158. m_bDrawGrid = dlg.m_bDrawGrid;
  1159.         //检查是否插放音乐   
  1160. m_bMusic = dlg.m_bMusic;
  1161. if (m_bMusic)
  1162. PlayMid();
  1163. else
  1164. StopMid();
  1165. Invalidate();
  1166. }
  1167. }
  1168. //用于生成当前区域大小与级别所对应的汉字描述
  1169. void CSkyblue_RectView::CurrentAreaAndLevel()
  1170. {
  1171. switch(m_iRow)
  1172. {
  1173. case 12:
  1174. m_strArea = "12行10列"; break;
  1175. case 18:
  1176. m_strArea = "18行15列"; break;
  1177. case 24:
  1178. m_strArea = "24行20列"; break;
  1179. case 30:
  1180. m_strArea = "30行25列"; break;
  1181. }
  1182. switch(m_iLevel)
  1183. {
  1184. case 0:
  1185. m_strLevel = "第一级: 入门级"; break;
  1186. case 1:
  1187. m_strLevel = "第二级: 初级级"; break;
  1188. case 2:
  1189. m_strLevel = "第三级: 中级"; break;
  1190. case 3:
  1191. m_strLevel = "第四级: 中高级"; break;
  1192. case 4:
  1193. m_strLevel = "第五级: 高级"; break;
  1194. case 5:
  1195. m_strLevel = "第六级: 顶级"; break;
  1196. }
  1197. }
  1198. /* * * * * * * * * * * * * * * * * * * * * *
  1199. * 内部函数:以下为菜单屏蔽与开启控制
  1200. *
  1201. * 最后修改日期:2005.8.6
  1202. * * * * * * * * * * * * * * * * * * * * * */
  1203. //如果游戏开始,则此[开始游戏]按钮被屏蔽
  1204. void CSkyblue_RectView::OnUpdateGameStart(CCmdUI* pCmdUI) 
  1205. {
  1206. if (m_bGameEnd || m_bGamePaush)
  1207. pCmdUI->Enable(TRUE);
  1208. else
  1209. pCmdUI->Enable(FALSE);
  1210. }
  1211. //如果游戏开始,则此[游戏设置]按钮被屏蔽
  1212. void CSkyblue_RectView::OnUpdateGameOption(CCmdUI* pCmdUI) 
  1213. {
  1214. if (m_bGameEnd)
  1215. pCmdUI->Enable(TRUE);
  1216. else
  1217. pCmdUI->Enable(FALSE);
  1218. }
  1219. //如游戏开始,则[游戏暂停]按钮开启
  1220. void CSkyblue_RectView::OnUpdateGamePaush(CCmdUI* pCmdUI) 
  1221. {
  1222. if (!m_bGameEnd)
  1223. pCmdUI->Enable(TRUE);
  1224. else
  1225. pCmdUI->Enable(FALSE);
  1226. }
  1227. //如果游戏开始,则此[游戏结束]按钮被开启
  1228. void CSkyblue_RectView::OnUpdateGameEnd(CCmdUI* pCmdUI) 
  1229. {
  1230. if (!m_bGameEnd)
  1231. pCmdUI->Enable(TRUE);
  1232. else
  1233. pCmdUI->Enable(FALSE);
  1234. }
  1235. //如果游戏开始,则此[退出系统]按钮被屏蔽
  1236. void CSkyblue_RectView::OnUpdateGameExit(CCmdUI* pCmdUI) 
  1237. {
  1238. if (m_bGameEnd)
  1239. pCmdUI->Enable(TRUE);
  1240. else
  1241. pCmdUI->Enable(FALSE);
  1242. }
  1243. //如果游戏开始,则此[关于]按钮被屏蔽
  1244. void CSkyblue_RectView::OnUpdateHelpAbout(CCmdUI* pCmdUI) 
  1245. {
  1246. if (m_bGameEnd)
  1247. pCmdUI->Enable(TRUE);
  1248. else
  1249. pCmdUI->Enable(FALSE);
  1250. }
  1251. //如果游戏开始,则此[帮助]按钮被屏蔽
  1252. void CSkyblue_RectView::OnUpdateHelpHelp(CCmdUI* pCmdUI) 
  1253. {
  1254. if (m_bGameEnd)
  1255. pCmdUI->Enable(FALSE);
  1256. else
  1257. pCmdUI->Enable(FALSE);
  1258. }
  1259. void CSkyblue_RectView::OnHelpHelp() 
  1260. {
  1261. }
  1262. //用菜单设置区域大小
  1263. void CSkyblue_RectView::OnUpdateOptionArea1(CCmdUI* pCmdUI) 
  1264. {
  1265. if (m_bGameEnd) 
  1266. pCmdUI -> Enable(TRUE);
  1267. else 
  1268. pCmdUI -> Enable(FALSE);
  1269. if (m_iRow==12)
  1270. pCmdUI -> SetCheck(TRUE);
  1271. else
  1272. pCmdUI -> SetCheck(FALSE);
  1273. }
  1274. void CSkyblue_RectView::OnUpdateOptionArea2(CCmdUI* pCmdUI) 
  1275. {
  1276. if (m_bGameEnd) 
  1277. pCmdUI -> Enable(TRUE);
  1278. else 
  1279. pCmdUI -> Enable(FALSE);
  1280. if (m_iRow==18)
  1281. pCmdUI -> SetCheck(TRUE);
  1282. else
  1283. pCmdUI -> SetCheck(FALSE);
  1284. }
  1285. void CSkyblue_RectView::OnUpdateOptionArea3(CCmdUI* pCmdUI) 
  1286. {
  1287. if (m_bGameEnd) 
  1288. pCmdUI -> Enable(TRUE);
  1289. else 
  1290. pCmdUI -> Enable(FALSE);
  1291. if (m_iRow==24)
  1292. pCmdUI -> SetCheck(TRUE);
  1293. else
  1294. pCmdUI -> SetCheck(FALSE);
  1295. }
  1296. void CSkyblue_RectView::OnUpdateOptionArea4(CCmdUI* pCmdUI) 
  1297. {
  1298. if (m_bGameEnd) 
  1299. pCmdUI -> Enable(TRUE);
  1300. else 
  1301. pCmdUI -> Enable(FALSE);
  1302. if (m_iRow==30)
  1303. pCmdUI -> SetCheck(TRUE);
  1304. else
  1305. pCmdUI -> SetCheck(FALSE);
  1306. }
  1307. //用菜单设置区域大小
  1308. void CSkyblue_RectView::OnOptionArea1() 
  1309. {
  1310. m_iRow = 12;
  1311. m_iCol = 10;
  1312. m_iLarge = 30;
  1313. Invalidate();
  1314. }
  1315. void CSkyblue_RectView::OnOptionArea2() 
  1316. {
  1317. m_iRow = 18;
  1318. m_iCol = 15;
  1319. m_iLarge = 20;
  1320. Invalidate();
  1321. }
  1322. void CSkyblue_RectView::OnOptionArea3() 
  1323. {
  1324. m_iRow = 24;
  1325. m_iCol = 20;
  1326. m_iLarge = 15;
  1327. Invalidate();
  1328. }
  1329. void CSkyblue_RectView::OnOptionArea4() 
  1330. {
  1331. m_iRow = 30;
  1332. m_iCol = 25;
  1333. m_iLarge = 12;
  1334. Invalidate();
  1335. }
  1336. // 用菜单设置游戏级别 
  1337. void CSkyblue_RectView::OnUpdateOptionLevel1(CCmdUI* pCmdUI) 
  1338. {
  1339. if (m_bGameEnd) 
  1340. pCmdUI -> Enable(TRUE);
  1341. else 
  1342. pCmdUI -> Enable(FALSE);
  1343. if (m_iLevel == 0)
  1344. pCmdUI -> SetCheck(TRUE);
  1345. else
  1346. pCmdUI -> SetCheck(FALSE);
  1347. }
  1348. void CSkyblue_RectView::OnUpdateOptionLevel2(CCmdUI* pCmdUI) 
  1349. {
  1350. if (m_bGameEnd) 
  1351. pCmdUI -> Enable(TRUE);
  1352. else 
  1353. pCmdUI -> Enable(FALSE);
  1354. if (m_iLevel == 1)
  1355. pCmdUI -> SetCheck(TRUE);
  1356. else
  1357. pCmdUI -> SetCheck(FALSE);
  1358. }
  1359. void CSkyblue_RectView::OnUpdateOptionLevel3(CCmdUI* pCmdUI) 
  1360. {
  1361. if (m_bGameEnd) 
  1362. pCmdUI -> Enable(TRUE);
  1363. else 
  1364. pCmdUI -> Enable(FALSE);
  1365. if (m_iLevel == 2)
  1366. pCmdUI -> SetCheck(TRUE);
  1367. else
  1368. pCmdUI -> SetCheck(FALSE);
  1369. }
  1370. void CSkyblue_RectView::OnUpdateOptionLevel4(CCmdUI* pCmdUI) 
  1371. {
  1372. if (m_bGameEnd) 
  1373. pCmdUI -> Enable(TRUE);
  1374. else 
  1375. pCmdUI -> Enable(FALSE);
  1376. if (m_iLevel == 3)
  1377. pCmdUI -> SetCheck(TRUE);
  1378. else
  1379. pCmdUI -> SetCheck(FALSE);
  1380. }
  1381. void CSkyblue_RectView::OnUpdateOptionLevel5(CCmdUI* pCmdUI) 
  1382. {
  1383. if (m_bGameEnd) 
  1384. pCmdUI -> Enable(TRUE);
  1385. else 
  1386. pCmdUI -> Enable(FALSE);
  1387. if (m_iLevel == 4)
  1388. pCmdUI -> SetCheck(TRUE);
  1389. else
  1390. pCmdUI -> SetCheck(FALSE);
  1391. }
  1392. void CSkyblue_RectView::OnUpdateOptionLevel6(CCmdUI* pCmdUI) 
  1393. {
  1394. if (m_bGameEnd) 
  1395. pCmdUI -> Enable(TRUE);
  1396. else 
  1397. pCmdUI -> Enable(FALSE);
  1398. if (m_iLevel == 5)
  1399. pCmdUI -> SetCheck(TRUE);
  1400. else
  1401. pCmdUI -> SetCheck(FALSE);
  1402. }
  1403. //用菜单设置游戏级别
  1404. void CSkyblue_RectView::OnOptionLevel1() 
  1405. {
  1406. m_iLevel = 0;
  1407. }
  1408. void CSkyblue_RectView::OnOptionLevel2() 
  1409. {
  1410. m_iLevel = 1;
  1411. }
  1412. void CSkyblue_RectView::OnOptionLevel3() 
  1413. {
  1414. m_iLevel = 2;
  1415. }
  1416. void CSkyblue_RectView::OnOptionLevel4() 
  1417. {
  1418. m_iLevel = 3;
  1419. }
  1420. void CSkyblue_RectView::OnOptionLevel5() 
  1421. {
  1422. m_iLevel = 4;
  1423. }
  1424. void CSkyblue_RectView::OnOptionLevel6() 
  1425. {
  1426. m_iLevel = 5;
  1427. }
  1428. //用菜单设置是否有网格
  1429. void CSkyblue_RectView::OnUpdateOptionGrid(CCmdUI* pCmdUI) 
  1430. {
  1431. if (m_bGameEnd)
  1432. pCmdUI -> Enable(TRUE);
  1433. else
  1434. pCmdUI -> Enable(FALSE);
  1435. if (m_bDrawGrid)
  1436. pCmdUI -> SetCheck(TRUE);
  1437. else
  1438. pCmdUI -> SetCheck(FALSE);
  1439. }
  1440. void CSkyblue_RectView::OnOptionGrid() 
  1441. {
  1442. if (m_bDrawGrid)
  1443. m_bDrawGrid = FALSE;
  1444. else
  1445. m_bDrawGrid = TRUE;
  1446. Invalidate();
  1447. }
  1448. //
  1449. //插放背景音乐, 所有错误忽略
  1450. //
  1451. void CSkyblue_RectView::PlayMid()
  1452. {
  1453. HWND hWnd;
  1454. hWnd = GetSafeHwnd();
  1455. //分配命令字符串缓冲,错误信息储存缓冲,播放的文件名
  1456. char szCmdBuf[300],errBuf[60],szfileName[255];
  1457. //错误码
  1458. MCIERROR mciError;
  1459. //初始化设备元素
  1460. strcpy(szfileName,"skyblue_rect.mid"); 
  1461. //初始化命令字符串
  1462. wsprintf( szCmdBuf,"open %s type sequencer alias bkMusic",szfileName);
  1463. //打开设备
  1464. mciError = mciSendString( szCmdBuf, errBuf, sizeof(errBuf), NULL);
  1465. if (mciError == 0)
  1466. {//如果打开成功则播放
  1467. mciError = mciSendString("play bkMusic notify",NULL,0, hWnd);
  1468. //根据播放操作是否成功决定是否关闭设备
  1469. if (mciError != 0)
  1470. mciSendString("close bkMusic",NULL,0,NULL);
  1471. }
  1472. }
  1473. //
  1474. //终止插放背景音乐
  1475. //
  1476. void CSkyblue_RectView::StopMid()
  1477. {
  1478. //关闭设备
  1479. mciSendString("close bkMusic",NULL,0,NULL);
  1480. }
  1481. //用菜单设置是否插放音乐
  1482. void CSkyblue_RectView::OnUpdateOptionMusic(CCmdUI* pCmdUI) 
  1483. {
  1484. if (m_bGameEnd)
  1485. pCmdUI -> Enable(TRUE);
  1486. else
  1487. pCmdUI -> Enable(FALSE);
  1488. if (m_bMusic)
  1489. pCmdUI -> SetCheck(TRUE);
  1490. else
  1491. pCmdUI -> SetCheck(FALSE);
  1492. }
  1493. void CSkyblue_RectView::OnOptionMusic() 
  1494. {
  1495. if (m_bMusic)
  1496. {
  1497. m_bMusic = FALSE;
  1498. StopMid();
  1499. }
  1500. else
  1501. {
  1502. m_bMusic = TRUE;
  1503. PlayMid();
  1504. }
  1505. }
  1506. void CSkyblue_RectView::OnGameExit() 
  1507. {
  1508. //清理内存设备环境,释放资源
  1509. DCEnvClear();
  1510. }
  1511. void CSkyblue_RectView::OnHelpAbout() 
  1512. {
  1513. HWND hwnd = ::AfxGetMainWnd()->GetSafeHwnd();
  1514. ShellAbout(hwnd,"俄罗斯方块  作者:skyblue 风中解码","E-mail:skyblue@yahoo.com.cn",NULL);
  1515. }