欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

一、项目概述

运行效果图

image-20260405111311312

image-20260405111316906

image-20260405111324308

image-20260405111331676

1.1 应用简介

棋谱记录是一款专为棋类爱好者设计的棋谱管理工具,支持围棋和象棋两种棋类的棋谱记录与复盘。无论是职业比赛还是业余对局,都能完整记录对局信息、棋步序列,方便日后复盘研究。应用采用经典的棋谱卡片式布局,对局信息一目了然。

应用支持棋谱的创建、编辑、删除和详情查看,棋步记录功能让每一步棋都有迹可循。复盘功能支持逐步前进后退,帮助棋手深入分析对局过程。标签分类和搜索筛选功能让棋谱管理更加便捷高效。

1.2 核心功能

功能模块 功能描述 实现方式
棋谱列表 展示所有棋谱记录 ListView + Card
新建棋谱 创建新的棋谱记录 表单页面
编辑棋谱 修改已有棋谱信息 表单预填充
删除棋谱 删除不需要的记录 确认对话框
详情查看 查看棋谱完整信息 详情页面
棋步记录 记录每一步棋 列表管理
复盘功能 逐步回放棋局 播放控制
类型筛选 按围棋/象棋筛选 PopupMenu
搜索功能 关键词搜索棋谱 TextField过滤
标签管理 棋谱标签分类 Chip组件

1.3 棋谱记录字段

字段 类型 说明
棋谱标题 String 棋谱名称,必填
棋类类型 ChessType 围棋/象棋
对局结果 GameResult 黑胜/白胜/红胜/和棋
黑方棋手 String 黑方选手姓名
白方棋手 String 白方选手姓名(围棋)
红方棋手 String 红方选手姓名(象棋)
对局日期 DateTime 对局发生日期
对局地点 String 对局举办地点
赛事名称 String 所属赛事
棋步序列 List 棋步列表
棋谱备注 String 棋谱详细说明
标签 List 分类标签
创建时间 DateTime 记录创建时间
更新时间 DateTime 最后修改时间

1.4 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
目标平台 鸿蒙OS API 21+

1.5 项目结构

lib/
└── main_chess_record.dart
    ├── ChessRecordApp         # 应用入口
    ├── ChessType              # 棋类类型枚举
    ├── GameResult             # 对局结果枚举
    ├── ChessMove              # 棋步模型
    ├── ChessRecord            # 棋谱模型
    ├── ChessRecordPage        # 主列表页面
    │   ├── _buildSearchBar()      # 搜索栏
    │   ├── _buildRecordsList()    # 记录列表
    │   └── _buildRecordCard()     # 记录卡片
    ├── ChessRecordEditPage    # 编辑页面
    │   ├── _selectDate()          # 日期选择
    │   ├── _addMove()             # 添加棋步
    │   ├── _addTag()              # 添加标签
    │   └── _save()                # 保存棋谱
    ├── ChessRecordDetailPage  # 详情页面
    │   └── _buildPlayerAvatar()   # 选手头像
    └── MovesReplayPage        # 复盘页面
        ├── _goToMove()            # 跳转棋步
        ├── _previousMove()        # 上一步
        └── _nextMove()            # 下一步

二、系统架构

2.1 整体架构图

Business Logic

Presentation Layer

Data Layer

ChessRecord
棋谱模型

ChessMove
棋步模型

ChessType
棋类枚举

GameResult
结果枚举

列表页面

搜索栏

棋谱卡片列表

编辑页面

基本信息表单

棋步记录区

标签管理区

详情页面

对局信息展示

复盘页面

棋步列表

播放控制

棋谱管理
增删改查

棋步管理
添加删除

复盘控制
前进后退

筛选搜索
_filteredRecords

2.2 类图设计

contains

manages

contains

has

has

navigates

navigates

navigates

ChessRecordApp

+Widget build()

«enumeration»

ChessType

go

xiangqi

«enumeration»

GameResult

unknown

blackWin

whiteWin

redWin

blackWinXiangqi

draw

ChessMove

