自创C++简易迷宫游戏(萌新)游戏代码


前言

这是一位萌新对自己编程能力的一种实践,也是他热情与奋斗的体现。

它的玩法基本完善,是一个迷宫游戏,包含二维和三维迷宫的功能,具有地图生成、保存/加载、颜色设置、动态障碍物等特性。(个人认为还有改进空间,如DIY功能还未实现,以及切换操作键位等)
作者邮箱真会回复!


正文

  1. 作者的话

从最初的1.0.0,到如今的1.1.4,经历了大概半个月的时间(有些代码还是AI帮我解决问题的)

目前代码属于C++11支持,可以在DEVC++5.11和visual studio上运行。

接下来还会不断更新。。。。。。一些小版本就不再展示了,等到功能焕然一新,会发第二版的游戏。一些小的建议或反馈可以发送给作者,我都会采纳的。希望大家多多支持!
游戏主页面

  1. 游戏玩法介绍

以下是《小时迷宫》的完整使用说明,涵盖核心玩法、功能操作和实用技巧:


一、游戏基础信息

  • 目标:操控角色(o)从起点抵达终点($),避开动态/静态障碍。
    2D游戏页面

  • 适用平台:Windows(支持控制台运行)

  • 存档路径D:\Labyrinth_Shi\(自动创建文件夹)


二、核心玩法详解

