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

Lua迭代器详解(附加红点功能实例)

Lua迭代器详解与用法

  • 1. 什么是迭代器
  • 2. 为什么需要理解迭代器的原理
  • 3. 迭代器的实现
    • 0. 闭包
    • 1. 有状态迭代器
    • 2. 无状态迭代器
  • 4. 红点树系统基础

1. 什么是迭代器

迭代器是一种能让我们遍历一个集合中的所有元素的代码结构。比如常用ipairs()和pairs()。

2. 为什么需要理解迭代器的原理

对于常见的table,无论key,value都可以通过ipairs()和pairs(),甚至访问table下标[*],next()遍历到table中所有的元素,而对于诸如链表,树,图等结构时,只依靠Lua原生的迭代器并不能方便的“以一条链或者路径的方式进行输出”,这时,我们需要根据所需自定义迭代器。

      对于一些还是在校学生等接触Lua时间不长的人来说,可能没法立刻体会到链表,树,图在Lua中的使用场景(除了练习数据结构)。
      其实,在结合Lua进行游戏开发的商业项目中,这些数据结构会得到广泛的使用,比如:

  1. LRU动态管理内存资源,通常LRU会由链表去解决地址冲突问题;
  2. 游戏的红点树,红点一般都是用内向外(一般游戏主界面可以理解为最外一层)逐级传递,通过树来构建整个游戏中所有界面的红点依赖,就可以通过设置某一个节点从而使得这条路径上所有的节点红点都能被响应(设置显隐)。

3. 迭代器的实现

0. 闭包

闭包(closure)是一个函数以及其引用的非局部变量的组合。闭包允许函数携带其执行环境,使得函数可以访问并操作其定义时的变量,即使这些变量超出了其定义的作用域。

function createCounter()local count = 0local function counter()count = count + 1return countendreturn counter
endlocal myCounter = createCounter()
print(myCounter()) -- 输出 1
print(myCounter()) -- 输出 2
print(myCounter()) -- 输出 3

1. 有状态迭代器

有状态迭代器需要在外部环境中维护状态信息,通常利用Lua的闭包实现

-- statefulRange 返回一个闭包函数,闭包中维护了 current 状态,这个状态在每次迭代时更新。function statefulRange(start, stop)local current = start - 1return function()current = current + 1if current <= stop thenreturn currentendend
endfor i in statefulRange(1, 5) doprint(i) -- 1 2 3 4 5
end

2. 无状态迭代器

无状态迭代器在每次调用迭代函数时,通过传入参数来计算下一个值。这些参数包含了必要的状态信息,但这些信息是通过函数调用参数传递的,而不是通过外部变量或表格。

-- 迭代函数
-- range 函数返回三个值:迭代函数 rangeIterator、初始状态 start 和初始控制变量 start - 1。
-- for 循环每次调用 rangeIterator 时,传入当前状态(start)和控制变量(current)。
-- 在 rangeIterator 内部,控制变量 current 被递增,然后返回递增后的值,直到达到 stop。function rangeIterator(start, stop, current)if current < stop thencurrent = current + 1return current, currentend
end-- 迭代器生成函数
function range(start, stop)return rangeIterator, start, start - 1
end

4. 红点树系统基础

下面给出的是根据策划配置构建红点树的大致过程,如需使用,可结合项目,在此基础上进行添加并完善对应功能。

