目录

一、部分设计思想

1.用一个资源类去管理资源,采用单例设计模式:

2.公共需要包含的头文件 common.h

3.静态数据成员要在类外进行初始化。

4.数据和绘图分离

5.整个游戏的逻辑由game完成

6.利用栈,(按空格键)实现悔棋(回退)功能

二、代码部分:

common.h

res.h

res.cpp

data.h

data.cpp

game.h

game.cpp

box.cpp(main)

三、写在最后


成果展示

一、部分设计思想

1.用一个资源类去管理资源,采用单例设计模式:

构造函数私有化

②提供一个静态接口(通过类名直接访问资源)

(资源包括:图片\音乐)

2.公共需要包含的头文件 common.h

#pragma once
#include<iostream>
#include<map>
#include<array>
#include<stack>
#include<conio.h>
#include<graphics.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

3.静态数据成员要在类外进行初始化。

4.数据和绘图分离

5.整个游戏的逻辑由game完成

/改相似代码小技巧:alt+左键选中需要修改的那一部分,ctrl+h进行替换即可。/

6.利用栈,(按空格键)实现悔棋(回退)功能

            原理:利用栈,每次修改地图的放置之前,都将原地图存一份到栈中。当按下空格键,优先检测empty()的值(防止越界),然后若栈中的值不为空,则用top()将地图赋给getmap()然后pop删除。

二、代码部分:

common.h

        主要包含:需要用到的一些容器的头文件,以及音乐播放、图形库等

#pragma once
#include<iostream>
#include<map>
#include<array>
#include<stack>
#include<string>
#include<conio.h>
#include<graphics.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;

res.h

主要包含私有构造函数、静态的构造函数的接口、静态映射map容器来管理资源

#pragma once
#include"common.h"class Res
{
public:static map<string, IMAGE*> img;static map<string, string>music;static void drawIMG(int x, int y, string str);static Res* getInstance();~Res();
private:Res();
};

res.cpp

主要内容:通过构造函数实现对资源之间的映射关系(绑定)

细节:静态数据成员要在类外进行初始化。

