需要源码和资源请点赞关注收藏后评论区留言私信~~~
在前面的博客中已经讲解了推箱子游戏的菜单和各种对话框的实现,下面对推箱子游戏的核心算法设计和实现进行讲解
一、地图文件读取模块的设计与实现
地图文件读取模块,主要负责将地图文件进行读取,并把相应的文件数据转换成地图显示出来,其设计步骤如下
1:读取当前文件夹中的地图文件
2:判断当前选择关口是否在文件中存在
3:如果存在则把当前关口的地图信息放置到地图数组中
其实现代码如下
- void CBoxManDlg::loadMap(int iMissionNum)
- {
- CString str;
- str.Format("[%d]", iMissionNum);
- FILE *pFile = fopen("map.txt", "rb");
- if (pFile == NULL)
- return;
- char cTmp[20];
- fgets(cTmp, 20, pFile);
- while (strncmp(cTmp, str, 3) != 0)
- {
- fgets(cTmp, 20, pFile);
- }
- for (int i = 0; i < 14; i++)
- fgets(m_cMap[i], 20, pFile);
- fclose(pFile);
- }
二、地图绘制模块的设计与实现
绘制地图模块主要负责将地图数组中的数据绘制成地图图像,其设计分为如下几个步骤
1:根据要求,实现不同类型格子的绘制函数,地图数组以及地图文件中各个字符代表的意思如下
2:读取地图数据,根据不同的数据调用不同的绘图函数
代码如下
- void CBoxManDlg::drawMap(CDC *pDC)
- {
- int i, j, x, y;
- for (i = 0; i < 14; i++)
- {
- for (j = 0; j < 16; j++)
- {
- x = j * 20;
- y = i * 20;
- switch (m_cMap[i][j])
- {
- case MAP_BACK://0
- drawBack(x, y, pDC);
- break;
- case MAP_WHITEWALL://1
- drawWhiteWall(x, y, pDC);
- break;
- case MAP_BLUEWALL://2
- drawBlueWall(x, y, pDC);
- break;
- case MAP_BALL://3
- drawBall(x, y, pDC);
- break;
- case MAP_BOX://4
- drawBox(x, y, pDC);
- break;
- case MAP_REDBOX://5
- drawRedBox(x, y, pDC);
- break;
- case MAP_MAN://6
- drawMan(x, y, pDC);
- break;
- case MAP_MANBALL://7
- drawManBall(x, y, pDC);
- break;
- }
- }
- }
-
- COLORREF crText = pDC->GetTextColor();
- COLORREF crBack = pDC->GetBkColor();
- pDC->SetTextColor(RGB(255, 0, 0));
- pDC->SetBkColor(RGB(255, 255, 255));
- CString str;
- str.Format("当前等级: %02d", g_level);
- pDC->TextOut(330, 50, str);
- str.Format("已走步数: %03d", passtime);
- pDC->TextOut(330, 100, str);
- }
- void CBoxManDlg::drawBack(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(0, 0, 0);
- pDC->FillSolidRect(x, y, 20, 20, clr);
- }
-
- void CBoxManDlg::drawWhiteWall(int x, int y, CDC *pDC)
- {
- COLORREF clr1 = RGB(255, 255, 255);
- COLORREF clr2 = RGB(48, 48, 48);
- COLORREF clr3 = RGB(192, 192, 192);
- pDC->FillSolidRect(x, y, 19, 19, clr1);
- pDC->FillSolidRect(x + 1, y + 1, 19, 19, clr2);
- pDC->FillSolidRect(x + 1, y + 1, 18, 18, clr3);
- pDC->MoveTo(x, y + 10);
- pDC->LineTo(x + 20, y + 10);
- pDC->MoveTo(x + 10, y + 10);
- pDC->LineTo(x + 10, y + 20);
- }
-
- void CBoxManDlg::drawBlueWall(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(0, 0, 255);
- pDC->FillSolidRect(x, y, 20, 20, clr);
- pDC->MoveTo(x, y + 10);
- pDC->LineTo(x + 20, y + 10);
- pDC->MoveTo(x + 10, y + 10);
- pDC->LineTo(x + 10, y + 20);
- }
-
- void CBoxManDlg::drawBall(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(0, 0, 255);
- pDC->FillSolidRect(x, y, 20, 20, clr);
- pDC->MoveTo(x, y + 10);
- pDC->LineTo(x + 20, y + 10);
- pDC->MoveTo(x + 10, y + 10);
- pDC->LineTo(x + 10, y + 20);
- pDC->Ellipse(x, y, x + 20, y + 20);
- pDC->Ellipse(x + 5, y + 5, x + 15, y + 15);
- }
-
- void CBoxManDlg::drawBox(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(255, 255, 0);
- pDC->FillSolidRect(x, y, 20, 20, clr);
- COLORREF clr2 = RGB(255, 192, 0);
- pDC->FillSolidRect(x + 2, y + 2, 16, 16, clr2);
- COLORREF clr3 = RGB(0, 0, 0);
- pDC->SetPixel(x + 3, y + 3, clr3);
- pDC->SetPixel(x + 17, y + 3, clr3);
- pDC->SetPixel(x + 3, y + 17, clr3);
- pDC->SetPixel(x + 17, y + 17, clr3);
- }
-
- void CBoxManDlg::drawRedBox(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(255, 255, 0);
- pDC->FillSolidRect(x, y, 20, 20, clr);
- COLORREF clr2 = RGB(255, 0, 0);
- pDC->FillSolidRect(x + 2, y + 2, 16, 16, clr2);
- COLORREF clr3 = RGB(0, 0, 0);
- pDC->SetPixel(x + 3, y + 3, clr3);
- pDC->SetPixel(x + 17, y + 3, clr3);
- pDC->SetPixel(x + 3, y + 17, clr3);
- pDC->SetPixel(x + 17, y + 17, clr3);
- }
-
- void CBoxManDlg::drawMan(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(0, 0, 255); //蓝色墙
- pDC->FillSolidRect(x, y, 20, 20, clr);
- pDC->MoveTo(x, y + 10);
- pDC->LineTo(x + 20, y + 10);
- pDC->MoveTo(x + 10, y + 10);
- pDC->LineTo(x + 10, y + 20);
- pDC->Ellipse(x + 6, y + 2, x + 14, y + 10); //人头
- pDC->MoveTo(x + 2, y + 11); //人手
- pDC->LineTo(x + 18, y + 11);
- pDC->MoveTo(x + 10, y + 10); //人身体
- pDC->LineTo(x + 10, y + 12);
- pDC->MoveTo(x + 2, y + 20); //人脚
- pDC->LineTo(x + 10, y + 12);
- pDC->LineTo(x + 18, y +20);
- }
-
- void CBoxManDlg::drawManBall(int x, int y, CDC *pDC)
- {
- COLORREF clr = RGB(0, 0, 255); //球
- pDC->FillSolidRect(x, y, 20, 20, clr);
- pDC->MoveTo(x, y + 10);
- pDC->LineTo(x + 20, y + 10);
- pDC->MoveTo(x + 10, y + 10);
- pDC->LineTo(x + 10, y + 20);
- pDC->Ellipse(x, y, x + 20, y + 20);
- pDC->Ellipse(x + 5, y + 5, x + 15, y + 15);
- pDC->Ellipse(x + 6, y + 2, x + 14, y + 10); //人头
- pDC->MoveTo(x + 2, y + 11); //人手
- pDC->LineTo(x + 18, y + 11);
- pDC->MoveTo(x + 10, y + 10); //人身体
- pDC->LineTo(x + 10, y + 12);
- pDC->MoveTo(x + 2, y + 20); //人脚
- pDC->LineTo(x + 10, y + 12);
- pDC->LineTo(x + 18, y +20);
- }
三、键盘操作模块的设计与实现
键盘操作模块主要负责接收玩家键盘输入并进行箱子移动等处理,其设计比较简单,只需要通过如下几步即可实现
1:通过截获当前窗口键盘按下消息来判断玩家按下的按键
2:根据玩家标下的按键把主角的相关坐标进行加减,
3:增加后的数据与地图数组中的数据进行比较,只要不是白墙就可以移动,如果是箱子还需要将箱子的坐标进行移动
4:但要注意,要判断箱子移动后的坐标是否可以移动
代码如下
- BOOL CBoxManDlg::PreTranslateMessage(MSG* pMsg)
- {
- if(pMsg->message == WM_KEYDOWN)
- {
- updateMap(pMsg->wParam);
- Invalidate(false);
- if (isFinish())
- {
- AfxMessageBox("您获得胜利,将进入下一关!");
- g_level = g_level +1;
- if (g_level > g_maxlevel)
- g_level = 1;
- GameStart();
-
- }
- }
- return CDialog::PreTranslateMessage(pMsg);
- }
- void CBoxManDlg::updateMap(UINT nChar)
- {
- int x1, y1, x2, y2, x3, y3;
- x1 = m_ptManPosition.x;
- y1 = m_ptManPosition.y;
- switch (nChar)
- {
- case VK_UP:
- x2 = x1;
- y2 = y1 - 1;
- x3 = x1;
- y3 = y1 - 2;
- ReDrawMap(x1, y1, x2, y2, x3, y3);
- break;
- case VK_DOWN:
- x2 = x1;
- y2 = y1 + 1;
- x3 = x1;
- y3 = y1 + 2;
- ReDrawMap(x1, y1, x2, y2, x3, y3);
- break;
- case VK_LEFT:
- x2 = x1 - 1;
- y2 = y1;
- x3 = x1 - 2;
- y3 = y1;
- ReDrawMap(x1, y1, x2, y2, x3, y3);
- break;
- case VK_RIGHT:
- x2 = x1 + 1;
- y2 = y1;
- x3 = x1 + 2;
- y3 = y1;
- ReDrawMap(x1, y1, x2, y2, x3, y3);
- break;
- default:
- break;
- }
- }
-
- void CBoxManDlg::ReDrawMap(int x1, int y1, int x2, int y2, int x3, int y3)
- {
- switch (m_cMap[y2][x2])
- {
- case MAP_BACK: //地图有问题
- MessageBox("地图有问题");
- break;
- case MAP_WHITEWALL:
- break;
- case MAP_BLUEWALL:
- m_cMap[y2][x2] = MAP_MAN;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- break;
- case MAP_BALL:
- m_cMap[y2][x2] = MAP_MANBALL;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- break;
- case MAP_BOX:
- if (m_cMap[y3][x3] == MAP_BALL)
- {
- m_cMap[y3][x3] = MAP_REDBOX;
- m_cMap[y2][x2] = MAP_MAN;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- }
- else if (m_cMap[y3][x3] == MAP_BLUEWALL)
- {
- m_cMap[y3][x3] = MAP_BOX;
- m_cMap[y2][x2] = MAP_MAN;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- }
- break;
- case MAP_REDBOX:
- if (m_cMap[y3][x3] == MAP_BALL)
- {
- m_cMap[y3][x3] = MAP_REDBOX;
- m_cMap[y2][x2] = MAP_MANBALL;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- }
- else if (m_cMap[y3][x3] == MAP_BLUEWALL)
- {
- m_cMap[y3][x3] = MAP_BOX;
- m_cMap[y2][x2] = MAP_MANBALL;
- if (m_cMap[y1][x1] == MAP_MAN)
- m_cMap[y1][x1] = MAP_BLUEWALL;
- else if (m_cMap[y1][x1] == MAP_MANBALL)
- m_cMap[y1][x1] = MAP_BALL;
- m_ptManPosition.x = x2;
- m_ptManPosition.y = y2;
- passtime++;
- }
- break;
- case MAP_MAN: //地图有问题
- MessageBox("地图有问题");
- break;
- case MAP_MANBALL: //地图有问题
- MessageBox("地图有问题");
- break;
- }
- }
-
- void CBoxManDlg::loadMap(int iMissionNum)
- {
- CString str;
- str.Format("[%d]", iMissionNum);
- FILE *pFile = fopen("map.txt", "rb");
- if (pFile == NULL)
- return;
- char cTmp[20];
- fgets(cTmp, 20, pFile);
- while (strncmp(cTmp, str, 3) != 0)
- {
- fgets(cTmp, 20, pFile);
- }
- for (int i = 0; i < 14; i++)
- fgets(m_cMap[i], 20, pFile);
- fclose(pFile);
- }
四、游戏规则模块的设计与实现
游戏规则模块,注意负责游戏规则的判断,其设计方法比较简单,需要在每次玩家移动主角后,对当前地图数组进行判断
- BOOL CBoxManDlg::isFinish()
- {
- for (int i = 0; i < 14; i++)
- {
- for (int j = 0; j < 16; j++)
- {
- if (m_cMap[i][j] == MAP_BALL || m_cMap[i][j] == MAP_MANBALL)
- {
- return FALSE;
- }
- }
- }
- return TRUE;
- }
五、主对话框的设计与实现
主要有如下几个部分
1:游戏初始化处理函数
2:菜单初始化处理函数
3:绘图函数处理
- void CBoxManDlg::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // device context for painting
-
- SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
-
- // Center icon in client rectangle
- int cxIcon = GetSystemMetrics(SM_CXICON);
- int cyIcon = GetSystemMetrics(SM_CYICON);
- CRect rect;
- GetClientRect(&rect);
- int x = (rect.Width() - cxIcon + 1) / 2;
- int y = (rect.Height() - cyIcon + 1) / 2;
-
- // Draw the icon
- dc.DrawIcon(x, y, m_hIcon);
- }
- else
- {
- CPaintDC dc(this);
- drawMap(&dc);
- CDialog::OnPaint();
- }
- }
创作不易 觉得有帮助请点赞关注收藏~~~
文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览44032 人正在系统学习中