BoxMan.cpp
上传用户:qiangti
上传日期:2022-04-06
资源大小:644k
文件大小:15k
源码类别:

其他智力游戏

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) AFE(Active-Free-Elegance)
  3. Module Name:
  4.      BoxMan.cpp
  5. Abstract:
  6. BoxMan Game Class ,solve all the important movment of the man and box,
  7. and some thing refer to them
  8. Author:
  9.     Weijian Luo (Arthur Luo)   15-Jun-2005
  10. E-mail: skybluehacker@yahoo.com.cn
  11. Revision History:      1.0
  12. --*/
  13. #include "stdafx.h"
  14. #include "skyblue_BoxMan.h"
  15. #include "BoxMan.h"
  16. #include <Mmsystem.h>   //音效  Winmm.lib
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[]=__FILE__;
  20. #define new DEBUG_NEW
  21. #endif
  22. //地图状态
  23. #define MAP_BACKGROUP  48  //'0'  对应字符'0'背景
  24. #define MAP_WHITEWALL  49  //'1'  墙
  25. #define MAP_BLUEWALL   50  //'2'  通道
  26. #define MAP_BALL       51  //'3'  目的点
  27. #define MAP_YELLOWBOX  52  //'4'  箱子
  28. #define MAP_REDBOX     53  //'5'  安放好的箱子
  29. #define MAP_MANWALL    54  //'6'  人在通道区域
  30. #define MAP_MANBALL    55  //'7'  人在目的点区域
  31. //声音状态
  32. #define SOUND_STATE_START   0  //游戏开始
  33. #define SOUND_STATE_MOVE    1  //工人行走移动
  34. #define SOUND_STATE_PUSH    2  //行走并推动箱子
  35. #define SOUND_STATE_VICTORY 3  //胜利
  36. //游戏区域小方块大小 
  37. #define BLOCK_WIDTH    20   //  宽度
  38. #define BLOCK_HEIGHT    20  //  深度
  39. //假宏定义
  40. int MAX_MISSION_NUM  = 1;
  41. //////////////////////////////////////////////////////////////////////
  42. // Construction/Destruction
  43. //////////////////////////////////////////////////////////////////////
  44. CBoxMan::CBoxMan()
  45. {
  46.     m_iMissionNum = 1;
  47. ::MAX_MISSION_NUM = LoadMaxMissionNum();
  48.     LoadMap(m_iMissionNum);
  49.     m_ptManPosition = GetManPosition();
  50. }
  51. CBoxMan::~CBoxMan()
  52. {
  53. }
  54. void CBoxMan::LoadMap(int iMissionNum)
  55. {
  56.     CString str;
  57.     str.Format("[%d]", iMissionNum);
  58. FILE *pFile = fopen("map.info", "rb");
  59. if (pFile == NULL)
  60. {
  61.         AfxMessageBox("载入地图文件失败");
  62.         return;
  63. }
  64.     char cTmp[M_TAB_WIDTH*2];
  65.     fgets(cTmp, M_TAB_WIDTH*2, pFile);
  66.     while (strncmp(cTmp, str, 3) != 0)
  67.     {
  68.         fgets(cTmp, M_TAB_WIDTH*2, pFile);
  69.     }
  70.     for (int i = 0; i < M_TAB_HEIGHT; i++)
  71.         fgets(m_cMap[i],M_TAB_WIDTH*2, pFile);
  72.     fclose(pFile);
  73. }
  74. int CBoxMan::LoadMaxMissionNum(void)
  75. {
  76. int iMissionNum = 1;
  77.     CString str;
  78.     str.Format("[%d]", iMissionNum);
  79. FILE *pFile = fopen("map.info", "rb");
  80. if (pFile == NULL)
  81. {
  82.         AfxMessageBox("载入地图文件失败");
  83.         return -1;
  84. }
  85.     char cTmp[M_TAB_WIDTH*2];
  86. while( !feof(pFile) )//not end of file
  87. {
  88. fgets(cTmp, M_TAB_WIDTH*2, pFile);
  89. if(strncmp(cTmp, str, 3) == 0)
  90. {
  91.     str.Format("[%d]", ++iMissionNum);
  92. }
  93. }
  94.     fclose(pFile);
  95. return iMissionNum-1;
  96. }
  97. CPoint CBoxMan::GetManPosition()
  98. {
  99.     CPoint manPosition(0, 0);
  100.     for (int i = 0; i < M_TAB_HEIGHT; i++)
  101.     {
  102.         for (int j = 0; j < M_TAB_WIDTH; j++)
  103.         {
  104.             if (m_cMap[i][j]==MAP_MANWALL || m_cMap[i][j]==MAP_MANBALL)
  105.             {
  106.                 manPosition.x = j;
  107.                 manPosition.y = i;
  108.             }
  109.         }
  110.     }
  111.     return manPosition;
  112. }
  113. void CBoxMan::DrawGameArea(CDC* pDC)
  114. {
  115.     int i, j, x, y;
  116. //绘制整个地图游戏区域
  117.     for (i = 0; i < M_TAB_HEIGHT; i++)
  118.     {
  119.         for (j = 0; j < M_TAB_WIDTH; j++)
  120.         {
  121.             x = j * BLOCK_WIDTH;
  122.             y = i * BLOCK_HEIGHT;
  123.             switch (m_cMap[i][j])
  124.             {
  125.             case MAP_BACKGROUP://背景
  126.                 DrawBackGroup(x, y, pDC);
  127.                 break;
  128.             case MAP_WHITEWALL://墙
  129.                 DrawWhiteWall(x, y, pDC);
  130.                 break;
  131.             case MAP_BLUEWALL://通道
  132.                 DrawBlueWall(x, y, pDC);
  133.                 break;
  134.             case MAP_BALL://目的地
  135.                 DrawBall(x, y, pDC);
  136.                 break;
  137.             case MAP_YELLOWBOX://未安放好的箱子
  138.                 DrawYellowBox(x, y, pDC);
  139.                 break;
  140.             case MAP_REDBOX://安放好的箱子
  141.                 DrawRedBox(x, y, pDC);
  142.                 break;
  143.             case MAP_MANWALL://人在通道区域
  144.                 DrawManWall(x, y, pDC);
  145.                 break;
  146.             case MAP_MANBALL://人在目的地区域
  147.                 DrawManBall(x, y, pDC);
  148.                 break;
  149.             }
  150.         }
  151.     }
  152. //获取旧的文本配置
  153.     COLORREF crOldText = pDC->GetTextColor();
  154.     COLORREF crOldBack = pDC->GetBkColor();
  155. //更改当前的文本配置
  156.     pDC->SetTextColor(RGB(0, 0, 102));
  157. pDC->SetBkColor(RGB(0, 0, 0));
  158. //输出文本
  159.     CString sTmp;
  160.     sTmp.Format("当前关数 : %d ", m_iMissionNum);
  161.     pDC->TextOut(50, 270, sTmp);
  162. //恢复原来文本配置
  163.     pDC->SetTextColor(crOldText);
  164.     pDC->SetBkColor(crOldBack);
  165. }
  166. //
  167. //  绘制背景
  168. //
  169. void CBoxMan::DrawBackGroup(int x, int y, CDC* pDC)
  170. {
  171.     COLORREF clr = RGB(0, 0, 0);
  172.     pDC->FillSolidRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT, clr);
  173. }
  174. //
  175. //  绘制墙
  176. //
  177. void CBoxMan::DrawWhiteWall(int x, int y, CDC* pDC)
  178. {
  179.     COLORREF clr1 = RGB(255, 255, 255);
  180.     COLORREF clr2 = RGB(48, 48, 48);
  181.     COLORREF clr3 = RGB(192, 192, 192);
  182. //重叠错开绘制3D效果,利用3层渐变
  183.     pDC->FillSolidRect(x, y, 19, 19, clr1);
  184.     pDC->FillSolidRect(x + 1, y + 1, 19, 19, clr2);
  185.     pDC->FillSolidRect(x + 1, y + 1, 18, 18, clr3);
  186. //绘制墙的缝隙
  187.     pDC->MoveTo(x, y + 10);
  188.     pDC->LineTo(x + 20, y + 10);
  189.     pDC->MoveTo(x + 10, y + 10);
  190.     pDC->LineTo(x + 10, y + 20);
  191. }
  192. //
  193. //  绘制通道
  194. //
  195. void CBoxMan::DrawBlueWall(int x, int y, CDC* pDC)
  196. {
  197.     COLORREF clr = RGB(0, 0, 255);
  198.     pDC->FillSolidRect(x, y, 20, 20, clr);
  199.     pDC->MoveTo(x, y + 10);
  200.     pDC->LineTo(x + 20, y + 10);
  201.     pDC->MoveTo(x + 10, y + 10);
  202.     pDC->LineTo(x + 10, y + 20);
  203. }
  204. //
  205. //  绘制目的地
  206. //
  207. void CBoxMan::DrawBall(int x, int y, CDC* pDC)
  208. {
  209.     COLORREF clr = RGB(0, 0, 255);
  210.     pDC->FillSolidRect(x, y, 20, 20, clr);
  211.     pDC->MoveTo(x, y + 10);
  212.     pDC->LineTo(x + 20, y + 10);
  213.     pDC->MoveTo(x + 10, y + 10);
  214.     pDC->LineTo(x + 10, y + 20);
  215.     pDC->Ellipse(x, y, x + 20, y + 20);
  216.     pDC->Ellipse(x + 5, y + 5, x + 15, y + 15);
  217. }
  218. //
  219. //  绘制未放好的箱子
  220. //
  221. void CBoxMan::DrawYellowBox(int x, int y, CDC* pDC)
  222. {
  223.     COLORREF clr = RGB(255, 255, 0);
  224.     pDC->FillSolidRect(x, y, 20, 20, clr);
  225.     COLORREF clr2 = RGB(255, 192, 0);
  226.     pDC->FillSolidRect(x + 2, y + 2, 16, 16, clr2);
  227.     COLORREF clr3 = RGB(0, 0, 0);
  228.     pDC->SetPixel(x + 3, y + 3, clr3);
  229.     pDC->SetPixel(x + 17, y + 3, clr3);
  230.     pDC->SetPixel(x + 3, y + 17, clr3);
  231.     pDC->SetPixel(x + 17, y + 17, clr3);
  232. }
  233. //
  234. //  绘制安放好的箱子
  235. //
  236. void CBoxMan::DrawRedBox(int x, int y, CDC* pDC)
  237. {
  238.     COLORREF clr = RGB(255, 255, 0);
  239.     pDC->FillSolidRect(x, y, 20, 20, clr);
  240.     COLORREF clr2 = RGB(255, 0, 0);
  241.     pDC->FillSolidRect(x + 2, y + 2, 16, 16, clr2);
  242.     COLORREF clr3 = RGB(0, 0, 0);
  243.     pDC->SetPixel(x + 3, y + 3, clr3);
  244.     pDC->SetPixel(x + 17, y + 3, clr3);
  245.     pDC->SetPixel(x + 3, y + 17, clr3);
  246.     pDC->SetPixel(x + 17, y + 17, clr3);
  247. }
  248. //
  249. //  绘制人在通道
  250. //
  251. void CBoxMan::DrawManWall(int x, int y, CDC* pDC)
  252. {
  253.     COLORREF clr = RGB(0, 0, 255);                   //蓝色墙
  254.     pDC->FillSolidRect(x, y, 20, 20, clr);
  255.     pDC->MoveTo(x, y + 10);
  256.     pDC->LineTo(x + 20, y + 10);
  257.     pDC->MoveTo(x + 10, y + 10);
  258.     pDC->LineTo(x + 10, y + 20);
  259. //人的绘制
  260.     pDC->Ellipse(x + 6, y + 2, x + 14, y + 10);      //人头
  261.     pDC->MoveTo(x + 2, y + 11);                      //人手
  262.     pDC->LineTo(x + 18, y + 11);
  263.     pDC->MoveTo(x + 10, y + 10);                     //人身体
  264.     pDC->LineTo(x + 10, y + 12);
  265.     pDC->MoveTo(x + 2, y + 20);                      //人脚
  266.     pDC->LineTo(x + 10, y + 12);
  267.     pDC->LineTo(x + 18, y +20);
  268. }
  269. //
  270. //  绘制人在目的地
  271. //
  272. void CBoxMan::DrawManBall(int x, int y, CDC* pDC)
  273. {
  274.     COLORREF clr = RGB(0, 0, 255);                   //球
  275.     pDC->FillSolidRect(x, y, 20, 20, clr);
  276.     pDC->MoveTo(x, y + 10);
  277.     pDC->LineTo(x + 20, y + 10);
  278.     pDC->MoveTo(x + 10, y + 10);
  279.     pDC->LineTo(x + 10, y + 20);
  280.     pDC->Ellipse(x, y, x + 20, y + 20);
  281.     pDC->Ellipse(x + 5, y + 5, x + 15, y + 15);
  282. //人的绘制
  283.     pDC->Ellipse(x + 6, y + 2, x + 14, y + 10);      //人头
  284.     pDC->MoveTo(x + 2, y + 11);                      //人手
  285.     pDC->LineTo(x + 18, y + 11);
  286.     pDC->MoveTo(x + 10, y + 10);                     //人身体
  287.     pDC->LineTo(x + 10, y + 12);
  288.     pDC->MoveTo(x + 2, y + 20);                      //人脚
  289.     pDC->LineTo(x + 10, y + 12);
  290.     pDC->LineTo(x + 18, y +20);
  291. }
  292. void CBoxMan::KeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  293. {
  294.     DispatchMsg(nChar);
  295.     if (IsFinish())
  296.     {
  297. m_soundState = SOUND_STATE_VICTORY;
  298.         m_iMissionNum = m_iMissionNum +1;
  299.         if (m_iMissionNum > MAX_MISSION_NUM)
  300.             m_iMissionNum = 1;
  301.         LoadMap(m_iMissionNum);
  302.         m_ptManPosition = GetManPosition();
  303.     }
  304. BoxManPlaySound();
  305. }
  306. void CBoxMan::DispatchMsg(UINT nChar)
  307. {
  308.     int x1, y1, x2, y2, x3, y3;
  309. //获取工人当前位置
  310.     x1 = m_ptManPosition.x;
  311.     y1 = m_ptManPosition.y;
  312. //分析按键消息
  313.     switch (nChar)
  314.     {
  315. //向上
  316.     case VK_UP:
  317.         x2 = x1;
  318.         y2 = y1 - 1;
  319.         x3 = x1;
  320.         y3 = y1 - 2;
  321. //将所有位置输入以判断并作地图更新
  322.         UpdateMap(x1, y1, x2, y2, x3, y3);
  323.         break;
  324. //向下
  325.     case VK_DOWN:
  326.         x2 = x1;
  327.         y2 = y1 + 1;
  328.         x3 = x1;
  329.         y3 = y1 + 2;
  330.         UpdateMap(x1, y1, x2, y2, x3, y3);
  331.         break;
  332. //向左
  333.     case VK_LEFT:
  334.         x2 = x1 - 1;
  335.         y2 = y1;
  336.         x3 = x1 - 2;
  337.         y3 = y1;
  338.         UpdateMap(x1, y1, x2, y2, x3, y3);
  339.         break;
  340. //向右
  341.     case VK_RIGHT:
  342.         x2 = x1 + 1;
  343.         y2 = y1;
  344.         x3 = x1 + 2;
  345.         y3 = y1;
  346.         UpdateMap(x1, y1, x2, y2, x3, y3);
  347.         break;
  348.   //选关功能键
  349.     case 82:  //R  重新玩当前关
  350.     case 114: //r  
  351.         LoadMap(m_iMissionNum);
  352.         m_ptManPosition = GetManPosition();
  353.         break;
  354.     case 113:  //F2  跳到下一关
  355.         m_iMissionNum = m_iMissionNum + 1;
  356.         if (m_iMissionNum > MAX_MISSION_NUM)
  357.             m_iMissionNum = 1;
  358.         LoadMap(m_iMissionNum);
  359.         m_ptManPosition = GetManPosition();
  360.         break;
  361.     case 112:  //F1  跳到前一关
  362.         m_iMissionNum = m_iMissionNum - 1;
  363.         if (m_iMissionNum < 1)
  364.             m_iMissionNum = MAX_MISSION_NUM;
  365.         LoadMap(m_iMissionNum);
  366.         m_ptManPosition = GetManPosition();
  367.     }
  368. }
  369. void CBoxMan::UpdateMap(int x1, int y1, int x2, int y2, int x3, int y3)
  370. {
  371.     switch (m_cMap[y2][x2])
  372.     {
  373.     case MAP_BACKGROUP:           //地图设计错误,不应该出现
  374.         AfxMessageBox("wrong map");
  375.         break;
  376.     case MAP_WHITEWALL:          //遇到墙,不做任何事情
  377.         
  378.         break;
  379.     case MAP_BLUEWALL:           //通道,可以行走
  380.         m_cMap[y2][x2] = MAP_MANWALL;
  381.         if (m_cMap[y1][x1] == MAP_MANWALL)
  382.             m_cMap[y1][x1] = MAP_BLUEWALL;
  383.         else if (m_cMap[y1][x1] == MAP_MANBALL)
  384.             m_cMap[y1][x1] = MAP_BALL;
  385.         m_ptManPosition.x = x2;
  386.         m_ptManPosition.y = y2;
  387. m_soundState = SOUND_STATE_MOVE;
  388.         break;
  389.     case MAP_BALL:               //目的地,可以行走
  390.         m_cMap[y2][x2] = MAP_MANBALL;
  391.         if (m_cMap[y1][x1] == MAP_MANWALL)
  392.             m_cMap[y1][x1] = MAP_BLUEWALL;
  393.         else if (m_cMap[y1][x1] == MAP_MANBALL)
  394.             m_cMap[y1][x1] = MAP_BALL;        
  395.         m_ptManPosition.x = x2;
  396.         m_ptManPosition.y = y2;
  397. m_soundState = SOUND_STATE_MOVE;
  398.         break;
  399.     case MAP_YELLOWBOX:          //箱子
  400.         if (m_cMap[y3][x3] == MAP_BALL)   //目的地可以行走
  401.         {
  402.             m_cMap[y3][x3] = MAP_REDBOX;
  403.             m_cMap[y2][x2] = MAP_MANWALL;
  404.             if (m_cMap[y1][x1] == MAP_MANWALL)
  405.                 m_cMap[y1][x1] = MAP_BLUEWALL;
  406.             else if (m_cMap[y1][x1] == MAP_MANBALL)
  407.                 m_cMap[y1][x1] = MAP_BALL;
  408.             m_ptManPosition.x = x2;
  409.             m_ptManPosition.y = y2;
  410. m_soundState = SOUND_STATE_PUSH;
  411.         }
  412.         else if (m_cMap[y3][x3] == MAP_BLUEWALL) //通道,可以行走
  413.         {
  414.             m_cMap[y3][x3] = MAP_YELLOWBOX;
  415.             m_cMap[y2][x2] = MAP_MANWALL;
  416.             if (m_cMap[y1][x1] == MAP_MANWALL)
  417.                 m_cMap[y1][x1] = MAP_BLUEWALL;
  418.             else if (m_cMap[y1][x1] == MAP_MANBALL)
  419.                 m_cMap[y1][x1] = MAP_BALL;
  420.             m_ptManPosition.x = x2;
  421.             m_ptManPosition.y = y2;
  422. m_soundState = SOUND_STATE_PUSH;
  423.         }
  424.         break;
  425.     case MAP_REDBOX:             //安放好的箱子
  426.         if (m_cMap[y3][x3] == MAP_BALL)   //目的地可以行走
  427.         {
  428.             m_cMap[y3][x3] = MAP_REDBOX;
  429.             m_cMap[y2][x2] = MAP_MANBALL;
  430.             if (m_cMap[y1][x1] == MAP_MANWALL)
  431.                 m_cMap[y1][x1] = MAP_BLUEWALL;
  432.             else if (m_cMap[y1][x1] == MAP_MANBALL)
  433.                 m_cMap[y1][x1] = MAP_BALL;
  434.             m_ptManPosition.x = x2;
  435.             m_ptManPosition.y = y2;
  436. m_soundState = SOUND_STATE_PUSH;
  437.         }
  438.         else if (m_cMap[y3][x3] == MAP_BLUEWALL)  //通道,可以行走
  439.         {
  440.             m_cMap[y3][x3] = MAP_YELLOWBOX;
  441.             m_cMap[y2][x2] = MAP_MANBALL;
  442.             if (m_cMap[y1][x1] == MAP_MANWALL)
  443.                 m_cMap[y1][x1] = MAP_BLUEWALL;
  444.             else if (m_cMap[y1][x1] == MAP_MANBALL)
  445.                 m_cMap[y1][x1] = MAP_BALL;
  446.             m_ptManPosition.x = x2;
  447.             m_ptManPosition.y = y2;
  448. m_soundState = SOUND_STATE_PUSH;
  449.         }        
  450.         break;
  451.     case MAP_MANWALL:            //地图设计错误,不应该出现
  452.         AfxMessageBox("wrong map");
  453.         break;
  454.     case MAP_MANBALL:            //地图设计错误,不应该出现
  455.         AfxMessageBox("wrong map");
  456.         break;
  457.     }
  458. }
  459. bool CBoxMan::IsFinish()
  460. {
  461.     bool bFinish = true;
  462.     for (int i = 0; i < M_TAB_HEIGHT; i++)
  463.     {
  464.         for (int j = 0; j < M_TAB_WIDTH; j++)
  465.         {
  466.             if (m_cMap[i][j] == MAP_BALL || m_cMap[i][j] == MAP_MANBALL)
  467.                 bFinish = false;
  468.         }
  469.     }
  470.     return bFinish;
  471. }
  472. BOOL CBoxMan::ChangeMissionNum(int iNum)
  473. {
  474. if((iNum>MAX_MISSION_NUM)||(iNum<1))
  475. {
  476. return FALSE;
  477. }
  478. else
  479. {
  480.         m_iMissionNum = iNum;
  481.         LoadMap(m_iMissionNum);
  482.         m_ptManPosition = GetManPosition();
  483. return TRUE;
  484. }
  485. }
  486. int  CBoxMan::GetNowMissionNum(void)
  487. {
  488. return m_iMissionNum;
  489. }
  490. void CBoxMan::BoxManPlaySound(void)
  491. {
  492. if(m_bSound)
  493. {
  494. char strFileName[30];
  495. switch (m_soundState)
  496. {
  497. case SOUND_STATE_START :
  498. strcpy(strFileName,"start.wav");
  499. break;
  500. case SOUND_STATE_MOVE :
  501. strcpy(strFileName,"move.wav");
  502. break;
  503. case SOUND_STATE_PUSH :
  504. strcpy(strFileName,"push.wav");
  505. break;
  506. case SOUND_STATE_VICTORY :
  507. strcpy(strFileName,"victory.wav");
  508. break;
  509. default:
  510. return;
  511. }
  512. PlaySound(strFileName, NULL, SND_ASYNC | SND_FILENAME);
  513. }
  514. }
  515. void CBoxMan::IsSound(BOOL bUse)
  516. {
  517. m_bSound = bUse;
  518. }