+int moveNumber

+String notation

+String? comment

+int? x

+int? y

ChessRecord

+String id

+String title

+ChessType chessType

+GameResult result

+String blackPlayer

+String whitePlayer

+String redPlayer

+DateTime gameDate

+List<ChessMove> moves

+List<String> tags

+String resultText

+String chessTypeText

+int totalMoves

ChessRecordPage

-List<ChessRecord> _records

-String _searchQuery

-String _selectedType

-List<ChessRecord> _filteredRecords

+Widget build()

-void _addRecord()

-void _editRecord()

-void _deleteRecord()

MovesReplayPage

-ChessRecord record

-int _currentMove

+Widget build()

-void _goToMove()

-void _previousMove()

-void _nextMove()

ChessRecordEditPage

ChessRecordDetailPage

2.3 数据流程图

新建

编辑

删除

查看

复盘

搜索

筛选

用户操作

操作类型

打开编辑页面

打开编辑页面-预填充

确认对话框

打开详情页面

打开复盘页面

过滤记录列表

按类型过滤

填写表单

添加棋步

保存棋谱

更新记录列表

棋步播放控制

逐步前进后退

2.4 复盘流程

播放控制 棋步列表 复盘页面 用户 播放控制 棋步列表 复盘页面 用户 打开复盘 加载棋步 显示第0手 点击下一步 _nextMove() 显示第1手 点击某步 _goToMove(index) 显示指定手 点击上一步 _previousMove() 显示上一手

三、核心模块设计

3.1 数据模型设计

3.1.1 棋类类型枚举 (ChessType)
enum ChessType {
  go,      // 围棋
  xiangqi, // 象棋
}
3.1.2 对局结果枚举 (GameResult)
enum GameResult {
  unknown,         // 未知
  blackWin,        // 黑胜(围棋)
  whiteWin,        // 白胜
  redWin,          // 红胜(象棋)
  blackWinXiangqi, // 黑胜(象棋)
  draw,            // 和棋
}
3.1.3 棋步模型 (ChessMove)
class ChessMove {
  final int moveNumber;    // 手数
  final String notation;   // 棋步记法
  final String? comment;   // 注释
  final int? x;            // X坐标
  final int? y;            // Y坐标
}
3.1.4 棋谱模型 (ChessRecord)
class ChessRecord {
  final String id;                  // 唯一标识
  String title;                     // 棋谱标题
  ChessType chessType;              // 棋类类型
  GameResult result;                // 对局结果
  String blackPlayer;               // 黑方(围棋)
  String whitePlayer;               // 白方(围棋)
  String redPlayer;                 // 红方(象棋)
  String blackPlayerXiangqi;        // 黑方(象棋)
  DateTime gameDate;                // 对局日期
  String location;                  // 对局地点
  String event;                     // 赛事名称
  List<ChessMove> moves;            // 棋步序列
  String comment;                   // 棋谱备注
  List<String> tags;                // 标签列表
  DateTime createdAt;               // 创建时间
  DateTime updatedAt;               // 更新时间
}

3.2 筛选过滤算法

3.2.1 过滤流程

获取全部记录

是否选择类型?

按类型过滤

保留全部

是否有搜索词?

关键词匹配过滤

按日期排序

返回过滤结果

3.2.2 过滤实现
List<ChessRecord> get _filteredRecords {
  var records = _records.toList();

  // 类型过滤
  if (_selectedType != '全部') {
    ChessType? type;
    switch (_selectedType) {
      case '围棋': type = ChessType.go; break;
      case '象棋': type = ChessType.xiangqi; break;
    }
    if (type != null) {
      records = records.where((r) => r.chessType == type).toList();
    }
  }

  // 关键词搜索
  if (_searchQuery.isNotEmpty) {
    records = records.where((r) {
      return r.title.toLowerCase().contains(_searchQuery.toLowerCase()) ||
          r.event.toLowerCase().contains(_searchQuery.toLowerCase()) ||
          r.blackPlayer.toLowerCase().contains(_searchQuery.toLowerCase());
    }).toList();
  }

  records.sort((a, b) => b.gameDate.compareTo(a.gameDate));
  return records;
}