1. 基础操作
模式按键功能
2DW/A/S/D上/左/下/右移动
3DW/A/S/D平面移动
3DU/N垂直上升/下降
3DX/Y/Z切换视图(XY / YZ / Z*X)
通用空格键暂停游戏(弹出菜单)
2. 障碍类型
符号名称特性应对策略
x静态墙永久阻挡,触碰即死绝对避开
^动态刺周期性凸起(危险)观察节奏,缩回时通过
_休眠刺周期性缩回(安全)快速穿越
3. 胜利条件
  • 2D模式:到达地图右下角(坐标H,W
  • 3D模式:到达三维顶点(坐标H3D,W3D,L3D
    游戏胜利界面

三、功能设置指南

1. 游戏设置(主菜单 → 设置)
选项功能说明推荐配置
颜色自定义调整角色/墙/刺/终点的显示颜色高对比度配色(如红墙黄终点)
地图尺寸2D支持10x10~37x133,3D支持35x35x35新手建议10x10小地图
重置默认恢复初始颜色和地图大小卡关时使用
2. 存档管理
功能操作路径说明
保存暂停菜单 → 按1存档至D:\Labyrinth_Shi\自定义命名
加载主菜单 → d选择.2DMap.3DMap文件
重玩死亡/胜利后按y重置当前地图(保留配置)
3. 暂停菜单

在进行游戏时按下空格即可暂停游戏

按键功能使用场景
0直接退出游戏紧急退出
1保存进度并退出临时中断时保留成果
其他返回游戏观察环境后继续

四、进阶技巧

  1. 动态刺规律

    • 周期 = 地图数据中的cycle值(如cycle=5表示5秒一切换)
    • 通过多次死亡记忆关键位置刺的节奏。
  2. 3D视图联动

    • 在XY视图中上升(U)后,立即切换YZ视图确认高度位置。
  3. 开发者模式

    • 修改MAP[x][y].canto值可编辑地图(需编程基础)。

五、常见问题解答

  • Q:游戏卡顿怎么办?
    A:关闭其他程序,或调小地图尺寸(设置 → 地图大小)。

  • Q:存档文件误删如何恢复?
    A:检查回收站,或重新生成同名地图(随机地图无法复原)。

  • Q:3D模式迷路怎么破?
    A:频繁切换视图,注意控制台底部坐标提示。
    3D游戏界面


六、联系开发者

  • 反馈渠道:发送邮件至syc20120920@163.com
  • 建议格式
    问题描述:[具体操作+现象]  
    期望效果:[如果是建议]  
    设备信息:[如Windows 10/11]  
    

掌握这些技巧,您已经超越90%的新手玩家!现在就去挑战35层超大地图吧! 🚩

  1. 游戏主程序

游戏代码:

/*
 * 抵制不良游戏,拒绝盗版游戏。
 * 注意自我保护,谨防受骗上当。
 * 适度游戏益脑,沉迷游戏伤身。
 * 合理安排时间,享受健康生活。
 */
 // 跨平台头文件兼容声明
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define NOMINMAX
#endif
#ifdef _WIN32
#include <windows.h>    // 控制台颜色与输入API
#include <conio.h>      // 非阻塞式键盘输入
#endif
#include<string>
#include<fstream>
#include<cstring>
#include<iostream>
#include<vector>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<stdexcept>
#include<exception> 

using namespace std;

// ---------- 全局配置 ----------
const string path = "D:\\Labyrinth_Shi"; // 地图保存文件夹固定路径 
const string m2d = ".2DMap"; // 二维地图 
const string m3d = ".3DMap"; // 三维地图 
#define Wrong "错误!请重试\n" // 错误提示语1
#define version "1.1.4" // 版本号(为后续开发做准备)
#define Backwrong "错误!返回中\n" // 错误提示语2
#define SWlen 8 // 加载界面词条数量 
const string SW[SWlen] = { // 加载界面随机提示语
    "欢迎游玩小时迷宫",
    "3D地图......你不晕就好!",
    "小贴士:有些刺会摆烂",
    "WSAD控制上下左右",
    "可以向作者的163邮箱发送消息提供意见(syc20120920@163.com)",
    "O(∩_∩)O哈哈~",
    "准备好你的迷宫之旅了吗",
    "按空格暂停游戏"
};

// ---------- 数据结构定义 ----------
struct Die { // 障碍物属性结构体
    int how; // 伤害类型(0:静态障碍 / 1:动态伤害)
    string way; // 障碍物名称描述
}
CD[101]; // 预设101种障碍类型(索引0未使用)

int X = 1, Y = 1; // 玩家坐标(初始位置1,1)
int X3D = 1, Y3D = 1, Z3D = 1; // 三维玩家坐标 
int H = 29, W = 100; // 地图大小 
int H3D = 35, W3D = 35, L3D = 35; // 三维地图大小 

int Cwall = 4, Cplayer = 10, Cstab = 1, Cwin = 14; // 墙,玩家,刺,终点等的颜色(供自定义用) 

struct _CTRLO {
    bool flag;
    string File_uffix;
};

struct _MAP { // 地图单元格属性
    int canto; // 当前状态(0:可通行 / 1:障碍物)
    int cycle; // 动态障碍物变化周期(0:静态)
}
MAP[38][134], // (二维)主地图(最大37行x133列,索引从1开始)
MAP3D[36][36][36], // 三维地图 (最大35x35x35,索引从1开始) 
ctrlcv[101][101], // 地图剪贴板(用于游戏重玩)
ctrlcv3D[36][36][36]; // 三维地图剪贴板 

// ---------- 函数声明 ----------
int GETCH(void);// GETCH; 
void update3D(); // 三维动态更新 
void paint3D(); // 三维地图渲染引擎 
void CTRLC3D(); // 三维地图复制(类似Ctrl+C)
void CTRLV3D(); // 三维地图粘贴(类似Ctrl+V)
void GAME3D(); // 三维地图主逻辑 
void randrestart3D(); // 三维随机地图生成器
_CTRLO CTRLO(); // 打开保存游戏 (包括二维和三维) 
void CTRLS(const string& File_uffix); // 游戏保存本地 (包括二维和三维) 
void GameStop(string File_uffix); // 游戏暂停 
void MAIN(); // 游戏主循环 
void ChangeMapsize(); // 切换地图大小 
void toggleIME(); // 切换输入法
void printtitle(string title); // 打印自定义标题
void paint(); // 地图渲染引擎
void winnerprint(); // 胜利动画
void randrestart(); // 随机地图生成器
void Color(int ForgC, int BackC); // 控制台颜色设置
void KO(Die way); // 死亡处理及动画
void GAME1(); // 游戏主逻辑
int GetTerminalColumns();// 获取屏幕宽度 
void CTRLC(); // 地图复制(类似Ctrl+C)
void CTRLV(); // 地图粘贴(类似Ctrl+V)
void WAIT(const string* SW, int len); // 加载界面动画
int Suiji(int many); // 封装随机数生成
void Changelog(); // 更新日志 
void Settings(); // 设置 
void Notice(); // 公告 
void Howplay(int Hchose); // 玩法详解
void update(); // 动态更新 
void Colorsettings(); // 颜色自定义 
void CSC(string which, int& what); // 颜色自定义附属函数 

// ---------- 主程序 ----------
int main() {
    toggleIME(); // 将输入法改为英文 

    // 初始化基础障碍类型
    CD[1] = { 0, "墙" }; // 索引1:静态墙壁
    CD[2] = { 0, "刺" }; // 索引2:动态尖刺

    srand((unsigned)time(NULL)); // 随机数种子

    // 创建用来存迷宫的文件夹 
    bool flag = CreateDirectoryA(path.c_str(), NULL);
    // 主界面循环
    MAIN();
    return 0;
}

// ---------- 功能实现 ----------

// getch;
int  GETCH(void) {
#ifdef _MSC_VER
    return _getch();
#elif defined(__MINGW32__) || defined(__MINGW64__)
    return getch();
#endif
}

// 获取终端列数(Windows 实现)
int GetTerminalColumns() {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    return csbi.srWindow.Right - csbi.srWindow.Left + 1;
}

// 打印自适应标题
void printtitle(string title) {
    system("cls");
    int cols = GetTerminalColumns();

    // 生成自适应分隔线(全屏横线)
    cout << setfill('-')              // 设置填充字符为 -
        << setw(cols) << ""          // 输出宽度为终屏列数的空字符串(自动填充-)
        << "\n\n";                   // 换两行

    // 计算标题居中位置(带冒号)
    title += ":";                     // 添加标题后的冒号
    int title_len = title.length();
    int left_pad = max(0, (cols - title_len) / 2); // 防止负数

    // 输出居中标题
    cout << setfill(' ')              // 重置填充为空格
        << setw(left_pad) << ""      // 左侧填充空格
        << title                    // 输出标题(已包含冒号)
        << "\n\n";                  // 换两行

    // 再次输出分隔线
    cout << setfill('-')
        << setw(cols) << ""
        << "\n\n";
}

// 控制台颜色设置(Windows API封装)
/*
值	属性
0	黑
1	蓝
2	绿
3	海蓝
4	红
5	紫红
6	黄/棕色
7	白/灰色
8	暗灰
9	亮蓝
A (十进制10)	亮绿
B (十进制11)	亮海蓝
C (十进制12)	亮红
D (十进制13)	亮紫红
E (十进制14)	亮黄/黄色
F (十进制15)	亮白
*/
void Color(int ForgC, int BackC) {
    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
}

// 封装随机数生成(范围1-many)
int Suiji(int many) {
    return rand() % many + 1;
}
// 加载动画(模拟进度条+随机提示)
void WAIT(const string* SW, int len) {
    system("cls"); //为了防止在其他函数中忘记清屏 
    int ans = 0;
    Color(3, 0); // 设置青蓝色文本
    int xx = rand() % len;
    string s = SW[xx];

    while (ans < 100) { // 进度模拟
        printf("加载中......\n\n%d%%\n\n", ans);
        int x = rand() % len;
        if (x <= len / 10) s = SW[rand() % len]; // 随机更换提示
        printf("%s", s.c_str());
        Sleep(Suiji(10) * 100); // 随机延迟(100-1000ms)
        ans += Suiji(20); // 随机进度增量(1-20)
        system("cls");
    }
}
// 游戏玩法(Hchose表示引用方式,0表示设置引用,1表示游戏引用 
void Howplay(int Hchose) {
    string ss;
    if (Hchose == 0)ss = "返回主界面";
    else if (Hchose == 1)ss = "确认";
    Color(14, 0);
    printtitle("游戏玩法");
    printf("以下是《小时迷宫》的详细玩法指南,帮助您更好地理解游戏机制:\n\
 **基础操作**\n\
- **移动控制**  \n\
  - **2D模式**:`W`上 `S`下 `A`左 `D`右  \n\
  - **3D模式**:  \n\
    - 平面移动:`W`上 `S`下 `A`左 `D`右  \n\
    - 垂直移动:`U`上升一层 `N`下降一层  \n\
    - **视图切换**:  \n\
      - `X`键:显示X*Y平面(俯视图)  \n\
      - `Y`键:显示Y*Z平面(侧视图)  \n\
      - `Z`键:显示Z*X平面(前视图)  \n\
  - **通用功能**:`空格键`暂停游戏(可保存进度或退出)\n\
\n\
---\n\
\n\
**游戏目标**\n\
- **核心任务**:操控角色(`o`)从起点(地图左上角)移动到终点(`$`),避开所有障碍物。\n\
- **胜利条件**:到达终点即触发胜利动画。\n\
\n\
---\n\
\n\
**地图元素解析**\n\
| 符号 | 颜色          | 说明                                                                 |\n\
|------|---------------|----------------------------------------------------------------------|\n\
| `o`  | 玩家自定义色  | 你的角色,初始位置在(1,1)(2D)或(1,1,1)(3D)。                     |\n\
| `$`  | 亮黄色        | 终点,位于地图右下角(2D)或最大坐标点(3D)。                       |\n\
| `x`  | 红色          | **静态墙**:触碰直接死亡。                                           |\n\
| `^`  | 蓝色          | **动态刺(凸起)**:周期性出现,触碰时若为凸起状态则死亡。           |\n\
| `_`  | 蓝色          | **动态刺(缩回)**:安全时段可通过。                                 |\n\
\n\
---\n\
\n\
**动态障碍机制**\n\
\n\
- **周期性变化**:动态刺(`^`和`_`)会按固定周期切换状态(如每3秒凸起→缩回)。  \n\
\n\
- **策略提示**:  \n\
  1. 观察刺的变化节奏,等待缩回时快速通过。  \n\
  2. 3D模式中,可通过切换视图观察不同平面的刺状态。\n\
\n\
---\n\
\n\
**2D与3D模式差异**\n\
| 特性          | 2D模式                     | 3D模式                             |\n\
|---------------|---------------------------|-------------------------------------|\n\
| **移动维度**  | 仅平面(X,Y)             | 三维空间(X,Y,Z)                   |\n\
| **视图**      | 单一平面                  | 支持X*Y、Y*Z、Z*X三种视图切换       |\n\
| **难度要点**  | 路径规划+动态刺躲避       | 空间导航+多平面障碍协同躲避         |\n\
\n\
---\n\
\n\
**新手技巧**\n\
1. **先熟悉2D模式**:掌握基础移动和刺的节奏后再挑战3D。\n\
2. **善用暂停**:按空格观察周围环境,规划路线。\n\
3. **颜色记忆**:牢记红色(墙)必死,蓝色(刺)需等待时机。\n\
4. **3D导航**:  \n\
   - 切换视图时,注意坐标提示(如`坐标:(3,5,2)`)。\n\
   - 上升/下降(`U/N`)后,立刻切换视图确认位置。  \n\
\n\
---\n\
\n\
**常见问题解答**\n\
- **Q:为什么有时刺明明是缩回的,走过去还是死了?**\n\
  A:是因为刺是会一直变化的,当你走到刺上时他可能刚好变成突出状态。\n\
- **Q:3D模式找不到终点怎么办?**  \n\
  A:终点在最大坐标(如35,35,35),通过视图切换锁定大致方向。  \n\
\n\
---\n\
\n\
**开发者建议**\n\
- 如果卡关,可在设置中调整地图尺寸(如选择10x10小地图练习)。\n\
- 自定义颜色(设置→颜色自定义)可增强视觉区分度。  \n\
\n\
---\n\
\n\
希望这份指南能让您的迷宫之旅更顺利!如果仍有疑问,欢迎通过游戏内邮箱反馈。祝您早日通关! (按任意键%s)", ss.c_str());
    char Hch;
    Hch = GETCH();
    system("cls");
    return;
}
// 胜利界面及动画
void winnerprint() {
    Color(14, 0); // 黄色 
    printf("无敌了!!!\n");
    printf("                    ^^^^^^^^^^\n\
                    /        \\\n\
                   (  _   _   )\n\
                    \\   ^   /\n\
                      -----\n\
                        |        /\n\
                      / |--------\n\
                    /   |\n\
                    \\   |\n\
                     \\  |\n\
                      \\ |\n\
                        |\n\
                      /   \\\n\
                     /     \\\n\
                    /       \\\n\
                   /         \\");
}
// 切换输入法
void toggleIME() {
    // 模拟按下Shift键切换中英文(适用于微软拼音)
    keybd_event(VK_SHIFT, 0, 0, 0); // 按下Shift
    keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); // 释放Shift
}

// 公告
void Notice() {
    system("cls");
    printtitle("公告");
    printf("欢迎您玩小时迷宫!作者能力有限,游戏可能会有bug。\
	如果您发现了bug,可以将反馈意见发送至作者163邮箱(syc20120920@163.com)\
	作者在了解信息后会尽快修复,并将新版本发布。谢谢\n\n下一阶段(1.2.0)\
	将完成完整的地图自定义功能,敬请期待\n\n(按任意键返回主页面)");
    char Nch;
    Nch = GETCH();
    system("cls");
    return;
}
// 死亡处理及ASCII艺术
void KO(Die way) {
    system("cls");
    if (way.how == 0) { // 静态障碍死亡
        Color(6, 0); // 橙色
        printf("你一头创死在%s上\n", (way.way).c_str());
        // ASCII艺术图形
        printf("       _____________\n\
        (  x   x   )\n\
         \\   -   /\n\
           -----\n\
             |        /      菜就多练\n\
           / |--------\n\
         /   |\n\
         \\   |\n\
          \\  |\n\
           \\ |\n\
             |\n\
           /   \\\n\
          /     \\\n\
         /       \\\n\
        /         \\");
    }
}
// 加载本地地图文件
_CTRLO CTRLO() {
    _CTRLO _ctrlo;
    _ctrlo.File_uffix = "Nothing";
    _ctrlo.flag = false;
    vector < string > savedFiles; // 存储可加载的文件列表
    WIN32_FIND_DATAA fileData;
    HANDLE hFind = FindFirstFileA((path + "\\*").c_str(), &fileData);

    // 获取存档目录下的所有文件
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
                savedFiles.push_back(fileData.cFileName);
            }
        } while (FindNextFileA(hFind, &fileData));
        FindClose(hFind);
    }

    // 显示加载界面
    system("cls");
    printtitle("加载地图");
    if (savedFiles.empty()) {
        printf("没有找到存档文件!\n");
        Sleep(2000);
        return _ctrlo;
    }

    // 显示文件列表
    printf("可加载的地图文件:\n");
    for (size_t i = 0; i < savedFiles.size(); ++i) {
        printf("%2zu. %s\n", i + 1, savedFiles[i].c_str());
    }

    // 用户选择文件
    printf("\n输入要加载的文件编号 (0取消): ");
    size_t choice;
    if (!(cin >> choice) || choice < 0 || choice > savedFiles.size()) {
        cin.clear();
        cin.ignore(numeric_limits < streamsize > ::max(), '\n');
        printf("%s", Wrong);
        Sleep(1000);
        return _ctrlo;
    }
    else if (choice == 0) return _ctrlo;

    // 构建完整路径
    string filename = path + "\\" + savedFiles[choice - 1];
    ifstream inFile(filename);
    if (!inFile.is_open()) {
        printf("无法打开文件: %s\n", filename.c_str());
        Sleep(2000);
        return _ctrlo;
    }

    try {
        // 读取文件头
        string fileType;
        inFile >> fileType;
        _ctrlo.File_uffix = fileType;
        if (fileType == m2d) {
            int savedH, savedW;
            inFile >> savedH >> savedW;

            // 验证地图尺寸
            if (savedH < 2 || savedH > 37 || savedW < 2 || savedW > 133) {
                throw runtime_error("地图尺寸非法");
            }

            // 读取颜色配置
            int savedCwall, savedCplayer, savedCstab, savedCwin;
            inFile >> savedCwall >> savedCplayer >> savedCstab >> savedCwin;

            // 临时存储地图数据
            vector < vector < _MAP >> tmpMap(savedH + 1, vector < _MAP >(savedW + 1));

            // 读取地图内容
            for (int h = 1; h <= savedH; ++h) {
                for (int w = 1; w <= savedW; ++w) {
                    if (!(inFile >> tmpMap[h][w].canto >> tmpMap[h][w].cycle)) {
                        throw runtime_error("地图数据损坏");
                    }
                    // 验证数据有效性
                    if (tmpMap[h][w].canto < 0 || tmpMap[h][w].cycle < 0 || tmpMap[h][w].cycle > 100) {
                        throw runtime_error("地图数据非法");
                    }
                }
            }

            // 应用加载的配置
            H = savedH;
            W = savedW;
            Cwall = savedCwall;
            Cplayer = savedCplayer;
            Cstab = savedCstab;
            Cwin = savedCwin;
            // 复制到全局地图
            for (int h = 1; h <= H; ++h) {
                for (int w = 1; w <= W; ++w) {
                    MAP[h][w] = tmpMap[h][w];
                }
            }
        }
        else if (fileType == m3d) {
            int savedH, savedW, savedL;
            inFile >> savedH >> savedW >> savedL;

            // 验证地图尺寸
            if (savedH < 2 || savedH > 35 || savedW < 2 || savedW > 35 || savedL < 2 || savedL > 35) {
                throw runtime_error("地图尺寸非法");
            }

            // 读取颜色配置
            int savedCwall, savedCplayer, savedCstab, savedCwin;
            inFile >> savedCwall >> savedCplayer >> savedCstab >> savedCwin;

            // 临时存储地图数据
            vector < vector < vector < _MAP > > > tmpMap(savedH + 1, vector < vector < _MAP > >(savedW + 1, vector < _MAP >(savedL + 1)));

            // 读取地图内容
            for (int h = 1; h <= savedH; ++h) {
                for (int w = 1; w <= savedW; ++w) {
                    for (int l = 1; l <= savedL; ++l) {
                        if (!(inFile >> tmpMap[h][w][l].canto >> tmpMap[h][w][l].cycle)) {
                            throw runtime_error("地图数据损坏");
                        }
                        // 验证数据有效性
                        if (tmpMap[h][w][l].canto < 0 || tmpMap[h][w][l].cycle < 0 || tmpMap[h][w][l].cycle > 100) {
                            throw runtime_error("地图数据非法");
                        }
                    }
                }
            }

            // 应用加载的配置
            H3D = savedH;
            W3D = savedW;
            L3D = savedL;
            Cwall = savedCwall;
            Cplayer = savedCplayer;
            Cstab = savedCstab;
            Cwin = savedCwin;
            // 复制到全局地图
            for (int h = 1; h <= H3D; ++h) {
                for (int w = 1; w <= W3D; ++w) {
                    for (int l = 1; l <= L3D; ++l) {
                        MAP3D[h][w][l] = tmpMap[h][w][l];
                    }
                }
            }
        }
        else throw runtime_error("文件格式不支持");

        system("cls");
        printf("地图加载成功!\n");
        Sleep(1000);
    }
    catch (const exception& e) {
        // 异常处理
        inFile.close();
        system("cls");
        printf("加载失败: %s\n", e.what());
        printf("按任意键返回...");
        _getch();
        return _ctrlo;
    }
    catch (...) {
        cerr << "发生未知错误" << endl;
        exit(1);
    }
    _ctrlo.flag = true;
    return _ctrlo;
}
// 游戏主循环 
void MAIN() {
    while (1) {
        Color(11, 0); // 设置初始文本颜色(亮青色)
        string SSTART;
        printtitle("首页");
        printf("欢迎来到小时迷宫(%s)版本!选择游戏方式:\n\n a:2D随机迷宫;    b:陨石模式;    c:设置;    d:打开已保存地图;    e:3D随机迷宫    0:退出\n\n", version);
        SSTART = GETCH();
        system("cls");
        if (SSTART == "a") { // 随机迷宫模式
            randrestart(); // 生成新地图
            CTRLC(); // 备份初始地图状态
            Howplay(1);
            //WAIT(SW, SWlen); // 加载动画
        g: // 游戏循环重入点
            GAME1(); // 启动游戏
            // 重玩选择
            printf("是否重玩?\n\ny:yes    n:no\n\n");
            SSTART = GETCH();
            if (SSTART == "y") {
                system("cls");
                CTRLV(); // 恢复初始地图
                goto g; // 重新进入游戏
            }
        }
        else if (SSTART == "b") { // 预留模式
            printf("本内容将在(1.5.0)版本开启");
            Sleep(1000);
        }
        else if (SSTART == "c") {
            //WAIT(SW,SWlen);
            Settings();
        }
        else if (SSTART == "d") {
            _CTRLO ctrlo_check = CTRLO();
            if (ctrlo_check.flag) {
                if (ctrlo_check.File_uffix == m2d) {
                    X = Y = 1;
                    CTRLC();
                    Howplay(1);
                go: GAME1();
                    // 重玩选择
                    printf("是否重玩?\n\ny:yes    n:no\n\n");
                    SSTART = GETCH();
                    if (SSTART == "y") {
                        system("cls");
                        CTRLV(); // 恢复初始地图
                        goto go; // 重新进入游戏
                    }
                }
                else if (ctrlo_check.File_uffix == m3d) {
                    X3D = Y3D = Z3D = 1;
                    CTRLC3D();
                    Howplay(1);
                    //WAIT(SW, SWlen);
                go3D: GAME3D();
                    // 重玩选择
                    printf("是否重玩?\n\ny:yes    n:no\n\n");
                    SSTART = GETCH();
                    if (SSTART == "y") {
                        system("cls");
                        CTRLV3D(); // 恢复初始地图
                        goto go3D; // 重新进入游戏
                    }
                }
                else {
                    printf("不支持的文件格式\n");
                    Sleep(1000);
                    system("cls");
                }
            }
        }
        else if (SSTART == "e") {
            randrestart3D(); // 生成新地图
            CTRLC3D(); // 备份初始地图状态
            Howplay(1);
            //WAIT(SW, SWlen); // 加载动画
        g3D: // 游戏循环重入点
            GAME3D(); // 启动游戏
            // 重玩选择
            printf("是否重玩?\n\ny:yes    n:no\n\n");
            SSTART = GETCH();
            if (SSTART == "y") {
                system("cls");
                CTRLV3D(); // 恢复初始地图
                goto g3D; // 重新进入游戏
            }
        }
        else if (SSTART == "0") exit(0);
        else { // 错误处理
            printf("%s", Wrong);
            Sleep(1000);
        }
    }
    return;
}

