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

用c++或c 做一个深度遍历的 棋谱树,我用来 做围棋棋谱的教学,要求节省内存、效率高,便于保存(棋谱)和拷贝棋谱

为了实现一个高效且节省内存的围棋棋谱树,我们可以使用如下思路和方法:

    1.    数据结构设计:

    •    使用一个树结构,每个节点表示棋局的一步(包括坐标和落子的颜色)。

    •    每个节点存储子节点的指针,表示该步之后的可能变化。

    •    为了节省内存,可以使用指针列表或数组管理子节点。

    •    节点还应包括对父节点的指针,便于回溯。

    2.    效率优化:

    •    使用紧凑的结构体存储棋局信息(例如,用一个 char 存储坐标,用一个 bool 存储黑白方)。

    •    使用内存池管理节点,减少频繁的动态内存分配开销。

    •    通过深度优先遍历(DFS)进行棋谱操作。

    3.    便于保存和拷贝:

    •    使用序列化和反序列化方法将棋谱存储为文件或字符串。

    •    提供简单的接口来拷贝整个棋谱树。

 

以下是一个示例实现:

 

代码实现

 

#include <iostream>

#include <vector>

#include <string>

#include <memory>

#include <fstream>

 

// 棋谱节点结构

struct MoveNode {

    int x, y;               // 落子坐标

    bool isBlack;           // 是否为黑子

    std::vector<MoveNode*> children; // 子节点

    MoveNode* parent;       // 父节点

 

    // 构造函数

    MoveNode(int x, int y, bool isBlack, MoveNode* parent = nullptr)

        : x(x), y(y), isBlack(isBlack), parent(parent) {}

 

    ~MoveNode() {

        for (auto child : children) {

            delete child;

        }

    }

};

 

// 棋谱树类

class GoTree {

private:

    MoveNode* root; // 根节点

 

public:

    // 构造函数

    GoTree() {

        root = new MoveNode(-1, -1, false); // 虚拟根节点

    }

 

    ~GoTree() {

        delete root;

    }

 

    // 添加棋谱节点

    MoveNode* addMove(MoveNode* parent, int x, int y, bool isBlack) {

        auto* newNode = new MoveNode(x, y, isBlack, parent);

        parent->children.push_back(newNode);

        return newNode;

    }

 

    // 深度优先遍历(打印棋谱)

    void printTree(MoveNode* node, int depth = 0) {

        if (node->x != -1 && node->y != -1) { // 跳过虚拟根节点

            std::cout << std::string(depth * 2, ' ')

                      << (node->isBlack ? "Black" : "White") << " (" << node->x << ", " << node->y << ")\n";

        }

        for (auto* child : node->children) {

            printTree(child, depth + 1);

        }

    }

 

    // 保存棋谱到文件

    void saveTree(MoveNode* node, std::ostream& os) {

        if (node->x != -1 && node->y != -1) {

            os << (node->isBlack ? "B" : "W") << "," << node->x << "," << node->y << "\n";

        }

        for (auto* child : node->children) {

            saveTree(child, os);

        }

        os << "END\n"; // 用END标记一个节点的子节点结束

    }

 

    // 从文件加载棋谱

    MoveNode* loadTree(std::istream& is, MoveNode* parent = nullptr) {

        std::string line;

        MoveNode* currentNode = parent ? parent : root;

        while (std::getline(is, line)) {

            if (line == "END") {

                return currentNode; // 子节点结束

            }

            char color;

            int x, y;

            if (sscanf(line.c_str(), "%c,%d,%d", &color, &x, &y) == 3) {

                bool isBlack = (color == 'B');

                currentNode = addMove(currentNode, x, y, isBlack);

                loadTree(is, currentNode);

            }

        }

        return currentNode;

    }

 

    MoveNode* getRoot() {

        return root;

    }

};

 

int main() {

    GoTree tree;

 

    // 构建棋谱

    auto* move1 = tree.addMove(tree.getRoot(), 3, 3, true);   // 黑3,3

    auto* move2 = tree.addMove(move1, 16, 16, false);         // 白16,16

    tree.addMove(move2, 4, 4, true);                          // 黑4,4

 

    // 打印棋谱

    std::cout << "棋谱树:\n";

    tree.printTree(tree.getRoot());

 

    // 保存棋谱

    std::ofstream outFile("goboard.txt");

    tree.saveTree(tree.getRoot(), outFile);

    outFile.close();

 

    // 加载棋谱

    std::ifstream inFile("goboard.txt");

    GoTree loadedTree;

    loadedTree.loadTree(inFile);

    inFile.close();

 

    // 打印加载后的棋谱

    std::cout << "\n加载后的棋谱树:\n";

    loadedTree.printTree(loadedTree.getRoot());

 

    return 0;

}

 

功能说明

    1.    数据结构:

    •    每一步棋局存储为一个 MoveNode,包含坐标、落子颜色、子节点和父节点。

    •    使用 std::vector 存储子节点,可以动态扩展子节点数量。

    2.    操作与接口:

    •    addMove:添加棋谱节点。

    •    printTree:深度优先遍历打印棋谱树。

    •    saveTree 和 loadTree:实现棋谱的保存和加载。

    3.    文件格式:

    •    保存为简单的 CSV 格式:B,3,3 表示黑棋落在 (3,3),END 表示子节点结束。

 

优点

    •    节省内存:使用紧凑的节点结构体和动态内存管理。

    •    效率高:支持快速的棋谱构建、保存和加载。

    •    可扩展性:可以根据需求增加功能,如支持回溯、分支删除等。

 

你可以根据实际需求进一步优化,比如将 std::vector 替换为固定大小的数组以进一步节省内存。

 


http://www.kler.cn/a/459669.html

相关文章:

  • 数据看板如何提升决策效率?
  • Linux硬盘分区 --- 挂载分区mount、卸载分区umount、永久挂载
  • 啥是大模型
  • ESP32-S3遇见OpenAI:OpenAI官方发布ESP32嵌入式实时RTC SDK
  • 在 macOS 上,你可以使用系统自带的 终端(Terminal) 工具,通过 SSH 协议远程连接服务器
  • 深入解析爬虫中的算法设计:提升效率与准确度
  • Unity 使用UGUI制作卷轴开启关闭效果
  • 【C#】元组
  • 【GO基础学习】gin的使用
  • ArcGIS教程(009):ArcGIS制作校园3D展示图
  • 基于 `android.accessibilityservice` 的 Android 无障碍服务深度解析
  • 20241227通过配置nomodeset参数解决更新grub之后,ubuntu20.04.5无法启动的问题
  • 移动 APP 设计规范参考
  • GXUOJ-算法-第二次作业(矩阵连乘、最长公共子序列、0-1背包问题、带权区间调度)
  • 工厂方法模式详解
  • Redis - 1 ( 7000 字 Redis 入门级教程 )
  • 语言模型在时间序列预测中的作用
  • PHP关键字Self、Static和parent的区别
  • 小程序中引入echarts(保姆级教程)
  • 对jenkins的rpm进行处理
  • Windows配置IE浏览器不自动跳转到Edge
  • Spring中的设计模式
  • 秒杀场景的设计思考
  • Webpack学习笔记(9)
  • 掌握 PostgreSQL 的 psql 命令行工具
  • 宝塔服务器安装备份配置