local RedPoint = {}local RedPointTable = {}function RedPoint.GetAll() -- 获取红点所有配置表return RedPointTable
end-- 获取一个节点的配置项
function RedPoint.GetConfig(NodeName)return RedPointTable[NodeName]
endfunction RedPoint.AddNode(NodeName,ParentNodeName,bEnd) -- 这种方式插入节点有个问题是要按照树的顺序从上到下,如果先插子节点,而父节点不存在,导致父节点的Child子节点索引表错误return function(cfg)if ParentNodeName ~= "none" thenlocal parentNode = RedPoint.GetConfig(ParentNodeName)if not parentNode.Child thenparentNode.Child = {}endparentNode.Child[NodeName] = true -- 以hash的方式存储,方便做一些子节点快速查找操作,如果不需要也可以直接按顺序插入endcfg.bEndNode = bEnd -- bEnd = false 添加非叶子节点 bEnd = true 添加非叶子节点cfg.parent = ParentNodeNameRedPointTable[NodeName] = cfgend
endfunction RedPoint.AddNodeEX(NodeName,ParentNodeName,bEnd) -- 这种方式插入可以不管父子节点的顺序,但是需要在使用前先对该配置表RedPointTable进行一次预处理,来建立每个节点的子节点表return function (cfg)cfg.bCatalog = bEndcfg.parent = ParentNodeNameRedPointTable[NodeName] = cfgend
end
------------------ 策划配置部分 Begin ------------------
--- 路径 1
RedPoint.AddNode("root","none",false){NodeValue = 1
}RedPoint.AddNode("child1","root",false){NodeValue = 2
}RedPoint.AddNode("grandchild1","child1",false){NodeValue = 5
}RedPoint.AddNode("grandchild2","grandchild1",true){NodeValue = 7
}--- 路径 2
RedPoint.AddNode("child2","root",true){NodeValue = 3
}--- 路径 3
RedPoint.AddNode("child3","root",true){NodeValue = 4
}--- 路径 4
RedPoint.AddNode("grandchild3","child1",true){NodeValue = 6
}
------------------ 策划配置部分 End ------------------------------------ 功能函数测试 -------------------
-- 实际开发中会有一个单独的红点功能来管理下面这些接口
-- 迭代器函数
local InnerNextNode = function (CurNodeName, CurNodeParentName)if not CurNodeParentName thenreturn CurNodeName,RedPoint.GetConfig(CurNodeName)elselocal Config = RedPoint.GetConfig(CurNodeParentName)local parent = Config.parentif parent ~= "none" thenreturn parent, RedPoint.GetConfig(parent)elsereturn nil, nilendend
end
-- 自定义for无状态迭代器
local NextNode = function(CurNodeName)return InnerNextNode,CurNodeName,nil
end
-- 由当前节点向父节点依次遍历,直到遍历到没有父节点为止
function RedPoint.GetEachNode(CurNodeName)for NodeName,NodeConfig in NextNode(CurNodeName) doprint("NodeName:",NodeName," NodeConfig:",NodeConfig.NodeValue)end
end
-- 获取一个节点的所有直接子节点
function RedPoint.GetNodeChild(CurNodeName)local CurNodeCfg = RedPointTable[CurNodeName]if CurNodeCfg and CurNodeCfg.Child thenlocal Child = CurNodeCfg.Childfor NodeName,bChild in pairs(Child) doif bChild thenlocal CurChildConfig = RedPoint.GetConfig(NodeName)if CurChildConfig thenprint("CurNodeName's Child NodeName is:",NodeName,CurChildConfig.NodeValue)elseerror("Cur Child Node is Invalid:",NodeName)endendendend
end
-- 遍历以CurNodeName节点为根节点时下面所有节点
function RedPoint.GetEachNodeAll(CurNodeName)local CurNodeConfig = RedPoint.GetConfig(CurNodeName)if CurNodeConfig thenprint("Cur Node====",CurNodeConfig.NodeValue)local CurChildNode = CurNodeConfig.Childif CurChildNode thenfor NodeName,NodeConfig in pairs(CurChildNode) doRedPoint.GetEachNodeAll(NodeName)endendendenddoRedPoint.GetEachNode("grandchild2")-- NodeName:    grandchild2  NodeConfig:    7-- NodeName:    grandchild1  NodeConfig:    5-- NodeName:    child1   NodeConfig:    2-- NodeName:    root     NodeConfig:    1RedPoint.GetNodeChild("root")-- CurNodeName's Child NodeName is: child2  3-- CurNodeName's Child NodeName is: child3  4-- CurNodeName's Child NodeName is: child1  2RedPoint.GetEachNodeAll("root")-- Cur Node==== 1-- Cur Node==== 3-- Cur Node==== 4-- Cur Node==== 2-- Cur Node==== 5-- Cur Node==== 7-- Cur Node==== 6
endreturn RedPoint

相关文章:

Lua迭代器详解(附加红点功能实例)

Lua迭代器详解与用法 1. 什么是迭代器2. 为什么需要理解迭代器的原理3. 迭代器的实现0. 闭包1. 有状态迭代器2. 无状态迭代器 4. 红点树系统基础 1. 什么是迭代器 迭代器是一种能让我们遍历一个集合中的所有元素的代码结构。比如常用ipairs()和pairs()。 2. 为什么需要理解迭代…...

锂磷硫(LPS)属于硫化物固态电解质 Li7P3S11是代表性产品

锂磷硫&#xff08;LPS&#xff09;属于硫化物固态电解质 Li7P3S11是代表性产品 锂磷硫&#xff08;LPS&#xff09;&#xff0c;为非晶态材料&#xff0c;是硫化物固态电解质代表性产品之一&#xff0c;具有热稳定性好、成本较低等优点&#xff0c;在固态电解质中离子电导率较…...

PointCloudLib 点云边缘点提取 C++版本

0.实现效果 1.算法原理 PCL(Point Cloud Library)中获取点云边界的算法主要基于点云数据的几何特征和法向量信息。以下是对该算法的详细解释,按照清晰的格式进行归纳: 算法概述 PCL中的点云边界提取算法主要用于从3D点云数据中识别并提取出位于物体边界上的点。这些边界…...

【Qt】QList<QVariantMap>中数据修改

1. 问题 QList<QVariantMap> 类型中&#xff0c;修改QVariantMap中的值。 2. 代码 //有效代码1QVariantMap itemMap itemList.at(0);itemMap.insert("title", "test");itemList.replace(0, itemMap);//有效代码 2itemList.operator [](0).insert(…...

如何避免vue的url中使用hash符号?

目录 1. 安装 Vue Router 2. 配置 Vue Router 使用 history 模式 3. 更新 main.js 4. 配置服务器以支持 history 模式&#xff08;此处需要仔细测试&#xff09; a. Nginx 配置 b. Apache 配置 5. 部署并测试 总结 在 Vue.js 项目中&#xff0c;避免 URL 中出现 # 符号的…...

