2.C++基础实践项目总结

2.总结


2.1 知识点

学习的主要内容

总结目的——养成良好的学习习惯

流程图

断点学习法

练习实践

程序员的最终目标


2.2 核心要点速览

项目架构

整体结构

  • 场景管理:通过 E_SceneType 枚举管理三个场景(开始、游戏、结束)
  • 主循环while(true) + switch 实现场景切换
  • 场景切换:修改 nowSceneTypebreak 跳出当前场景循环

核心模块

模块 职责 关键函数/结构体
控制台初始化 设置窗口大小、隐藏光标 consoleInit()
开始/结束场景 菜单选择、场景切换 beginOrEndScene()
游戏场景 核心游戏逻辑 gameScene()
地图系统 格子生成、绘制 MapGrid
玩家系统 移动、状态管理 Player

控制台设置

API 作用 示例
setConsoleSize(w, h) 设置控制台大小 setConsoleSize(50, 30)
setCursorVisibility(bool) 显示/隐藏光标 setCursorVisibility(false)
setCursorPosition(x, y) 设置光标位置 setCursorPosition(10, 5)
setTextColor(color) 设置文本颜色 setTextColor(Red)
system("cls") 清屏 切换场景前调用

颜色系统

enum E_Color
{
    Blue = 1,    // 蓝色
    Green = 2,   // 绿色
    Red = 4,     // 红色
    White = 7,   // 白色
};

颜色组合Red | Blue = 紫色,Green | Blue = 青色,Red | Green = 黄色

场景管理

场景枚举

enum E_SceneType
{
    Begin,  // 开始场景
    Game,   // 游戏场景
    End,    // 结束场景
};

场景切换流程

主循环 while(true)
    ↓
switch(nowSceneType)
    ├── Begin → beginOrEndScene() → 选择开始 → nowSceneType = Game
    ├── Game  → gameScene()       → 游戏结束 → nowSceneType = End
    └── End   → beginOrEndScene() → 选择返回 → nowSceneType = Begin

地图系统

格子类型

类型 枚举值 符号 颜色 效果 概率
普通格子 Normal 白色 无效果 85%
炸弹 Boom 红色 后退5格 5%
暂停 Pause 蓝色 暂停一回合 5%
时空隧道 Tunnel ¤ 黄色 随机效果 5%

地图生成逻辑

  • 蛇形布局:X 方向移动 10 格后,Y 方向移动 2 行,然后反向
  • 动态内存new Grid[gridNum] 分配格子数组
  • 析构释放delete[] grids 防止内存泄漏

玩家系统

玩家属性

属性 类型 说明
type E_PlayerType 玩家/电脑
nowIndex int 当前格子索引
isPause bool 是否暂停

移动逻辑

扔骰子(1~6)
    ↓
nowIndex += 点数
    ↓
判断格子类型 → 触发效果
    ↓
重绘地图和玩家
    ↓
判断是否到达终点

时空隧道效果

随机数 效果
1 后退5格
2 暂停一回合
3 与对方交换位置

输入处理

按键 ASCII 作用
W/w 87/119 选择上一项
S/s 83/115 选择下一项
J/j 74/106 确认选择
任意键 - 扔骰子

注意:使用 _getch() 获取输入,无需回车确认。


2.3 面试题精选

基础题

1. 这个飞行棋项目的整体架构是怎么设计的?

题目

请简述这个飞行棋项目的整体架构设计思路。

深入解析

项目采用场景驱动的架构设计,核心思想是将游戏划分为多个独立场景,每个场景有独立的逻辑和渲染。

架构层次

  1. 控制台层:封装底层 API,提供窗口大小、光标、颜色控制
  2. 场景管理层:通过枚举和主循环实现场景切换
  3. 游戏逻辑层:地图、玩家、格子效果等核心逻辑
  4. 渲染层:各模块的 draw() 方法负责绘制

数据流向

用户输入 → 场景逻辑 → 数据更新 → 渲染绘制 → 用户输入(循环)