// 好难!保存地图到本地
void CTRLS(const string& File_uffix) {
    string mapname;
    string pathway;

    printtitle("保存地图到本地");
    printf("输入保存文件名 (不能包含 \\/:*?\"<>|):\n\n");
    getline(cin, mapname);

    // 文件名合法性检查
    const string illegalChars = "\\/:*?\"<>|";
    for (auto& c : mapname) {
        if (illegalChars.find(c) != string::npos) {
            printf("错误!文件名包含非法字符\n");
            Sleep(1000);
            system("cls");
            return;
        }
    }

    if (mapname.empty()) {
        printf("错误!文件名不能为空\n");
        Sleep(1000);
        system("cls");
        return;
    }

    if (mapname.size() > 50) {
        printf("错误!文件名过长(最大50字符)\n");
        Sleep(1000);
        system("cls");
        return;
    }

    pathway = path + "\\" + mapname + File_uffix;

    try {
        // 使用C++文件流代替freopen
        ofstream outFile(pathway, ios::trunc);
        if (!outFile.is_open()) {
            throw runtime_error("无法打开文件");
        }

        // 写入文件头
        outFile << File_uffix << "\n";
        if (File_uffix == m2d) outFile << H << " " << W << "\n";
        else if (File_uffix == m3d) outFile << H3D << " " << W3D << " " << L3D << "\n";
        else throw runtime_error("文件格式错误");
        outFile << Cwall << " " << Cplayer << " " << Cstab << " " << Cwin << "\n";

        // 写入地图数据
        if (File_uffix == m2d) {
            for (int h = 1; h <= H; ++h) {
                for (int w = 1; w <= W; ++w) {
                    outFile << MAP[h][w].canto << " " << MAP[h][w].cycle;
                    if (w != W) outFile << " "; // 行末不加空格
                }
                outFile << "\n"; // 使用换行符保持跨平台兼容性
            }
        }
        else if (File_uffix == m3d) {
            for (int h = 1; h <= H3D; ++h) {
                for (int w = 1; w <= W3D; ++w) {
                    for (int l = 1; l <= L3D; ++l) {
                        outFile << MAP3D[h][w][l].canto << " " << MAP3D[h][w][l].cycle;
                        if (l != L3D) outFile << " ";
                    }
                    outFile << "\n";
                }
                outFile << "\n";
            }
        }

        // 显式关闭文件流
        outFile.close();

        // 验证文件完整性
        ifstream inFile(pathway);
        string suffix_check;
        if (!(inFile >> suffix_check) || suffix_check != File_uffix) {
            throw runtime_error("文件头验证失败");
        }

        // ...(其他验证逻辑,根据需要添加)

        // 恢复控制台输出
        system("cls");
        printf("地图已成功保存至:\n%s\n", pathway.c_str());
        Sleep(2000);

    }
    catch (const exception& e) {
        // 确保恢复控制台输出
        freopen("CON", "w", stdout);
        freopen("CON", "r", stdin);
        cerr << "保存失败: " << e.what() << endl;
        printf("按任意键返回...");
        GETCH();
        system("cls");
    }
    catch (...) {
        cerr << "发生未知错误" << endl;
        exit(1);
    }
}

