Visual C++实现推箱子游戏的核心算法设计与实现(附源码和和资源)

news2024/9/21 22:33:48

需要源码和资源请点赞关注收藏后评论区留言私信~~~

在前面的博客中已经讲解了推箱子游戏的菜单和各种对话框的实现,下面对推箱子游戏的核心算法设计和实现进行讲解

一、地图文件读取模块的设计与实现

地图文件读取模块,主要负责将地图文件进行读取,并把相应的文件数据转换成地图显示出来,其设计步骤如下

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();
	}
}

 

 

 创作不易 觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/511864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI大模型】“讯飞星火”认知大模型正式发布 计划10月底赶超ChatGPT

文章目录 前言你使用过这种对话式AI吗&#xff1f;有什么看法或感受&#xff1f;“讯飞星火大模型将超越chatgpt&#xff1f;”这类型的人工智能对现在的社会有什么意义&#xff1f;这类型的人工智能&#xff0c;未来前景如何&#xff1f;申请体验写在最后 前言 5月6日&#xf…

科普:跨链桥是如何被黑的?

科普&#xff1a;跨链桥是如何被黑的&#xff1f; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbvPVTkb-1666679410875)(htTPS://tva1.sinaimg.cn/large/e6c9d24ely1h4r0auxvmxg20tr04ojug.gif)] 跨链桥是一种允许两个独立区块链网络之间进行通信…

【git】用好 stash,工作超nice

一、介绍 如果修改后的内容还不想commit&#xff0c;就可以用git stash命令。它会将工作区和暂存区中的修改(也就是还没commit的内容)都会被保存到堆栈里&#xff0c;并在之后恢复到任意指定的分支上。 二、应用场景 1、在分支a进行开发feature 1时&#xff0c;突然需要紧急…

【AI大模型】讯飞星火大模型能否超越chatgpt?

文章目录 前言你使用过这种对话式AI吗&#xff1f;有什么看法或感受&#xff1f;“讯飞星火大模型将超越chatgpt&#xff1f;”这类型的人工智能对现在的社会有什么意义&#xff1f;这类型的人工智能&#xff0c;未来前景如何&#xff1f;申请体验写在最后 前言 5月6日&#xf…

机器学习-10 聚类算法

聚类算法 算法概括聚类&#xff08;clustering&#xff09;聚类的概念聚类的要求聚类与分类的区别 常见算法分类聚类算法中存在的问题 距离度量闵可夫斯基距离欧式距离&#xff08;欧几里得距离&#xff09;曼哈顿距离切比雪夫距离皮尔逊相关系数余弦相似度杰卡德相似系数 划分…

建造者模式详解:建造随意搭配的肯德基套餐

一、简介 建造者模式&#xff08;Builder Pattern&#xff09;是五种创建型设计模式之一&#xff0c;它将一个复杂对象的构建与其表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。这句话怎么理解呢&#xff1a;一个对象的构建过程本质上就是这个对象包含的所有成员…

一觉醒来IDEA感觉不香了,AI智能编程工具Cursor使用

一、简介 为使用人工智能编程而构建的编辑器&#xff0c;一款人工智能编程软件、智能Ai代码生成工具。 它有什么特点呢&#xff1f; 集成了GPT-4&#xff0c;国内可用&#xff0c;不仅有ChatGPT的聊天功能&#xff0c;还有强大的自动代码生成能力&#xff0c;简直是编码神器。 …

Java中常见的几种数组排序方法

这篇文章总结一下我学习到的几种常见的数组排序方法 冒泡排序 冒泡排序在我看来是最简单、最基本的排序方法&#xff0c;我们应当将冒泡排序的原理和代码熟记于心。 冒泡排序的原理十分简单&#xff1a;用数组的第一个元素和第二个元素进行比较&#xff0c;将大的放到后面&a…

【Java编程系列】Minio实现文件上传下载

热门系列&#xff1a; 【Java编程系列】Amazon S3实现文件上传下载 目录 热门系列&#xff1a; 1、前言 2、Minio实战代码 2.1 Minio环境部署 2.2 Minio的Sdk对接实现 2.2.1 Minio Maven依赖 2.2.2 minio配置与初始化 2.2.3 上传文件 2.2.4 下载文件 2.2.5 生成文件…

【LLM大模型】LLM模型和指令微调方法

note 文章目录 note零、AIGC生成式模型1. 核心要素2. LLM evolutionary tree3. 几个bigScience里的概念 二、LLM大模型1. ChatGLM&#xff08;1&#xff09;GLM-130B&#xff08;2&#xff09;ChatGLM-6B 2. LLaMA3. RoBERTa4. Bloom5. PaLM 三、模型指令微调1. 指令微调的注意…