Java学习 - MySQL存储过程、函数和触发器练习实例

存储过程 存储过程是什么 存储过程是一组已经编译好的SQL语句存储过程优点有什么 安全 性能高 提高代码复用性创建存储过程的语法 DELIMITER $ # 不能加分号CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型) BEGIN存储过程语句块 END;$DELIMITER ;创建一个无参的存储…...

【深度神经网络 (DNN)】

深度神经网络 (DNN) 深度神经网络 (DNN) 是机器学习领域中一种强大的工具&#xff0c;它由多层神经元组成&#xff0c;能够学习复杂的数据模式&#xff0c;解决各种任务&#xff0c;如图像识别、语音识别、自然语言处理等。 DNN 的构成&#xff1a; 神经元: DNN 的基本单元&…...

ES全文检索支持繁简和IK分词检索

ES全文检索支持繁简和IK分词检索 1. 前言2. 引入繁简转换插件analysis-stconvert2.1 下载已有作者编译后的包文件2.2 下载源码进行编译2.3 复制解压插件到es安装目录的plugins文件夹下 3. 引入ik分词器插件3.1 已有作者编译后的包文件3.2 只有源代码的版本3.3 安装ik分词插件 4…...

解决Visual Studio Code在Ubuntu上崩溃的问题

解决Visual Studio Code在Ubuntu上崩溃的问题 我正在使用Ubuntu系统&#xff0c;每次打开Visual Studio Code时&#xff0c;只能短暂打开一秒钟&#xff0c;然后就会崩溃。当通过终端使用code --verbose命令启动Visual Studio Code时&#xff0c;出现以下错误信息&#xff1a;…...

【OpenGauss源码学习 —— (ALTER TABLE(SET attribute_option))】

ALTER TABLE&#xff08;SET attribute_option&#xff09; ATExecSetOptions 函数 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。…...

Elasticsearch 数据提取 - 最适合这项工作的工具是什么?

作者&#xff1a;来自 Elastic Josh Asres 了解在 Elasticsearch 中为你的搜索用例提取数据的所有不同方式。 对于搜索用例&#xff0c;高效采集和处理来自各种来源的数据的能力至关重要。无论你处理的是 SQL 数据库、CRM 还是任何自定义数据源&#xff0c;选择正确的数据采集…...

‘浔川画板v5.1’即将上线!——浔川python社

1 简介&#xff1a; 浔川画板是一款专业的数字绘画和漫画创作软件&#xff0c;它为艺术家和设计师提供了丰富的绘画工具、色彩管理功能以及易于使用的界面。用户可以使用浔川画板进行手绘风格的绘画、精细的素描、漫画分格、UI设计等多种创作。该软件支持多种笔刷和特效&#…...

RockChip Android12 System之Datetime

一:概述 本文将针对Android12 Settings二级菜单System中Date&time的UI修改进行说明。 二:Date&Time 1、Activity packages/apps/Settings/AndroidManifest.xml <activityandroid:name="Settings$DateTimeSettingsActivity"android:label="@stri…...

详解 ClickHouse 的副本机制

一、简介 副本功能只支持 MergeTree Family 的表引擎&#xff0c;参考文档&#xff1a;https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/replication/ ClickHouse 副本的目的主要是保障数据的高可用性&#xff0c;即使一台 ClickHouse 节点宕机&#…...

速卖通测评成本低见效快,自养号测评的实操指南,快速积累销量和好评

对于初入速卖通的新卖家而言&#xff0c;销量和评价的积累显得尤为关键。由于新店铺往往难以获得平台活动的青睐&#xff0c;因此流量的获取成为了一大挑战。在这样的背景下&#xff0c;进行产品测评以积累正面的用户反馈和销售记录&#xff0c;成为了提升店铺信誉和吸引潜在顾…...

php反序列化漏洞简介

目录 php序列化和反序列化简介 序列化 反序列化 类中定义的属性 序列化实例 反序列化实例 反序列化漏洞 序列化返回的字符串格式 魔术方法和反序列化利用 绕过wakeup 靶场实战 修复方法 php序列化和反序列化简介 序列化 将对象状态转换为可保持或可传输的格式的…...

力扣随机一题 模拟+字符串

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 1910.删除一个字符串中所有出现的给定子字符串【中等】 题目&#xff1a; …...

java-正则表达式 1

Java中的正则表达式 1. 正则表达式的基本概念 正则表达式&#xff08;Regular Expression, regex&#xff09;是一种用于匹配字符串中字符组合的模式。正则表达式广泛应用于字符串搜索、替换和解析。Java通过java.util.regex包提供了对正则表达式的支持&#xff0c;该包包含两…...

Python xlrd库:读excel表格

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

开发中遇到的一个bug

遇到的报错信息是这样的&#xff1a; java: Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [hm-api,hm-common,hm-service] are excluded from annotation processing 翻译过来就是存在循环引用的情况&#xff0c;导…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...