// 切换地图大小 
void ChangeMapsize() {
    while (1) {
        system("cls");
        printf("选择地图尺寸\n\n1:(原版大地图)29:100\n\n2:(小小地图)10:10\n\n3:(小地图)20:20\n\n4:自定义\n\n【新!】5:(超大地图)37:133\n\n0:退出\n\n");
        char CMSch;
        CMSch = GETCH();
        system("cls");
        if (CMSch == '1') {
            H = 29;
            W = 100;
            printf("地图修改成功!");
            Sleep(1000);
            break;
        }
        else if (CMSch == '2') {
            H = 10;
            W = 10;
            printf("地图修改成功!");
            Sleep(1000);
            break;
        }
        else if (CMSch == '3') {
            H = 20;
            W = 20;
            printf("地图修改成功!");
            Sleep(1000);
            break;
        }
        else if (CMSch == '4') {
            printf("输入地图的宽度(2~37)和长度(2~133)\n\n");
            int CMShch, CMSwch;
            int checkCMSch = scanf("%d%d", &CMShch, &CMSwch);
            if (!((CMShch < 2 || CMShch > 37) || (CMSwch < 2 || CMSwch > 133)) && checkCMSch == 2) { // 判断是否在范围内 
                H = CMShch;
                W = CMSwch;
                printf("地图修改成功!");
                Sleep(1000);
                break;
            }
            else {
                printf("%s", Backwrong);
                Sleep(1000);
                break;
            }
        }
        else if (CMSch == '5') {
            H = 37;
            W = 133;
            printf("地图修改成功!");
            Sleep(1000);
            break;
        }
        else if (CMSch == '0') break;
        else {
            printf("%s", Wrong);
            Sleep(1000);
            system("cls");
        }
    }
    return;
}

