武汉市网站建设_网站建设公司_自助建站_seo优化
2025/12/27 11:46:12 网站建设 项目流程

C++ 推箱子游戏 - 实践

2025-12-27 11:40  tlnshuju  阅读(0)  评论(0)    收藏  举报

C++ 推箱子V1版

  • C++ 推箱子V1版 纯代码
  • 1.游戏截图
  • 2.游戏逻辑:
    • 游戏概述
    • ️ 核心设计思想
      • 1. **状态驱动设计**
      • 2. **数据与表现分离**
    • 核心游戏逻辑
      • 1. **初始化流程**
      • 2. **游戏主循环**
      • 3. **移动处理逻辑**
        • **玩家移动决策树**:
        • **状态转换规则**:
      • 4. **碰撞检测系统**
      • 5. **胜利条件判定**
    • 输入处理设计
      • 方向控制映射:
    • 架构优势
      • 1. **模块化设计**
      • 2. **可扩展性**
      • 3. **错误处理**
    • 性能考虑
      • 1. **高效的状态查找**
      • 2. **最小化重绘**
    • 可能的优化方向
  • 3.代码

C++ 推箱子V1版 纯代码

1.游戏截图

游戏开始
在这里插入图片描述
游戏运行
在这里插入图片描述

游戏胜利
在这里插入图片描述

2.游戏逻辑:

游戏概述

推箱子是一款经典的益智游戏,玩家需要控制角色推动箱子到指定目标位置。本实现采用C++控制台方式,展现了清晰的游戏逻辑架构。

️ 核心设计思想

1. 状态驱动设计

// 使用枚举类精确描述每个格子的状态
enum class Object {
OBJ_WALL,           // 不可移动的障碍物
OBJ_SPACE,          // 可通行的空地  
OBJ_GOAL,           // 目标位置(空)
OBJ_BOX,            // 箱子(未在目标上)
OBJ_MAN,            // 玩家角色
OBJ_BOX_ON_GOAL,    // 箱子在目标上(已完成)
OBJ_MAN_ON_GOAL,    // 玩家在目标上
};

设计理念:每个格子有且仅有一种状态,通过状态组合表达复杂游戏情形。

2. 数据与表现分离

  • 数据层Object 数组存储游戏状态
  • 表现层Draw() 函数负责渲染显示
  • 优势:逻辑处理与界面显示完全解耦

核心游戏逻辑

1. 初始化流程

读取字符串地图 → 解析字符 → 转换为状态枚举 → 构建游戏世界

特点:使用字符串字面量定义关卡,便于修改和扩展。

2. 游戏主循环

while (游戏未通关) {
清屏并绘制当前状态
检查通关条件
获取玩家输入
根据输入更新游戏状态
}

3. 移动处理逻辑

玩家移动决策树
检查目标位置状态:
├── 空地/目标点 → 直接移动
├── 箱子/箱子在目标上 → 检查箱子后方:
│   ├── 空地/目标点 → 推动箱子并移动
│   └── 墙/其他箱子 → 阻止移动
└── 墙 → 阻止移动
状态转换规则
  • 玩家移动

    • MAN + SPACESPACE + MAN
    • MAN + GOALGOAL + MAN_ON_GOAL
    • MAN_ON_GOAL + SPACEGOAL + MAN
    • MAN_ON_GOAL + GOALGOAL + MAN_ON_GOAL
  • 箱子推动

    • MAN + BOX + SPACESPACE + MAN + BOX
    • MAN + BOX + GOALSPACE + MAN + BOX_ON_GOAL
    • MAN + BOX_ON_GOAL + SPACEGOAL + MAN_ON_GOAL + BOX

4. 碰撞检测系统

// 三层边界检查:
1. 玩家移动边界检查
2. 箱子推动边界检查
3. 目标位置状态合法性检查

5. 胜利条件判定

// 简单而有效:检查场景中是否存在未完成的箱子
bool CheckClear() {
for (每个格子) {
if (找到 OBJ_BOX) return false;  // 还有箱子没推到目标
}
return true;  // 所有箱子都在目标上
}

输入处理设计

方向控制映射:

设计考虑:符合玩家直觉的方向控制,便于操作。

架构优势

1. 模块化设计

2. 可扩展性

  • 易于添加新关卡(修改字符串地图)
  • 状态枚举便于添加新游戏元素
  • 清晰的接口便于功能扩展