使用Vue+Vue-router+el-menu实现菜单功能实战

前言 上节回顾 上一小节我们使用H5+CSS3实现了管理平台的架构布局,并且通过Vuex的使用,获取到前端数据本地化存储的username,绑定到右上角进行全局展示。还不了解上下文的同学可以回顾一下 使用Vue+Vuex+CSS3完成管理端响应式架构模板实战 。 本节介绍 本小节已经是专栏的…

【C语言】字符串---刷题篇

1.统计字符串中元音字母的字数 2.使用起泡法和选择法将字符串按ASCII码值从小到大排列 3.将字符串中的数字字符倒置&#xff0c;即‘0’变‘9’、‘1’变‘8’、…、‘9’变‘0’.例如&#xff1a;字符串“a1b2c3d4e9f0”倒置变为“a8b7c6d5e0f9 4.将一个字符串中从第m个字符开…

187页9万字企业大数据治理与云平台实施方案(word)

1 项目背景概述 1.1 项目背景理解 1.2 项目需求范围 2 项目技术方案 2.1 咨询研究服务方案 2.1.1 咨询研究服务内容 2.1.2 咨询服务方案 2.2 第三方独立评估 2.2.1 概述 2.2.2 管理办法 2.2.3 考核机制 2.3 安全咨询研究服务方案 2.3.1 安全咨询服务内…

大唐杯学习笔记(1)—— 5G网络架构与组网部署

目录 一、名词汇总1.核心网与接入网2.5G网络架构3.核心网架构演进(1)2G核心网(1)3G&#xff0c;4G核心网 4.4G核心网架构5.5G核心网架构6.5G接入网网架构7.主要网元功能 二、5G主要网元功能1.用户面功能UPF(User Plane Function)2.会话管理功能SMF(Session Management Function…

【SpringCloud微服务实践】服务注册与发现(理论)

注册与发现 在之前的示例中&#xff0c;采取的是硬编码的方式&#xff0c;需要调用的微服务的地址是被我们写死在文件或代码中的。在传统应用程序中&#xff0c;一般都是这么做的&#xff0c;然而这种方式存在不少缺陷&#xff1a; 静态配置&#xff1a;因为是写死的网络地址…

Cy5.5-PEG2000-Biotin,Cy5.5-聚乙二醇-生物素;Biotin-PEG-Cy5.5;可用于检测抗生物素、链霉亲和素或中性生物素

Cyanine5.5-PEG-Biotin&#xff0c;Cy5.5-聚乙二醇-生物素 中文名称;Cy5.5-聚乙二醇-生物素 英文名称;Cyanine5.5-PEG-Biotin 性状&#xff1a;粘稠液体或固体粉末&#xff0c;取决于分子量大小 溶剂&#xff1a;溶于水、氯仿、DMSO等常规性有机溶剂 分子量PEG:1k、2k、3.…

【Python】JupyterLab报错:Server Connection Error如何解决?

文章目录 一、报错情形二、深层原因三、解决方案3.1 重命名用户名3.2 启用Administrator账户3.3 切换Administrator账户3.4 重命名用户文件夹3.5 修改注册表3.6 修改环境变量 小结 Anaconda的JupyterLab 作为优秀的网页编辑器&#xff0c;非常适用于编写Python程序&#xff0c;…

Qt的窗口的设置

窗口外部设置 Qt::WindowFlags Qt::WidgetQWidget默认窗口&#xff0c;没有父窗口的话&#xff0c;是一个独立窗口Qt::Window是一个窗口&#xff0c;有窗口边框和标题Qt::Dialog是一个对话框窗口Qt::Sheet是一个窗口或部件Macintosh表单(sheet)Qt::Drawer是一个窗口或部件Ma…

Mac 安装Nginx详细教程

一、前言 本文介绍一下&#xff0c;如何在Mac系统中安装Nginx&#xff0c;把详细过程记录下来&#xff0c;方便以后查看&#xff0c;也方便大家学习。 二、正文 1、安装 Homebrew homebrew是什么&#xff1f;它是Mac中的一款软件包管理工具&#xff0c;通过brew可以很方便的…

复刻一个羊了个羊掘金商城版

游戏逻辑 与羊了个羊逻辑一致&#xff0c;不再赘述 游戏实现 盛放元素的容器box&#xff0c;临时存储的容器temp&#xff0c;多余元素的容器source与source1&#xff0c;结果元素result <div id"box"></div><div id"temp"></div&…