// 设置界面
void Settings() {
    while (1) {
        Color(10, 0);
        printtitle("设置");
        printf("输入选项:\n\n1:更新日志;\n2:公告;\n3:玩法详解;\n4:颜色自定义\n5:地图大小设置\n0:退出");
        string SIS;
        SIS = GETCH();
        system("cls");
        if (SIS == "1") Changelog();
        else if (SIS == "2") Notice();
        else if (SIS == "3") Howplay(0);
        else if (SIS == "4") Colorsettings();
        else if (SIS == "5") ChangeMapsize();
        else if (SIS == "0") break;
        else {
            printf("%s", Wrong);
            Sleep(1000);
            system("cls");
        }
    }
}

// 颜色自定义附属函数 
void CSC(string which, int& what) {
    printf("输入%s颜色(1~15)\n", which.c_str());
    int CSCch;
    int checkCSCch = scanf("%d", &CSCch);
    system("cls");
    if (CSCch > 0 && CSCch < 16 && checkCSCch == 1) what = CSCch; // 判断是否在范围内 
    else {
        printf("错误!");
        Sleep(1000);
        system("cls");
    }
}

// 颜色自定义 
void Colorsettings() {
    while (1) {
        system("cls");
        printf("输入选项:\n1:自定义颜色;\n2:恢复默认;\n0:退出\n");
        char Cch;
        Cch = GETCH();
        system("cls");
        if (Cch == '1') {
            CSC("玩家", Cplayer);
            CSC("墙的", Cwall);
            CSC("终点", Cwin);
            CSC("刺的", Cstab);
            break;
        }
        else if (Cch == '2') {
            Cwall = 4;
            Cplayer = 10;
            Cwin = 14;
            Cstab = 1;
            break;
        }
        else if (Cch == '0') break;
        else {
            printf("%s", Wrong);
            Sleep(1000);
            system("cls");
        }
    }
}