#include "res.h"/*静态数据成员要在类外初始化*/
map<string, IMAGE*>Res::img;
map<string, string>Res::music;void Res::drawIMG(int x, int y, string str)
{putimage(x, y, getInstance()->img[str]);
}Res* Res::getInstance()
{static Res* res = new Res;return res;/*所有的资源都用这一个对象即可*/
}Res::~Res()
{delete img["墙"];delete img["路"];delete img["球"];delete img["框"];delete img["人"];delete img["鸡"];}Res::Res()
{img["墙"] = new IMAGE;//0img["路"] = new IMAGE;//0img["球"] = new IMAGE;//4img["框"] = new IMAGE;//3img["人"] = new IMAGE;//5 8img["鸡"] = new IMAGE;//7loadimage(img["墙"], "..//res//img//1.bmp");loadimage(img["路"], "..//res//img//0.bmp");loadimage(img["球"], "..//res//img//4.bmp");loadimage(img["框"], "..//res//img//3.bmp");loadimage(img["人"], "..//res//img//5.bmp");loadimage(img["鸡"], "..//res//img//7.bmp");music["背景"] = "res//music//back.mp3";music["移动"] = "res//music//Boxmove.WAV";}

data.h

  主要内容:①数据成员map表示绘制的地图(0\1\3\5分别对应不同的绘制)

②提供修改地图的接口setValue()、getMap()

③searchPos()用来返回角色所在的坐标({行,列})

④三个判断函数isBox()、isMove()、noBall()分别用来判断当前位置是否是box(篮球)、是否空地、以及是否还有球未进框(用来判断游戏是否需要结束)

#pragma once
#include"common.h"class Data
{
public:void setValue(int i, int j, int value);          //设置地图中的值pair<int, int>searchPos();                       //找任务的坐标bool isBox(int i, int j);bool isMove(int i, int j);bool noBall();array<array<int, 8>, 8>& getMap();
protected:array<array<int, 8>, 8> map       /*8*8的地图*/={1,1,1,1,1,1,1,1,1,3,4,0,0,4,3,1,1,0,1,1,0,1,1,1,1,0,0,0,5,0,0,1,1,0,1,1,0,0,1,1,1,0,1,0,0,4,0,1,1,3,4,0,0,3,0,1,1,1,1,0,0,0,1,1};};

data.cpp

主要内容:相关成员函数的实现过程。

细节:①setValue的时候采用+=的算法,就是为了好让人从篮筐中走开时,还原篮筐

②pair键值对的返回类型的写法{ i, j }就已经表示一个pair<int,int>类型

③isbox()在进行逻辑判断的时候,4和7都要算,因为当为7的时候(即球在篮筐上的时候也要保证是可以推的)

④isMove()保证0和3都算,因为篮筐在此我们认为属于空地的范畴

#include "data.h"void Data::setValue(int i, int j, int value)
{map[i][j] += value;/*注意:这里为何是+=而非=,因为人从篮筐走开,是需要还原篮筐的。*/
}pair<int, int> Data::searchPos()
{/*5和8->显示人   ques:为何8也是人,因为人可能是站在篮筐上,此时map中对应的值对应8*/for (int i = 0; i < 8; i++){for (int j = 0; j < 8; j++){if (map[i][j] == 5 || map[i][j] == 8)return { i,j };/*这样的写法,是因为容器是可以用列表的方式进行初始化的。*/}/*小技巧:列表数据可以直接初始化容器*/}return {-1,-1};/*没找到就返回-1,-1代表没找到人的位置*/
}bool Data::isBox(int i, int j)
{/*球=箱子*//*当前位置是箱子or箱子在篮筐上*/if (map[i][j] == 4 || map[i][j] == 7)return true;return false;
}bool Data::isMove(int i, int j)
{/*判断当前位置是不是空地*/if (map[i][j] == 0 || map[i][j] == 3)  /*0是空地,3是篮筐,可以走,等效于空地*/return true;return false;
}bool Data::noBall()
{for(int i=0;i<8;i++)for (int j = 0; j < 8; j++){if (map[i][j] == 4)return true;/*代表地图中还存在球,游戏还不能结束*/}return false;
}array<array<int, 8>, 8>& Data::getMap()
{return map;//通过接口访问map
}

game.h

主要内容:构造函数、绘制函数、按键捕捉函数、判断游戏结束+

Data类型的指针、一个8*8的栈

  细节:在头文件中用到的自定义类型,尽量使用前向声明的方式(防止交叉包含)

#pragma once
#include"common.h"
class Data;/*小技巧:头文件中用到类型,尽量用前向声明的方式*/
class Game
{
public:Game();void DrawGame();void KeyDown();bool GameOver();
protected:Data* pData;stack<array<array<int, 8>, 8>>mstack;
};

game.cpp

主要内容:①构造函数game()中创建出一个窗口,并播放音乐

②DrawGame()中根据pData中的数据成员中map的值分别对应到绘制相应的图形

③keydown()中主要实现空地移动的逻辑+推球移动的逻辑

细节:①构造函数的参数列表的pData直接new出来

#include "game.h"
#include"data.h"/*不要在头文件中互相包含(用前向声明)!!!,尽量在.cpp中互相包含*/
#include"res.h"Game::Game():pData(new Data)
{initgraph(64 * 8, 64 * 8);/*先打开音乐,再播放音乐*/string open = "open " + Res::getInstance()->music["背景"];mciSendString(open.c_str(), 0, 0, 0);string play = "play " + Res::getInstance()->music["背景"];mciSendString(play.c_str(), 0, 0, 0);}
void Game::DrawGame()
{for (int i = 0; i < 8; i++){for (int j = 0; j < 8; j++){int x = 64 * j;int y = 64 * i;switch (pData->getMap()[i][j]){case 0:              /*路*/putimage(x, y, Res::getInstance()->img["路"]);break;case 1:                /*墙*/putimage(x, y, Res::getInstance()->img["墙"]);break;case 3:                /*框*/putimage(x, y, Res::getInstance()->img["框"]);break;case 4:                /*球*/putimage(x, y, Res::getInstance()->img["球"]);break;case 5:                /*人*/case 8:putimage(x, y, Res::getInstance()->img["人"]);break;case 7:             /*3+4=7->鸡*/putimage(x, y, Res::getInstance()->img["鸡"]);break;}}}
}void Game::KeyDown()
{pair<int, int>role = pData->searchPos();/*得到人物的坐标*/char userkey = _getch();string close = "close" + Res::getInstance()->music["移动"];mciSendString(close.c_str(), 0, 0, 0);/*先打开音乐,再播放音乐,再关闭*/string open = "open" + Res::getInstance()->music["移动"];mciSendString(open.c_str(), 0, 0, 0);string play = "play" + Res::getInstance()->music["移动"]+"wait";mciSendString(play.c_str(), 0, 0, 0);/*注:此处是不用while(1)持续画的,只有当按键后,才需要改变*/switch (userkey){case 'w':case 'W':case 72:if (pData->isMove(role.first - 1, role.second))      //检测行-1的位置(即向上走)是否为空地{mstack.push(pData->getMap());pData->setValue(role.first, role.second ,- 5);   //原来的位置要-5,显示空地or篮筐pData->setValue(role.first - 1, role.second, 5);//w向上移动,+5显示人物}if (pData->isBox(role.first - 1, role.second))      /*若行进方向有箱子*/{if (pData->isMove(role.first - 2, role.second)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);pData->setValue(role.first-1, role.second, 1);/*为啥是1:球走-4  人来+5  =1*/pData->setValue(role.first - 2, role.second, 4);}}break;case 'S':case 's':case 80:if (pData->isMove(role.first + 1, role.second)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);  //原来的位置要-5,显示空地or篮筐pData->setValue(role.first +1, role.second, 5);//S向down移动,+5显示人物}if (pData->isBox(role.first + 1, role.second)){if (pData->isMove(role.first + 2, role.second)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);pData->setValue(role.first + 1, role.second, 1);/*为啥是1,球走-4  人来+5  =1*/pData->setValue(role.first + 2, role.second, 4);}}                                                       /*改相似代码小技巧:alt+左键选中需要修改的那一部分,ctrl+h进行替换即可。*/break;case 'a':case 'A':case 75:if (pData->isMove(role.first , role.second-1)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5); //原来的位置要-5,显示空地or篮筐pData->setValue(role.first , role.second-1, 5);//a向left移动,+5显示人物}if (pData->isBox(role.first, role.second-1)){if (pData->isMove(role.first , role.second-2)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);pData->setValue(role.first , role.second-1, 1);/*为啥是1,球走-4  人来+5  =1*/pData->setValue(role.first , role.second-2, 4);}}break;case 'd':case 'D':case 77:if (pData->isMove(role.first , role.second+1)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);  //原来的位置要-5,显示空地or篮筐pData->setValue(role.first , role.second+1, 5);//d向right移动,+5显示人物}if (pData->isBox(role.first , role.second+1)){if (pData->isMove(role.first , role.second+2)){mstack.push(pData->getMap());pData->setValue(role.first, role.second, -5);pData->setValue(role.first , role.second+1, 1);/*为啥是1,球走-4  人来+5  =1*/pData->setValue(role.first , role.second+2, 4);}}break;case ' ':                                                    /*当空格键被按下*/if (!mstack.empty()){pData->getMap() = mstack.top();mstack.pop();}}
}bool Game::GameOver()
{return pData->noBall();
}

box.cpp(main)

#include"game.h"
int main()
{Game game;game.DrawGame();while (1){game.DrawGame();if (!game.GameOver())break;game.KeyDown();}cout << "恭喜你,通关了!" << endl;return 0;
}

三、写在最后

巩固了stl容器部分的知识.

完整素材见个人主页的资源部分自行下载。   ​​​  ​
C++推箱子https://download.csdn.net/download/zjjaibc/85765465?spm=1001.2014.3001.5503

Day16:C++之STL应用篇(推箱子cxk限定)相关推荐

  1. [新手必备]Unity推箱子小游戏C#代码详解(第一篇-代码部分)

    完整项目请参考博客:https://blog.csdn.net/qq_41676090/article/details/96300302 本文为推箱子小游戏C#代码详解第一篇的代码部分,主要讲解 Sy ...

  2. 使用Rust编写推箱子游戏基础篇

    使用Rust编写推箱子游戏教程已翻译完成 项目地址 在线阅读 推箱子是个啥样的游戏嘞? 没玩过推箱子游戏?想当年用诺基亚黑白屏手机的时候就有这款游戏了.你可以下载一个玩一下或者点这里看下维基百科的介绍 ...

  3. 使用 C# 开发智能手机软件:推箱子(十二)

    这是"使用 C# 开发智能手机软件:推箱子"系列文章的第十二篇.在这篇文章中,介绍 Window/AboutDlg.cs 源程序文件. 这个源程序文件包括 AboutDlg 类,该 ...

  4. 使用 C# 开发智能手机软件:推箱子(二十三)

    这是"使用 C# 开发智能手机软件:推箱子" 系列文章的第二十三篇.在这篇文章中,介绍 Window/MainForm.Common.cs 源程序文件.这个源程序文件是 MainF ...

  5. 使用 C# 开发智能手机软件:推箱子(二十)

    这是"使用 C# 开发智能手机软件:推箱子" 系列文章的第二十篇.在这篇文章中,介绍 Window/DesignDlg.cs 源程序文件.这个源程序文件包含 DesignDlg 类 ...

  6. c#推箱子小游戏代码_推箱子小游戏V1.0制作

    小游戏实践 推箱子简易版 大家好,我是努力学习争取成为优秀的Game Producer的路人猿,今天来一起做一个推箱子的简易版本V1.0!下面跟我一起做吧~ 我们用到的软件如下: 编辑类 Visual ...

  7. Java 编写推箱子报告_Java推箱子怎么写啊?

    展开全部 这是我之前写的一篇java实现推箱子算法的文章,简单的给你看一下: <推箱子游戏>是一款益智32313133353236313431303231363533e59b9ee7ad9 ...

  8. 用JAVA制作小游戏——推箱子(三)

    本篇博客主要是对推箱子地图编辑器功能的代码讲解. 首先给出这段代码的部分运行截图: 重难点: 地图编辑器主要有三个重难点: 需要有一个绘制地图的界面 能够实现地图绘制的功能 地图绘制完成后需要将地图内 ...

  9. 用JAVA制作小游戏——推箱子(二)

    本篇博客主要是推箱子游戏界面功能的代码讲解. 首先先给出这段代码的部分运行截图: 重难点: 游戏界面主要有五个重难点: 固定好地图的位置 地图的显示 构建菜单栏 读取地图数据 玩家操作功能实现 地图的 ...

  10. 用JAVA制作小游戏——推箱子(一)

    本篇博客是对推箱子游戏首页代码的展示 效果图: 难点: 在背景图上添加按钮. 由于直接使用add方法,会变成图片一块区域,按钮一块区域,彼此互不重叠,形成的界面效果不太好,因此用了JLayeredPa ...

最新文章

  1. uchome后台系统配置分析
  2. 《React Native移动开发实战》一一3.4 完善商品列表——ListView组件
  3. ubuntu20.04中gedit使用markdown插件(没搞定)
  4. uni-app 微信小程序自定义radio样式
  5. linux 环境 RocketMQ 4.8.0 安装、部署控制台
  6. Qt笔记-Qt中Json存二进制文件并读取文件(QJsonObject、QJsonArray、QJsonDocument的使用)
  7. html5-了解元素的属性
  8. python 面向对象oop
  9. win64 Python下安装PIL出错解决2.7版本 (3.6版本可以使用)
  10. js生成execl表格
  11. 利用Python进行数据分析的学习笔记——chap12
  12. 支付宝芝麻认证接口-扫码方式(芝麻认证接口与之类似)
  13. 基于javaweb+jsp的学生档案管理系统
  14. 工控ARM板登陆、wifi连接
  15. 一个高效的敏感词过滤方法(PHP)
  16. halcon 纹理检测_Halcon 纹理缺陷检测 apply_texture_inspection_model
  17. 电子小制作:户外下雨传感装置
  18. 西门子fc功能块应用介绍
  19. 【附源码】计算机毕业设计java在线党建学习平台设计与实现
  20. 《地理信息系统导论》chapter 5 GIS数据获取 习作

热门文章

  1. inno setup 初次使用
  2. kuka机器人码垛编程网盘_KUKA机器人码垛程序怎么写(案例)
  3. 如何让你的技术团队成员自觉工作
  4. Open3d学习计划——11(使用NumPy)
  5. c语言中双引号是什么作用,C语言中单引号与双引号的区别
  6. CUDA学习笔记(三)——共享内存
  7. 强网杯 2018 core ROP做法
  8. Django查询关键字
  9. java 一年有多少周_Java8根据一年中的第几周获得Monday
  10. David G. Lowe课题组 Fully Automatic Multi-target Tracking System