3.3 复盘控制算法

3.3.1 播放控制流程

初始状态

下一步

下一步

上一步

上一步

回到开始

跳到结束

第0手

第1手

第2手

第N手

3.3.2 播放控制实现
void _previousMove() {
  if (_currentMove > 0) {
    setState(() {
      _currentMove--;
    });
  }
}

void _nextMove() {
  if (_currentMove < widget.record.moves.length) {
    setState(() {
      _currentMove++;
    });
  }
}

void _goToMove(int index) {
  setState(() {
    _currentMove = index;
  });
}

void _goToStart() {
  setState(() {
    _currentMove = 0;
  });
}

void _goToEnd() {
  setState(() {
    _currentMove = widget.record.moves.length;
  });
}

3.4 页面结构设计

3.4.1 列表页面布局

列表页面

搜索栏

棋谱卡片列表

浮动按钮

棋谱卡片1

棋谱卡片2

...

类型/结果标签

棋谱标题

赛事/日期

对局双方

手数/标签

3.4.2 编辑页面布局
┌─────────────────────────────────────────────────────────────┐
│  AppBar: 新建/编辑棋谱                        [💾 保存]     │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 📝 棋谱标题 *                                       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌──────────────────┐  ┌──────────────────┐                │
│  │ 棋类: 围棋/象棋  │  │ 结果: 黑胜/白胜  │                │
│  └──────────────────┘  └──────────────────┘                │
│                                                             │
│  📅 对局日期 | 🏆 赛事名称 | 📍 对局地点                     │
│                                                             │
│  对局双方:                                                  │
│  ┌──────────────────┐  ┌──────────────────┐                │
│  │ ● 黑方           │  │ ○ 白方           │                │
│  └──────────────────┘  └──────────────────┘                │
│                                                             │
│  棋步记录                                    [+ 添加]       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ ① 炮二平五  ② 马8进7  ③ ...                        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  📋 棋谱备注                                               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              多行文本输入                            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  标签: [名局] [决赛] [×]                                   │
└─────────────────────────────────────────────────────────────┘

3.5 状态管理

3.5.1 核心状态变量
class _ChessRecordPageState extends State<ChessRecordPage> {
  final List<ChessRecord> _records = [];   // 所有棋谱
  String _searchQuery = '';                 // 搜索关键词
  String _selectedType = '全部';            // 选中的类型筛选
}

class _MovesReplayPageState extends State<MovesReplayPage> {
  int _currentMove = 0;                     // 当前棋步位置
}
3.5.2 状态更新流程
// 添加棋步
void _addMove() {
  if (_moveController.text.isNotEmpty) {
    setState(() {
      _moves.add(ChessMove(
        moveNumber: _moves.length + 1,
        notation: _moveController.text,
      ));
      _moveController.clear();
    });
  }
}

// 删除棋步
void _removeMove(int index) {
  setState(() {
    _moves.removeAt(index);
    // 重新编号
    for (int i = 0; i < _moves.length; i++) {
      _moves[i] = ChessMove(
        moveNumber: i + 1,
        notation: _moves[i].notation,
      );
    }
  });
}

四、UI设计规范

4.1 配色方案

应用采用棕色主题风格,体现棋类的传统文化:

颜色类型 色值 用途
主色 Brown AppBar、按钮、强调
围棋标签 Black 围棋类型标识
象棋标签 Red 象棋类型标识
黑方 Black 黑方选手标识
白方 Grey 白方选手标识
红方 Red 红方选手标识

4.2 棋类类型样式

4.2.1 类型标签
类型 颜色 说明
围棋 黑色 黑白对弈
象棋 红色 红黑对弈
4.2.2 结果标签
结果 颜色
黑胜 黑色
白胜 灰色
红胜 红色
和棋 橙色
未知 灰色

4.3 组件规范

