用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.mzph.cn/news/890921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理想的以太网网络故障排查工具:LinkXpert M3

在排查铜缆、光纤和Wi-Fi以太网故障时&#xff0c;通常需要多种昂贵的工具&#xff0c;操作起来会很复杂。因此&#xff0c;我们推出了LinkXpert M3 —— 一个专为铜缆、光纤和Wi-Fi以太网网络故障排查而设计的工具。它功能强大、体积小巧、性价比高&#xff0c;无疑是您值得信…

【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 7.2.1. 路径的简介 在Rust里&#xff0c;如果想要找到模块里的某个东西&#xff0c;就必须知道并使用它的路径。Rust中的路径就跟文件系统…

Git如何设置和修改当前分支跟踪的上游分支

目录 前言 背景 设置当前分支跟踪的上游分支 当前分支已有关联&#xff0c;删除其关联&#xff0c;重新设置上游 常用的分支操作 参考资料 前言 仅做学习记录&#xff0c;侵删 背景 在项目开发过程中&#xff0c;从master新建分支时&#xff0c;会出现没有追踪的上游分…

专业版pycharm与服务器连接

一、先连接服务器 先创建配置&#xff1a; 名字随便取一个&#xff1a; 点击测试连接测试是否连接成功&#xff1b; 二、添加解释器 添加解释器&#xff0c;这个解释器是最开始在xshell中创建好的虚拟环境&#xff0c;具体虚拟环境创建可参考这篇&#xff1a;AutoDL服务器深…

LabVIEW如何学习FPGA开发

FPGA&#xff08;现场可编程门阵列&#xff09;开发因其高性能、低延迟的特点&#xff0c;在实时控制和高速数据处理领域具有重要地位。LabVIEW FPGA模块为开发者提供了一个图形化编程平台&#xff0c;降低了FPGA开发的门槛。本篇文章将详细介绍LabVIEW FPGA开发的学习路径&…

ISDP010_基于DDD架构实现收银用例主成功场景

信息系统开发实践 &#xff5c; 系列文章传送门 ISDP001_课程概述 ISDP002_Maven上_创建Maven项目 ISDP003_Maven下_Maven项目依赖配置 ISDP004_创建SpringBoot3项目 ISDP005_Spring组件与自动装配 ISDP006_逻辑架构设计 ISDP007_Springboot日志配置与单元测试 ISDP008_SpringB…

中学数学:一个函数值计算题

在数学的领域中&#xff0c;函数是一种描述变量之间关系的桥梁&#xff0c;它能够揭示出看似复杂现象背后的简洁规律。通过函数&#xff0c;我们可以预测、分析并解决实际问题。在这张图片中&#xff0c;我们看到了一位数学爱好者手写的解题过程&#xff0c;它展示了如何巧妙地…

#渗透测试#漏洞挖掘#红蓝攻防#常见未授权访问漏洞汇总

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

基于Oauth2的SSO单点登录---前端

Vue-element-admin 是一个基于 Vue.js 和 Element UI 的后台管理系统框架&#xff0c;提供了丰富的组件和功能&#xff0c;可以帮助开发者快速搭建现代化的后台管理系统。 一、基本知识 &#xff08;一&#xff09;Vue-element-admin 的主要文件和目录 vue-element-admin/ |--…

linux内核如何实现TCP的?

TCP(传输控制协议)是网络通信中的核心协议之一,实现了可靠的、面向连接的、基于字节流的通信。在Linux内核中,TCP的实现相对复杂,涉及多个模块和层次。以下是一些关键概念和机制: 1. 协议栈 Linux 内核中的网络协议栈(Network Stack)是分层设计的,包括链路层、网络层…

ElasticSearch 分布式部署

一、引言 在当今大数据时代&#xff0c;数据呈爆炸式增长&#xff0c;如何高效地存储、检索数据成为了众多企业面临的关键挑战。ElasticSearch 作为一款强大的分布式搜索引擎&#xff0c;凭借其卓越的性能、灵活的扩展性以及强大的全文检索能力&#xff0c;在日志分析、数据分…

依图科技简介

依图科技&#xff08;YITU Technology&#xff09;是中国一家全球领先的人工智能&#xff08;AI&#xff09;公司&#xff0c;成立于2012年&#xff0c;总部位于上海。公司专注于计算机视觉、语音识别和自然语言处理等核心AI技术&#xff0c;致力于推动AI技术在医疗、安防、金融…

[创业之路-206]:《华为战略管理法-DSTE实战体系》- 6-关键成功因素法CSF

目录 一、概述 1、定义与起源 2、关键成功因素的定义 3、关键成功因素的来源 4、关键成功因素的确认方法 5、关键成功因素法的步骤 6、关键成功因素法的应用 7、关键成功因素法的优势与局限性 二、 关键成功因素法CSF的应用 1、企业战略管理 2、项目管理 3、绩效管…

Express.js 有哪些常用的中间件?

在使用 Express.js 开发应用程序时&#xff0c;中间件&#xff08;Middleware&#xff09;是处理请求和响应的关键组件。它们可以执行各种任务&#xff0c;如解析请求体、添加HTTP头部、记录日志等。以下是一些常用的中间件&#xff1a; body-parser 用于解析传入的请求体。它…

华为 AI Agent:企业内部管理的智能变革引擎(11/30)

一、华为 AI Agent 引领企业管理新潮流 在当今数字化飞速发展的时代&#xff0c;企业内部管理的高效性与智能化成为了决定企业竞争力的关键因素。华为&#xff0c;作为全球领先的科技巨头&#xff0c;其 AI Agent 技术在企业内部管理中的应用正掀起一场全新的变革浪潮。 AI Ag…

RustDesk内置ID服务器,Key教程

RustDesk内置ID服务器&#xff0c;Key教程 首先需要准备一个域名&#xff0c;并将其指定到你的 rustdesk 服务器 ip 地址上&#xff0c;这里编译采用的是Github Actions &#xff0c;说白了是就workflows&#xff0c;可以创建一些自动化的工作流程&#xff0c;例如代码的检查&a…

虚幻引擎结构之UObject

一. UObject 的介绍 UObject 是虚幻引擎中的核心基础类,所有其他游戏对象和资源类都直接或间接地继承自它。作为虚幻引擎的基石,UObject 提供了多项关键功能,包括内存管理、序列化、反射(introspection)、垃圾回收以及元数据支持。在虚幻引擎中,UObject 类的实例通常被称…

Python异常处理在“简易记事本”项目中的应用

Python异常处理在“简易记事本”项目中的应用 在“简易记事本”项目中&#xff0c;异常处理的使用尤为重要&#xff0c;因为文件操作过程中可能会遇到各种问题&#xff0c;例如文件不存在、权限不足或文件占用等。如果这些问题未被妥善处理&#xff0c;程序可能会崩溃&#xf…

Wend看源码-Java-集合学习(List)

摘要 本篇文章深入探讨了基于JDK 21版本的Java.util包中提供的多样化集合类型。在Java中集合共分类为三种数据结构&#xff1a;List、Set和Queue。本文将详细阐述这些数据类型的各自实现&#xff0c;并按照线程安全性进行分类&#xff0c;分别介绍非线程安全与线程安全的实现方…

阿里云新用户服务器配置

创建和链接实例 创建实例&#xff0c;点击左侧标签栏总的实例&#xff0c; 找到链接帮助 根据帮助中的ip信息&#xff0c;然后启用vscode的ssh链接 ctrlp选择配置&#xff0c;输入公网的ip即可 passwd修改root密码 安装conda 参考 https://blog.csdn.net/adreammaker/arti…