// 游戏暂停 
void GameStop(string File_uffix) {
    system("cls");
    Color(13, 0);
    printtitle("游戏暂停");
    printf("按0直接退出游戏,按1保存游戏状态到本地并退出,按其他键返回\n");
    char GSch;
    GSch = GETCH();
    if (GSch == '0') exit(0);
    else if (GSch == '1') CTRLS((File_uffix == m2d) ? m2d : m3d);
    cerr << 0;
    system("cls");
}

// 更新日志(内容取决于版本号)
void Changelog() {
    system("cls");
    printf("%s版本更新内容:\n\n", version);
    printf("1.修复已知问题,提升系统稳定性\n\n2:提升代码兼容性\n\n3:更新游戏玩法\n\n(按任意键返回主页面)\n");
    char Vch;
    Vch = GETCH(); // 按任意键返回主页面
    system("cls");
    return;
}

// 地图状态复制(保存到剪贴板)
void CTRLC() {
    for (int i = 1; i <= H; i++)
        for (int j = 1; j <= W; j++)
            ctrlcv[i][j] = MAP[i][j];
}

// 3D地图状态粘贴(从剪贴板恢复)
void CTRLV3D() {
    for (int i = 1; i <= 35; i++)
        for (int j = 1; j <= 35; j++)
            for (int k = 1; k <= 35; k++)
                MAP3D[i][j][k] = ctrlcv3D[i][j][k];
}