4.3.1 棋谱卡片
┌─────────────────────────────────────────────────────────────┐
│  [围棋] [黑胜]                                      ⋮      │
│  名人战决赛第一局                                           │
│  🏆 名人战    📅 2024-01-15                                │
│  ● 柯洁 vs ○ 申真谞                                        │
│  📋 250手                              [名局] [决赛]       │
└─────────────────────────────────────────────────────────────┘
4.3.2 选手头像
┌─────────────────┐
│  ● 黑方         │
│     柯洁        │
└─────────────────┘

4.4 交互设计

4.4.1 操作方式
操作 手势 效果
查看详情 点击卡片 跳转详情页
新建棋谱 点击浮动按钮 跳转编辑页
编辑棋谱 点击菜单-编辑 跳转编辑页
删除棋谱 点击菜单-删除 确认后删除
复盘棋局 点击菜单-复盘 跳转复盘页
搜索 输入关键词 实时过滤
筛选 点击筛选图标 选择类型
4.4.2 复盘控制
┌─────────────────────────────────────────────────────────────┐
│  ⏮ ◀  [ 50/250 ]  ▶ ⏭                                     │
└─────────────────────────────────────────────────────────────┘

五、核心功能实现

5.1 列表页面构建


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('棋谱记录'),
      actions: [
        PopupMenuButton<String>(
          icon: const Icon(Icons.filter_list),
          onSelected: (value) {
            setState(() {
              _selectedType = value;
            });
          },
          itemBuilder: (context) => _typeFilters.map((type) {
            return PopupMenuItem(value: type, child: Text(type));
          }).toList(),
        ),
      ],
    ),
    body: Column(
      children: [
        _buildSearchBar(),
        Expanded(
          child: _filteredRecords.isEmpty
              ? _buildEmptyState()
              : _buildRecordsList(),
        ),
      ],
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: _addRecord,
      child: const Icon(Icons.add),
    ),
  );
}

5.2 棋步管理

// 添加棋步
void _addMove() {
  if (_moveController.text.isNotEmpty) {
    setState(() {
      _moves.add(ChessMove(
        moveNumber: _moves.length + 1,
        notation: _moveController.text,
      ));
      _moveController.clear();
    });
  }
}

// 删除棋步
void _removeMove(int index) {
  setState(() {
    _moves.removeAt(index);
    // 重新编号所有棋步
    for (int i = 0; i < _moves.length; i++) {
      _moves[i] = ChessMove(
        moveNumber: i + 1,
        notation: _moves[i].notation,
        comment: _moves[i].comment,
      );
    }
  });
}

5.3 复盘功能

class _MovesReplayPageState extends State<MovesReplayPage> {
  int _currentMove = 0;

  void _previousMove() {
    if (_currentMove > 0) {
      setState(() {
        _currentMove--;
      });
    }
  }

  void _nextMove() {
    if (_currentMove < widget.record.moves.length) {
      setState(() {
        _currentMove++;
      });
    }
  }

  void _goToMove(int index) {
    setState(() {
      _currentMove = index;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // 当前手数显示
          Text('第 $_currentMove / ${widget.record.moves.length} 手'),
          // 棋步列表
          Expanded(child: ListView.builder(...)),
          // 播放控制
          Row(
            children: [
              IconButton(onPressed: _goToStart, icon: Icon(Icons.skip_previous)),
              IconButton(onPressed: _previousMove, icon: Icon(Icons.chevron_left)),
              Text('$_currentMove/${widget.record.moves.length}'),
              IconButton(onPressed: _nextMove, icon: Icon(Icons.chevron_right)),
              IconButton(onPressed: _goToEnd, icon: Icon(Icons.skip_next)),
            ],
          ),
        ],
      ),
    );
  }
}

5.4 表单验证与保存