3. 错误处理

性能考虑

1. 高效的状态查找

// 线性搜索玩家位置 - 对小地图足够高效
for (index = 0; index < width * height; index++) {
if (state[index] == OBJ_MAN || state[index] == OBJ_MAN_ON_GOAL) {
break;
}
}

2. 最小化重绘

  • 只在状态变化时重绘
  • 清屏操作避免画面残留

可能的优化方向

  1. 关卡管理系统:支持多个关卡切换
  2. 撤销功能:记录移动历史
  3. 步数统计:记录玩家表现
  4. 更复杂的游戏元素:如传送门、炸弹等

这个设计体现了状态机思想在游戏开发中的应用,通过有限的状态组合表达丰富的游戏行为,是经典而有效的游戏架构模式。

3.代码

#include <iostream>#include <string>// 推箱子游戏 Caron Daltroff做出修改// 场景宽 高const int gStageWidth = 8;const int gStageHight = 5;// 场景初始化地图const char gStageData[] = "\########\n\# .. p #\n\# oo   #\n\#      #\n\########";// 枚举元素的状态enum class Object{OBJ_WALL,				// 墙OBJ_SPACE,				// 空地OBJ_GOAL,				// 目标OBJ_BOX,				// 箱子OBJ_MAN,				// 玩家OBJ_BOX_ON_GOAL,		// 箱子在目标上OBJ_MAN_ON_GOAL,		// 玩家在目标上OBJ_INVALID				// 无效};void Initialize(Object* state, int width, int height, const char* stageData);void Draw(const Object* state, int width, int height);void Update(Object* state, const char input, int width, int height);bool CheckClear(Object* state, int width, int height);// 工具类函数,清理屏幕void ClearScreen();// 初始化场景void Initialize(Object* state, int width, int height, const char* stageData){const char* data = stageData;int x = 0;int y = 0;while(*data != '\0'){Object temp;switch (*data){case '#': temp = Object::OBJ_WALL; break;case ' ': temp = Object::OBJ_SPACE; break;case '.': temp = Object::OBJ_GOAL; break;case 'o': temp = Object::OBJ_BOX; break;case 'p': temp = Object::OBJ_MAN; break;case 'O': temp = Object::OBJ_BOX_ON_GOAL; break;case 'P': temp = Object::OBJ_MAN_ON_GOAL; break;case '\n':	// 下一行x = 0;y++;temp = Object::OBJ_INVALID;break;default: temp = Object::OBJ_INVALID;}// 初始化下一个字符++data;// 写入数据if (temp != Object::OBJ_INVALID){state[y * width + x] = temp;++x;}}}// 绘制每一个元素void Draw(const Object* state, int width, int height){const char font[] = {'#','.',' ','o','O','p','P'};Object temp = Object::OBJ_INVALID;for(int y = 0; y < height; ++y){for(int x = 0; x < width; ++x){// 取出来,绘制temp = state[y * width + x];switch (temp){case Object::OBJ_WALL: std::cout << "#"; break;case Object::OBJ_SPACE: std::cout << " "; break;case Object::OBJ_GOAL: std::cout << "."; break;case Object::OBJ_BOX: std::cout << "o"; break;case Object::OBJ_MAN: std::cout << "p"; break;case Object::OBJ_BOX_ON_GOAL: std::cout << "O"; break;case Object::OBJ_MAN_ON_GOAL: std::cout << "P"; break;}}std::cout << std::endl;}}// 更新每一次移动void Update(Object* state, char input, int width, int height){// 移动的变化int dx = 0;int dy = 0;// 获取用户输入switch (input){case 'a': dx = -1; break;case 'd': dx = 1; break;case 'w': dy = -1; break;case 's': dy = 1; break;case 'e':exit(0);}// 查询玩家位置int index = -1;for (index = 0; index < width * height; index++){if (state[index] == Object::OBJ_MAN || state[index] == Object::OBJ_MAN_ON_GOAL){break;}}// 计算当前位置坐标int posX = index % width;int posY = index / width;// 移动后的坐标int targetPosX = posX + dx;int targetPosY = posY + dy;// 计算移动后的坐标是否合理, 即边界判断if (targetPosX < 0 || targetPosY < 0 || targetPosX >= width || targetPosY >= height){return;}// 正式移动 玩家移动和箱子移动// 玩家当前的位置int playerPosition = posY * width + posX;int targetPosition = targetPosY * width + targetPosX;// 排列组合//							箱子玩家都可以移动// MAN/MAN_ON_GOAL	BOX/BOX_ON_GOAL			WALL						不能// MAN/MAN_ON_GOAL	BOX/BOX_ON_GOAL			SPACE						能// MAN/MAN_ON_GOAL	BOX/BOX_ON_GOAL			GOAL						能// MAN/MAN_ON_GOAL	BOX/BOX_ON_GOAL			BOX_ON_GOAL					不能// MAN/MAN_ON_GOAL	BOX/BOX_ON_GOAL			BOX							不能//							只有玩家可以移动// MAN/MAN_ON_GOAL	SPACE					WALL/BOX/BOX_ON_GOAL		能// MAN/MAN_ON_GOAL	GOAL					WALL/BOX/BOX_ON_GOAL		能// MAN/MAN_ON_GOAL	BOX						WALL/BOX/BOX_ON_GOAL		不能// MAN/MAN_ON_GOAL	WALL					WALL/BOX/BOX_ON_GOAL		不能// MAN/MAN_ON_GOAL	BOX_ON_GOAL				WALL/BOX/BOX_ON_GOAL		不能// 人移动,但是箱子不移动if (state[targetPosition] == Object::OBJ_SPACE || (state[targetPosition] == Object::OBJ_GOAL)){// 移动到目标位置的时候,玩家状态改变state[targetPosition] = (state[targetPosition] == Object::OBJ_GOAL)? Object::OBJ_MAN_ON_GOAL: Object::OBJ_MAN;// 更改移动前玩家所在的状态state[playerPosition] = (state[playerPosition] == Object::OBJ_MAN_ON_GOAL)? Object::OBJ_GOAL: Object::OBJ_SPACE;} // 玩家和箱子都可以移动else if (state[targetPosition] == Object::OBJ_BOX || state[targetPosition] == Object::OBJ_BOX_ON_GOAL){// 下下个位置范围检查int tx2 = targetPosX + dx;int ty2 = targetPosY + dy;if (tx2 < 0 || ty2 < 0 || tx2 >= width || ty2 >= height){return;}// 检查再下一个位置的状态: Wall 不可移动box,space 可以移动box, goal 可移动box并改变状态int target2Position = (targetPosY + dy) * width + (targetPosX + dx);if (state[target2Position] == Object::OBJ_SPACE || state[target2Position] == Object::OBJ_GOAL){// 移动box到下一个位置state[target2Position] = state[target2Position] == Object::OBJ_GOAL ? Object::OBJ_BOX_ON_GOAL : Object::OBJ_BOX;// 移动玩家state[targetPosition] = state[targetPosition] == Object::OBJ_BOX_ON_GOAL ? Object::OBJ_MAN_ON_GOAL : Object::OBJ_MAN;// 修改玩家上一次的位置state[playerPosition] = state[playerPosition] == Object::OBJ_MAN_ON_GOAL ? Object::OBJ_GOAL : Object::OBJ_SPACE;}}}// 判断是否游戏结束bool CheckClear(Object* state, int width, int height){// 如何判断,没有BOX的就行了for (int index = 0; index < width * height; ++index){if (state[index] == Object::OBJ_BOX){return false;}}return true;}// 清理屏幕void ClearScreen(){#if defined(_WIN32)system("cls");#elsesystem("clear");#endif}int main(){// 初始化场景Object* state = new Object[gStageWidth * gStageHight];Initialize(state, gStageWidth, gStageHight, gStageData);char input;while(true){// 绘制Draw(state, gStageWidth, gStageHight);// 游戏结束判断if (CheckClear(state, gStageWidth, gStageHight)){// 游戏结束break;}// 没有通关,继续接收玩家移动操作std::cout << "press the key 'w' 'a' 's' 'd' to control the pawn to move." << std::endl;std::cin >> input;// 更新移动后的结果Update(state, input, gStageWidth, gStageHight);ClearScreen();}// 通关std::cout << "Congratulation! You Won." << std::endl;std::cout << "press E to exit game" << std::endl;std::cin >> input;if (input == 'e'){delete[] state;state = nullptr;exit(0);}return 0;}

《游戏开发 世嘉新人培训教材》

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询