// 3D地图状态复制(保存到剪贴板)
void CTRLC3D() {
    for (int i = 1; i <= 35; i++)
        for (int j = 1; j <= 35; j++)
            for (int k = 1; k <= 35; k++)
                ctrlcv3D[i][j][k] = MAP3D[i][j][k];
}

// 地图状态粘贴(从剪贴板恢复)
void CTRLV() {
    for (int i = 1; i <= H; i++)
        for (int j = 1; j <= W; j++)
            MAP[i][j] = ctrlcv[i][j];
}

// 地图渲染核心
void paint() {
    for (int i = 1; i <= H; i++) {
        for (int j = 1; j <= W; j++) {
            // 终点标识
            if (i == H && j == W) {
                Color(Cwin, 0);
                printf("$");
            }
            // 玩家标识
            else if (i == X && j == Y) {
                Color(Cplayer, 0);
                printf("o");
            }
            // 可通行区域
            else if (MAP[i][j].canto == 0) {
                if (MAP[i][j].cycle == 0) printf(" "); // 普通道路
                else { // 动态障碍 
                    Color(Cstab, 0);
                    printf("_");
                }
            }
            // 障碍物区域
            else {
                if (MAP[i][j].cycle == 0) { // 静态障碍
                    Color(Cwall, 0);
                    printf("x");
                }
                else { // 动态障碍
                    Color(Cstab, 0);
                    printf("^");
                }
            }
        }
        if (i != H) cout << endl;
    }
}

// 地3D图渲染核心
void paint3D(char view) {
    Color(11, 0);
    if (view == 'x') {

        for (int i = 1; i <= H3D; i++) {
            for (int j = 1; j <= W3D; j++) {
                // 终点标识
                if (i == H3D && j == W3D && Z3D == L3D) {
                    Color(Cwin, 0);
                    printf("$");
                }
                // 玩家标识
                else if (i == X3D && j == Y3D) {
                    Color(Cplayer, 0);
                    printf("o");
                }
                // 可通行区域
                else if (MAP3D[i][j][Z3D].canto == 0) {
                    if (MAP3D[i][j][Z3D].cycle == 0) printf(" "); // 普通道路
                    else { // 动态障碍 
                        Color(Cstab, 0);
                        printf("_");
                    }
                }
                // 障碍物区域
                else {
                    if (MAP3D[i][j][Z3D].cycle == 0) { // 静态障碍
                        Color(Cwall, 0);
                        printf("x");
                    }
                    else { // 动态障碍
                        Color(Cstab, 0);
                        printf("^");
                    }
                }
            }
            if (i != H3D) cout << endl;
        }
        cout << "目前视图:x*y     坐标:(" << X3D << "," << Y3D << "," << Z3D << ")";
    }
    else if (view == 'y') {
        for (int i = 1; i <= W3D; i++) {
            for (int j = 1; j <= L3D; j++) {
                // 终点标识
                if (i == W3D && j == L3D && X3D == H3D) {
                    Color(Cwin, 0);
                    printf("$");
                }
                // 玩家标识
                else if (i == Y3D && j == Z3D) {
                    Color(Cplayer, 0);
                    printf("o");
                }
                // 可通行区域
                else if (MAP3D[X3D][i][j].canto == 0) {
                    if (MAP3D[X3D][i][j].cycle == 0) printf(" "); // 普通道路
                    else { // 动态障碍 
                        Color(Cstab, 0);
                        printf("_");
                    }
                }
                // 障碍物区域
                else {
                    if (MAP3D[X3D][i][j].cycle == 0) { // 静态障碍
                        Color(Cwall, 0);
                        printf("x");
                    }
                    else { // 动态障碍
                        Color(Cstab, 0);
                        printf("^");
                    }
                }
            }
            if (i != W3D) cout << endl;
        }
        cout << "目前视图:y*z     坐标:(" << X3D << "," << Y3D << "," << Z3D << ")";
    }
    else {
        for (int i = 1; i <= L3D; i++) {
            for (int j = 1; j <= H3D; j++) {
                // 终点标识
                if (i == L3D && j == H3D && Y3D == W3D) {
                    Color(Cwin, 0);
                    printf("$");
                }
                // 玩家标识
                else if (i == Z3D && j == X3D) {
                    Color(Cplayer, 0);
                    printf("o");
                }
                // 可通行区域
                else if (MAP3D[j][Y3D][i].canto == 0) {
                    if (MAP3D[j][Y3D][i].cycle == 0) printf(" "); // 普通道路
                    else { // 动态障碍 
                        Color(Cstab, 0);
                        printf("_");
                    }
                }
                // 障碍物区域
                else {
                    if (MAP3D[j][Y3D][i].cycle == 0) { // 静态障碍
                        Color(Cwall, 0);
                        printf("x");
                    }
                    else { // 动态障碍
                        Color(Cstab, 0);
                        printf("^");
                    }
                }
            }
            if (i != L3D) cout << endl;
        }
        cout << "目前视图:z*x     坐标:(" << X3D << "," << Y3D << "," << Z3D << ")";
    }
}

// 动态元素更新
void update() {
    for (int updatei = 1; updatei <= H; updatei++) {
        for (int updatej = 1; updatej <= W; updatej++) {
            if (MAP[updatei][updatej].cycle != 0) {
                MAP[updatei][updatej].canto++;
                MAP[updatei][updatej].canto %= MAP[updatei][updatej].cycle; // 周期性切换状态
            }
        }
    }
}