void _save() {
  if (_formKey.currentState!.validate()) {
    final now = DateTime.now();

    final record = ChessRecord(
      id: widget.record?.id ?? DateTime.now().millisecondsSinceEpoch.toString(),
      title: _titleController.text,
      chessType: _selectedType,
      result: _selectedResult,
      blackPlayer: _blackPlayerController.text,
      whitePlayer: _whitePlayerController.text,
      redPlayer: _redPlayerController.text,
      blackPlayerXiangqi: _blackPlayerXiangqiController.text,
      gameDate: _gameDate,
      location: _locationController.text,
      event: _eventController.text,
      moves: _moves,
      comment: _commentController.text,
      tags: _tags,
      createdAt: widget.record?.createdAt ?? now,
      updatedAt: now,
    );

    Navigator.pop(context, record);
  }
}

六、棋谱知识拓展

6.1 围棋棋谱

6.1.1 围棋记谱方式

围棋记谱

坐标记谱

中文记谱

Q16 (星位)

D4 (小目)

右上星

左下小目

6.1.2 围棋术语
术语 说明
棋盘上的9个星位
小目 三四路位置
目外 三五路位置
高目 四五路位置
天元 棋盘中心点

6.2 象棋棋谱

6.2.1 象棋记谱方式

象棋记谱

着法记录

局面记录

炮二平五

马8进7

车一进一

初始局面

残局局面

6.2.2 象棋术语
术语 说明
棋子横向移动
棋子向前移动
退 棋子向后移动
将军
绝杀

6.3 棋谱保存格式

6.3.1 常见格式
格式 说明 用途
SGF 围棋标准格式 围棋软件通用
PGN 国际象棋格式 国际象棋通用
XQF 象棋格式 象棋软件专用
JSON 通用数据格式 跨平台交换

七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 2024-03-31 核心记录功能 棋步管理功能 复盘播放功能 数据持久化 棋盘可视化 导入导出功能 形势判断功能 AI分析功能 在线对弈功能 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 棋谱记录应用开发计划

7.2 功能扩展建议

7.2.1 棋盘可视化
功能 说明
围棋棋盘 19x19路棋盘显示
象棋棋盘 9x10路棋盘显示
落子动画 棋子放置动画效果
标记功能 标记关键点
7.2.2 导入导出
功能 说明
SGF导入 导入围棋SGF文件
XQF导入 导入象棋XQF文件
图片导出 导出棋盘图片
分享功能 分享棋谱链接
7.2.3 AI分析
功能 说明
形势判断 分析当前局面
最佳选点 AI推荐最佳着法
失误分析 标记关键失误

八、注意事项

8.1 开发注意事项

  1. 棋步编号:删除棋步后需要重新编号

  2. 类型切换:切换棋类类型时清空不相关字段

  3. 日期处理:注意日期的格式化和解析

  4. 表单验证:必填字段要进行验证

8.2 用户体验优化

💡 用户体验建议 💡

  • 棋步记录简洁高效
  • 复盘操作流畅自然
  • 对局信息一目了然
  • 支持快速搜索筛选

8.3 常见问题

问题 原因 解决方案
棋步编号错误 删除后未重编号 检查重编号逻辑
类型切换异常 字段未清空 切换时清空字段
复盘位置错误 索引越界 检查边界条件
搜索无结果 过滤条件错误 检查过滤逻辑

九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

9.2 运行命令

# 查看可用设备
flutter devices

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_chess_record.dart

# 运行到Windows
flutter run -d windows -t lib/main_chess_record.dart

# 代码分析
flutter analyze lib/main_chess_record.dart

十、总结

棋谱记录应用通过完善的功能设计,帮助棋类爱好者记录和管理棋谱。应用支持围棋和象棋两种棋类,对局信息、棋步序列、备注标签等核心数据完整记录。复盘功能支持逐步前进后退,帮助棋手深入分析对局过程。

棋步管理功能支持添加和删除操作,编号自动维护。标签功能帮助对棋谱进行分类,方便筛选和管理。搜索和筛选功能让用户快速定位目标棋谱,提高管理效率。

界面设计采用棕色主题风格,体现棋类的传统文化底蕴。类型标签使用不同颜色区分围棋和象棋,选手头像清晰展示对局双方。应用采用Material Design 3设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。

棋谱记录,传承经典,复盘研究,棋艺精进!


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