news 2026/5/14 20:54:06

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用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应用,还能深入理解游戏逻辑的实现原理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 20:52:07

从Servlet到Spring Boot:Java Web开发核心技术演进与实战解析

1. Java Web开发技术演进全景图 如果把Java Web开发比作建造房屋&#xff0c;Servlet就是最原始的砖瓦&#xff0c;Spring框架是预制构件&#xff0c;而Spring Boot则是精装交付的全套解决方案。2001年Servlet 2.3规范发布时&#xff0c;开发者需要手动处理每个HTTP请求&#x…

作者头像 李华
网站建设 2026/5/14 20:44:35

基于Nuxt 3与Shadcn/UI的现代化全栈仪表盘开发实践

1. 项目概述&#xff1a;一个现代全栈仪表盘的起点最近在做一个内部管理后台&#xff0c;技术选型上想用 Nuxt 3 做全栈框架&#xff0c;UI 组件库想用上 Shadcn/UI 的设计感&#xff0c;样式用 Tailwind CSS 来快速构建&#xff0c;还得支持多语言。在 GitHub 上找了一圈&…

作者头像 李华
网站建设 2026/5/14 20:44:10

CircuitPython引脚抽象与通信协议单例:跨平台硬件编程的核心机制

1. 项目概述&#xff1a;CircuitPython的引脚抽象与通信协议单例在嵌入式硬件编程的世界里&#xff0c;最基础也最令人头疼的事情之一&#xff0c;就是和板子上那些密密麻麻的引脚打交道。你刚在一个基于ATSAMD21的QT Py板上用board.A0写好了代码&#xff0c;换到一块ESP32-S2的…

作者头像 李华