// 3D动态元素更新
void update3D() {
    for (int update3Di = 1; update3Di <= H3D; update3Di++) {
        for (int update3Dj = 1; update3Dj <= W3D; update3Dj++) {
            for (int update3Dk = 1; update3Dk <= L3D; update3Dk++) {
                if (MAP3D[update3Di][update3Dj][update3Dk].cycle != 0) {
                    MAP3D[update3Di][update3Dj][update3Dk].canto++;
                    MAP3D[update3Di][update3Dj][update3Dk].canto %= MAP3D[update3Di][update3Dj][update3Dk].cycle; // 周期性切换状态
                }
            }
        }
    }
}

// 随机地图生成算法
void randrestart() {
    for (int i = 1; i <= H; i++) {
        for (int j = 1; j <= W; j++) {
            // 保留起点和终点
            if (!((i == X && j == Y) || (i == H && j == W))) {
                int flag1 = rand() % 2, flag2 = rand() % 2;
                MAP[i][j].canto = (flag1 && flag2); // 25%概率生成障碍

                // 动态障碍生成逻辑
                if (MAP[i][j].canto == 1) {
                    int flagt = rand() % 6; // 16.7%概率变为动态
                    if (flagt == 1) {
                        int tf = rand() % 6 + 1; // 变化周期1-6
                        MAP[i][j].cycle = tf;
                        MAP[i][j].canto = tf / 2; // 初始相位
                    }
                    else {
                        MAP[i][j].cycle = 0;
                    }
                }
            }
            if (!((i != X || j != Y) && (i != H || j != W))) MAP[i][j].canto = 0;
        }
    }
}

// 随机3D地图生成算法
void randrestart3D() {
    for (int i = 1; i <= H3D; i++) {
        for (int j = 1; j <= W3D; j++) {
            for (int k = 1; k <= L3D; k++) {
                // 保留起点和终点
                if (!((i == X3D && j == Y3D && k == Z3D) || (i == H3D && j == W3D && k == L3D))) {
                    int flag1 = rand() % 2, flag2 = rand() % 2;
                    MAP3D[i][j][k].canto = (flag1 && flag2); // 25%概率生成障碍

                    // 动态障碍生成逻辑
                    if (MAP3D[i][j][k].canto == 1) {
                        int flagt = rand() % 6; // 16.7%概率变为动态
                        if (flagt == 1) {
                            int tf = rand() % 6 + 1; // 变化周期1-6
                            MAP3D[i][j][k].cycle = tf;
                            MAP3D[i][j][k].canto = tf / 2; // 初始相位
                        }
                        else {
                            MAP3D[i][j][k].cycle = 0;
                        }
                    }
                }
                if (!((i != X3D || j != Y3D || k != Z3D) && (i != H3D || j != W3D || k != L3D))) MAP3D[i][j][k].canto = 0;
            }
        }
    }
}

// 游戏主循环
void GAME1() {
    char ch; // 用于判断上下左右 
    X = 1;
    Y = 1; // 重置玩家位置
    while (1) {
        // 胜利条件检测(终点在H行W列)
        if (X == H && Y == W) { // 注意:终点坐标可能需要调整
            winnerprint();
            break;
        }

        paint(); // 渲染当前帧
        update(); // 动态元素更新 
        ch = GETCH(); // 获取键盘输入

        // 移动处理与碰撞检测
        if (ch == 'w') { // 上移
            X--;
            if (!(MAP[X][Y].canto == 0 && X != 0)) {
                KO(MAP[X][Y].cycle == 0 ? CD[1] : CD[2]); // 根据障碍类型选择反馈
                break;
            }
        }
        // 其他方向处理同理(略)
        else if (ch == 'd') {
            Y++;
            if (!(MAP[X][Y].canto == 0 && Y != W + 1)) {
                KO(MAP[X][Y].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 's') {
            X++;
            if (!(MAP[X][Y].canto == 0 && X != H + 1)) {
                KO(MAP[X][Y].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 'a') {
            Y--;
            if (!(MAP[X][Y].canto == 0 && Y != 0)) {
                KO(MAP[X][Y].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == ' ') {
            GameStop(m2d); // 游戏暂停 
        }
        system("cls");
    }
    return;
}

// 游戏3D主循环
void GAME3D() {
    char ch; // 用于判断上下左右 
    X3D = 1;
    Y3D = 1;
    Z3D = 1; // 重置玩家位置
    char view = 'x';
    while (1) {
        // 胜利条件检测(终点在H3D行W3D列L3D层)
        if (X3D == H3D && Y3D == W3D && Z3D == L3D) { // 注意:终点坐标可能需要调整
            winnerprint();
            break;
        }

        paint3D(view); // 渲染当前帧
        update3D(); // 动态元素更新 
        ch = GETCH(); // 获取键盘输入
        // 视图切换
        if (ch == 'x' || ch == 'y' || ch == 'z') {
            view = ch;
        }
        // 移动处理与碰撞检测
        else if (ch == 'u') { // 上层 
            Z3D++;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && Z3D != L3D + 1)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 'n') { // 下层
            Z3D--;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && Z3D != 0)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 'w') { // 上移
            X3D--;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && X3D != 0)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]); // 根据障碍类型选择反馈
                break;
            }
        }
        // 其他方向处理同理(略)
        else if (ch == 'd') {
            Y3D++;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && Y3D != W3D + 1)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 's') {
            X3D++;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && X3D != H3D + 1)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == 'a') {
            Y3D--;
            if (!(MAP3D[X3D][Y3D][Z3D].canto == 0 && Y3D != 0)) {
                KO(MAP3D[X3D][Y3D][Z3D].cycle == 0 ? CD[1] : CD[2]);
                break;
            }
        }
        else if (ch == ' ') {
            GameStop(m3d); // 游戏暂停 
        }
        system("cls");
    }
    return;
}

总结

祝大家玩得开心!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值