当前位置: 首页 > news >正文

手把手教你用C++和STL写一个命令行象棋对战程序(附完整可运行代码)

从零构建C++命令行象棋:STL实战与设计模式精解

1. 项目架构设计

象棋程序的核心在于棋盘表示棋子行为建模。我们采用面向对象设计,将棋盘抽象为ChessBoard类,棋子抽象为ChessPiece基类及其派生类。这种设计符合开闭原则,新增棋子类型无需修改现有代码。

关键数据结构选择

  • 使用std::array<std::array<ChessPiece*, 9>, 10>表示10行9列的棋盘
  • 红黑双方棋子分别用std::list<ChessPiece*>存储,便于遍历和删除
  • 坐标系统采用Point结构体封装(x,y)位置
class ChessBoard { private: std::array<std::array<ChessPiece*, 9>, 10> board; std::list<ChessPiece*> redPieces; std::list<ChessPiece*> blackPieces; public: // 接口方法... };

2. 棋子移动算法实现

每种棋子通过重写CanMoveTo虚函数实现特有移动规则。我们采用策略模式,将不同棋子的移动规则封装在各自的类中。

2.1 车(Rook)的直线移动

bool Rook::CanMoveTo(const Point& dest) const { if (dest.x != current.x && dest.y != current.y) return false; // 检查路径上是否有阻挡 if (dest.x == current.x) { int step = dest.y > current.y ? 1 : -1; for (int y = current.y + step; y != dest.y; y += step) { if (board.GetPiece({current.x, y})) return false; } } else { int step = dest.x > current.x ? 1 : -1; for (int x = current.x + step; x != dest.x; x += step) { if (board.GetPiece({x, current.y})) return false; } } return true; }

2.2 马(Horse)的日字移动

马走日需考虑蹩马腿:

bool Horse::CanMoveTo(const Point& dest) const { int dx = abs(dest.x - current.x); int dy = abs(dest.y - current.y); if (!((dx == 1 && dy == 2) || (dx == 2 && dy == 1))) return false; // 检查马腿位置 Point blockPoint = dx == 2 ? Point{(current.x + dest.x)/2, current.y} : Point{current.x, (current.y + dest.y)/2}; return !board.GetPiece(blockPoint); }

3. 游戏状态管理

ChessGame类负责管理游戏流程,实现以下核心功能:

  1. 回合制切换:使用布尔变量isRedTurn记录当前回合
  2. 胜负判定
    • 将帅照面直接判胜
    • 一方将/帅被吃判负
  3. 特殊规则处理
    • 兵过河后才能横向移动
    • 象不能过河
    • 士不出九宫
class ChessGame { public: bool Move(const Point& from, const Point& to) { ChessPiece* piece = board.GetPiece(from); if (!piece || piece->IsRed() != isRedTurn) return false; if (piece->CanMoveTo(to)) { // 执行移动逻辑... isRedTurn = !isRedTurn; return true; } return false; } GameState CheckGameState() const { // 胜负判定逻辑... } private: ChessBoard board; bool isRedTurn = true; // 红方先行 };

4. 命令行交互实现

为提升用户体验,我们实现以下交互功能:

  1. 彩色棋盘显示:使用Windows API设置控制台颜色
  2. 输入验证:确保坐标在0-8和0-9范围内
  3. 游戏状态提示:显示当前回合和获胜信息
void PrintBoard(const ChessBoard& board) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); for (int y = 0; y < 10; ++y) { for (int x = 0; x < 9; ++x) { ChessPiece* piece = board.GetPiece({x, y}); if (piece) { SetConsoleTextAttribute(hConsole, piece->IsRed() ? FOREGROUND_RED : FOREGROUND_BLUE); std::cout << piece->GetName(); } else { std::cout << "+"; } } std::cout << std::endl; } SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); }

5. 内存管理与异常处理

智能指针应用

class ChessBoard { private: std::array<std::array<std::unique_ptr<ChessPiece>, 9>, 10> board; std::list<std::unique_ptr<ChessPiece>> redPieces; std::list<std::unique_ptr<ChessPiece>> blackPieces; };

移动语义优化

ChessBoard::ChessBoard(ChessBoard&& other) noexcept : board(std::move(other.board)), redPieces(std::move(other.redPieces)), blackPieces(std::move(other.blackPieces)) {}

6. 单元测试策略

为验证各棋子移动规则,我们使用Google Test框架:

TEST(RookTest, StraightMove) { ChessBoard board; Rook rook({4,4}, true, board); EXPECT_TRUE(rook.CanMoveTo({4,8})); // 垂直移动 EXPECT_TRUE(rook.CanMoveTo({8,4})); // 水平移动 EXPECT_FALSE(rook.CanMoveTo({5,5})); // 斜线移动 } TEST(HorseTest, BlockedMove) { ChessBoard board; Horse horse({2,2}, true, board); Rook blocker({2,3}, false, board); // 蹩马腿 EXPECT_FALSE(horse.CanMoveTo({1,4})); }

7. 性能优化技巧

  1. 空间换时间:使用二维数组直接访问棋子,O(1)时间复杂度
  2. 延迟计算:只在需要时检查将帅照面
  3. 位运算优化:使用位掩码存储棋子属性
enum PieceAttributes { CAN_CROSS_RIVER = 1 << 0, CAN_CAPTURE = 1 << 1, // ... }; class ChessPiece { protected: uint8_t attributes; public: bool CanCrossRiver() const { return attributes & CAN_CROSS_RIVER; } };

8. 扩展性设计

通过继承体系可轻松支持新棋子类型:

class NewChessPiece : public ChessPiece { public: NewChessPiece(const Point& pos, bool isRed, ChessBoard& board) : ChessPiece(pos, isRed, board) {} bool CanMoveTo(const Point& dest) const override { // 实现特定移动规则 } };

9. 跨平台考虑

使用条件编译实现跨平台支持:

#ifdef _WIN32 #include <windows.h> void SetConsoleColor(int color) { /* Windows实现 */ } #else void SetConsoleColor(int color) { /* Linux实现 */ } #endif

10. 完整项目结构

最终项目包含以下文件:

ChineseChess/ ├── Chess.h # 类声明和常量定义 ├── Chess.cpp # 类方法实现 ├── main.cpp # 主程序入口 └── tests/ # 单元测试

在实现过程中,特别要注意象棋规则的各种边界情况,如:

  • 兵到底线后的处理
  • 将帅不能主动送吃
  • 长将判负规则
  • 重复局面处理

通过这个项目,开发者不仅能掌握C++面向对象编程和STL应用,还能深入理解游戏逻辑的实现原理。

http://www.jsqmd.com/news/817500/

相关文章:

  • 2026年5月贵州工程机械设备/混凝土搅拌车/混凝土泵车/车载泵/混凝土输送泵厂家解析,认准通用工程机械设备出租 - 2026年企业推荐榜
  • RedShell框架:基于LLM的Windows渗透测试自动化工具
  • 从ZIP压缩到网络传输:CRC32校验码在你不知道的地方默默守护数据安全
  • 用P4和BMv2在Ubuntu上搭建你的第一个可编程交换机(附完整代码和避坑指南)
  • 安阳招聘平台哪个好:秒聘网稳居首位 - 13724980961
  • 2026年天津GEO优化权威排名:核心数据深度解析与避坑指南 - 元点智创
  • 深入VESC Tool:Makerbase VESC的PPM遥控信号配置与‘电流控制’模式详解
  • 论文写作圈都在传的书匠策AI(http://www.shujiangce.com),期刊论文功能到底有多“离谱“?
  • 第19天:面向对象编程进阶
  • 技能图谱构建:从知识管理到团队能力数字化的工程实践
  • LLM-Hub:快速搭建AI应用原型的开源集成平台实践指南
  • ce-lazy-student:基于VSCode的智能代码生成与自动化开发效率工具
  • 2026年乌鲁木齐GEO优化权威排名:核心数据深度解析与避坑指南 - 元点智创
  • Notion AI Agent Hub:工作空间变身智能体编排中心
  • Java做AI不行?2026年最大的认知误区
  • 智能别墅安防组网实战:用这款433模块的Mesh和防冲撞功能,低成本实现全屋传感器信号无死角覆盖
  • 个人知识体系工程化:从计划到构建的系统化实践
  • C# Winform ToolTip:从基础显示到自定义绘制的实战指南
  • 开源项目chatgpt-artifacts:为ChatGPT实现Claude式并排视图,支持多模型部署
  • 2026年5月深度解析义乌实木/原木/多层实木/兔宝宝/定制衣柜供应格局与领军者 - 2026年企业推荐榜
  • ARM有符号加载指令LDRSB/LDRSH详解与应用
  • AIGS:软件正在被AI重新定义一遍
  • 5月13日AI生态大变局:购物Agent、隐私革命与算力危机
  • 基于Nuxt 3与Shadcn/UI的现代化全栈仪表盘开发实践
  • Cerebras $488亿IPO:晶圆级芯片挑战英伟达AI算力霸权
  • 基于Robei与FPGA:构建Lora无线通讯的机器人控制核心
  • 独立开发者如何利用 Taotoken 以更低成本试验多种大模型
  • 【限时解锁】Midjourney私有风格库构建术:仅限Pro+账户可用的--style-ref隐式调用协议与本地化缓存加速秘技
  • 3分钟掌握Navicat密码找回:免费开源工具的终极使用指南
  • Harbor私有仓库从入门到精通:不只是安装,还有多节点登录配置与日常运维命令