关键设计

  • 使用 enum class 定义类型,避免命名冲突
  • 结构体封装数据和行为(如 Grid::draw()Player::draw()
  • 动态内存管理地图数据,析构时释放
答题示例

项目采用场景驱动架构,分为开始、游戏、结束三个场景。

主循环用 while + switch 根据场景类型调用对应处理函数。每个场景独立处理输入、逻辑和渲染。

数据层用结构体封装,比如 Map 管理格子数组,Player 管理玩家状态。控制台 API 封装成工具函数,方便调用。

参考文章
  • 1.飞行棋实践

2. 如何实现场景切换?

题目

项目中是如何实现场景切换的?请说明具体实现方式。

深入解析

场景切换通过状态机模式实现,核心是维护一个当前场景状态变量。

实现要点

  1. 状态变量E_SceneType nowSceneType 记录当前场景
  2. 主循环分发switch(nowSceneType) 根据状态调用对应函数
  3. 状态修改:在场景函数内修改 nowSceneType 实现跳转
  4. 清屏重绘:切换场景前 system("cls") 清除旧内容

代码示例

E_SceneType nowSceneType = Begin;
while (true)
{
    switch (nowSceneType)
    {
    case Begin:
        system("cls");
        beginOrEndScene(w, h, nowSceneType);
        break;
    case Game:
        system("cls");
        gameScene(w, h, nowSceneType);
        break;
    case End:
        system("cls");
        beginOrEndScene(w, h, nowSceneType);
        break;
    }
}
答题示例

状态机模式实现。维护一个 nowSceneType 枚举变量,主循环用 switch 根据它调用对应场景函数。

场景函数内部通过修改 nowSceneType 实现跳转,比如开始场景选「开始游戏」后设为 Game

切换前调用 system("cls") 清屏,保证新场景干净显示。

参考文章
  • 1.飞行棋实践

进阶题

1. 地图生成算法是如何设计的?

题目

请说明地图格子的生成算法,包括布局和类型分布。

深入解析

地图生成包含布局算法类型分布两部分。

布局算法(蛇形)

int stepNum = 2;  // X方向步长
for (int i = 0; i < gridNum; i++)
{
    grids[i].pos = Vector2(x, y);
    
    if (indexX == 10)
    {
        y += 1;
        ++indexY;
        if (indexY == 2)
        {
            stepNum = -stepNum;
            indexX = 0;
            indexY = 0;
        }
    }
    else
    {
        x += stepNum;
        ++indexX;
    }
}

类型分布(概率)

int randomNum = getRandom(0, 100);
if (randomNum < 85 || i == 0 || i == gridNum - 1)
    grids[i].type = Normal;
else if (randomNum < 90)
    grids[i].type = Boom;
else if (randomNum < 95)
    grids[i].type = Pause;
else
    grids[i].type = Tunnel;

设计考量

  • 首尾格子强制普通,避免开局/终点触发特殊效果
  • 概率可调,通过修改随机数区间实现
答题示例

布局用蛇形算法:X 方向走 10 格,Y 方向下移 2 行,然后 X 反向,循环往复。

类型用概率分布:随机数 0-100,85% 普通格子,5% 炸弹,5% 暂停,5% 时空隧道。

首尾格子强制普通,避免玩家开局踩炸弹或终点触发特殊效果。

参考文章
  • 1.飞行棋实践

2. 如何处理玩家和电脑重合的情况?

题目

项目中如何处理玩家和电脑在同一格子的重合情况?

深入解析

重合处理通过条件判断 + 特殊绘制实现。

判断逻辑

void drawPlayer(Player& player, Player& computer, Map& map)
{
    if (player.nowIndex == computer.nowIndex)
    {
        Grid grid = map.grids[player.nowIndex];
        setCursorPosition(grid.pos.x, grid.pos.y);
        setTextColor(White);
        cout << "◎";
    }
    else
    {
        player.draw(map);
        computer.draw(map);
    }
}

设计要点

  1. 比较索引nowIndex 相同即为重合
  2. 特殊符号:重合时用 区分
  3. 颜色区分:玩家紫红色 ,电脑青色 ,重合白色
  4. 绘制时机:每次移动后重新绘制,保证状态同步
答题示例

通过比较 nowIndex 判断重合。重合时绘制特殊符号 ,不重合时分别绘制玩家 和电脑

颜色也做区分:玩家紫红色,电脑青色,重合白色。

每次移动后调用 drawPlayer() 重新绘制,保证显示状态实时更新。

参考文章
  • 1.飞行棋实践

深度题

1. 如果要扩展这个项目,你会如何设计?

题目

如果要为这个飞行棋项目添加新功能(如多人游戏、道具系统、存档功能),你会如何设计架构?

深入解析

多人游戏扩展

vector<Player> players;
int currentPlayerIndex = 0;

void nextTurn()
{
    currentPlayerIndex = (currentPlayerIndex + 1) % players.size();
}

道具系统

enum E_ItemType
{
    Accelerate,
    Shield,
    Reverse,
};

struct Item
{
    E_ItemType type;
    int count;
};

// 在 Player 结构体中添加
map<E_ItemType, int> items;

存档功能

struct SaveData
{
    vector<int> playerPositions;
    vector<bool> playerPauses;
    vector<Grid> mapGrids;
};

void saveGame(const string& filename, const SaveData& data)
{
    ofstream file(filename, ios::binary);
    file.write((char*)&data, sizeof(data));
}

SaveData loadGame(const string& filename)
{
    SaveData data;
    ifstream file(filename, ios::binary);
    file.read((char*)&data, sizeof(data));
    return data;
}

架构优化建议

  1. 场景基类:抽象出 Scene 基类,各场景继承实现
  2. 事件系统:格子效果改为事件触发,便于扩展
  3. 配置文件:格子概率、地图大小等改为配置
答题示例

多人游戏:用 vector<Player> 存储玩家,currentPlayerIndex 记录当前回合,每回合结束取模切换。

道具系统:定义道具枚举,在 Player 中加 map<E_ItemType, int> 存储道具数量。

存档功能:定义 SaveData 结构体,用二进制文件读写保存玩家位置、暂停状态、地图信息。

架构上可以抽象 Scene 基类,格子效果改为事件系统,配置外置提高扩展性。

参考文章
  • 1.飞行棋实践


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