ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

learngo 复古 LED 时钟项目四道数组实战练习:重构、闹钟、百分秒与滚动动画

learngo 复古 LED 时钟项目四道数组实战练习:重构、闹钟、百分秒与滚动动画 示例工程教程【免费下载链接】learngo❤️ 1000 Hand-Crafted Go Examples, Exercises, and Quizzes. Learn Go by fixing 1000 tiny programs.项目地址https://gitcode.com/gh_mirrors/le/learngo点击查看免费下载导读本指南围绕learngo仓库中 15-project-retro-led-clock/exercises/README.md 展开逐一拆解 Retro LED Clock 项目的四道进阶练习多文件重构Refactor、每隔 10 秒显示闹钟Set an Alarm、显示十分之一秒的百分秒Split Second以及从右向左滑动的时钟动画Ticker。完成本指南后你将掌握数组[...]T与[5]string的声明、赋值、替换与索引运算在真实终端动画程序中的完整用法并理解 Go 的包级作用域、短声明限制与多文件同包编译规则。项目背景Retro LED Clock 五步曲Retro LED Clock 是learngo课程中用于强化数组知识的大型综合项目项目主目录 15-project-retro-led-clock/README.md 将整个项目划分为五个循序渐进的目标步骤打印数字01-printing-the-digits定义占位符类型为 0~9 每个数字创建[5]string数组放入digits数组并排输出打印时钟02-printing-the-clock获取当前时间构造时钟数组加入冒号分隔符动画时钟03-animating-the-clock无限循环每秒刷新、清屏、将光标移到左上角冒号闪烁04-blinking-the-separators让分隔符按秒奇偶闪烁完整带注释解答05-full-annotated-solution/main.go。而 exercises/README.md 正是在前四步成果之上的四道强化练习目的是证明你能写出易于维护的 Go 程序。练习一Refactor —— 把占位符搬进独立文件目标将时钟项目的一部分代码移动到同包下的新文件中使项目更易长期维护。具体分四步新建文件placeholders.go把placeholder类型移到placeholders.go把 0~9 及冒号的所有占位符移到placeholders.go把digits数组也移到placeholders.go。练习文件位于 01-refactor/main.go其顶部注释给出了三条关键提示placeholders.go必须同样属于main包重温PART I — Packages, Scopes and Importing课程包作用域下短声明:不可用必须改用var这是Short Declaration: Package Scope课程的核心结论若收到undefined: placeholder/undefined: colon的编译错误说明你没有同时编译多个文件需要用go run .方式运行同包多文件。重构后的 01-refactor/solution/placeholders.go 展示了答案的核心模式package main type placeholder [5]string var zero placeholder{ ███, █ █, █ █, █ █, ███, } // ... one 到 nine 同理 ... var colon placeholder{ , ░ , , ░ , , } var digits [...]placeholder{ zero, one, two, three, four, five, six, seven, eight, nine, }而 01-refactor/solution/main.go 只剩主循环逻辑screen.Clear()清屏 →screen.MoveTopLeft()复位光标 → 取time.Now()的时/分/秒 → 用digits[hour/10]、digits[hour%10]等索引运算组装clock数组 → 逐行逐列打印time.Sleep(time.Second)控制每秒刷新。期望输出重构前后运行结果完全一致。这一练习的价值在于验证你对同一目录下多个.go文件同属一个包和包级变量必须用var声明两个知识点的掌握。练习二Set an Alarm —— 每 10 秒打印 ALARM目标在时钟运行过程中每隔 10 秒将画面切换为 ALARM! 字样。练习文件为 02-alarm/main.go 与 02-alarm/placeholders.go。注释中给出提示可以新建一个与clock数组等长的alarm数组每 10 秒把alarm复制到clock数组。alarm数组由 8 个placeholder组成其中首尾两个是空白占位符用于对齐中间 6 个分别对应 ALARM 六个字母的 LED 字形见 02-alarm/solution/placeholders.govar alarm [...]placeholder{ { , , , , }, // 空白对齐 {███, █ █, ███, █ █, █ █}, // A {█ , █ , █ , █ , ███}, // L {███, █ █, ███, █ █, █ █}, // A {██ , █ █, ██ , █ █, █ █}, // R {█ █, ███, █ █, █ █, █ █}, // M { █ , █ , █ , , █ }, // ! { , , , , }, // 空白对齐 }核心判据是 02-alarm/solution/main.go 中的一行alarmed : sec%10 0当秒数能被 10 整除即每 10 秒一次时在逐行打印之前执行clock alarm用alarm数组整体替换clock数组——这正是数组可以整体赋值、比较语义的直接体现for line : range clock[0] { if alarmed { clock alarm } // ...打印逻辑不变... }期望输出中 ALARM! 字形还带有░冒号闪烁效果与前四步的sec%2 0逻辑保持一致。练习三Split Second —— 时钟加速到十分之一秒目标把刷新粒度从每秒提升到每 1/10 秒100 毫秒并在时钟右侧追加一个百分秒数字。练习文件为 03-split-second/main.go注释给出了详细步骤计算当前的百分秒split second在时钟中加入点字符dot把百分秒数字加入时钟数组让点字符像冒号一样每两秒闪烁把刷新周期从 1 秒改为 1/10 秒。注释提示使用Time类型的Nanosecond方法百分秒就是Nanosecond的第一位数字并且time.Second是整数常量可以直接除以数字。03-split-second/solution/main.go 给出了完整答案now : time.Now() hour, min, sec : now.Hour(), now.Minute(), now.Second() ssec : now.Nanosecond() / 1e8 clock : [...]placeholder{ digits[hour/10], digits[hour%10], colon, digits[min/10], digits[min%10], colon, digits[sec/10], digits[sec%10], dot, digits[ssec], }关键点now.Nanosecond() / 1e8取出纳秒值的第一位数字0~9即为百分秒clock数组扩为 10 个元素末尾追加dot和百分秒数字闪烁条件扩展为if (digit colon || digit dot) sec%2 0点与冒号同节奏闪烁刷新周期改为const splitSecond time.Second / 10; time.Sleep(splitSecond)印证了time.Second整数常量可参与除法运算的特性。期望输出展示了多种百分秒与秒的组合形态注意当时钟以十分之一秒刷新时画面会以 10 倍于原版的速度动态更新。练习四Ticker高难度—— 从右向左滑动时钟目标让整个时钟动画从屏幕右侧向左侧连续滑动。这是四道练习中标注HARD EXERCISE的一道练习文件为 04-ticker/main.go。04-ticker/solution/main.go 的核心思路是引入一个无限递增的shift变量用取模运算控制起始索引同时利用把时钟长度想象成两倍的技巧实现回绕for shift : 0; ; shift { screen.Clear() screen.MoveTopLeft() now : time.Now() hour, min, sec : now.Hour(), now.Minute(), now.Second() clock : [...]placeholder{ digits[hour/10], digits[hour%10], colon, digits[min/10], digits[min%10], colon, digits[sec/10], digits[sec%10], } for line : range clock[0] { l : len(clock) // 用 shift%l 防止越界 s, e : shift%l, l // 当 shift%(l*2) l 时说明时钟已完全滑出屏幕左端 // 重置起始位置为 0结束位置为 s形成回绕 if shift%(l*2) l { s, e 0, s } // 打印空白占位营造从右向左移动的效果 for j : 0; j l-e; j { fmt.Print( ) } // 从 s 到 e 绘制数字 for i : s; i e; i { next : clock[i][line] if clock[i] colon sec%2 0 { next } fmt.Print(next, ) } fmt.Println() } time.Sleep(time.Second) }值得注意的工程细节源码注释中均有说明每次循环都调用screen.Clear()否则上一帧的字符会残留在屏幕上另一种替代方案是用空白行填满缺失的占位符shift%l防止索引越界shift%(l*2) l判定时钟是否已整体滑出左端从而把(s, e)从(shift%l, l)重置为(0, s)l-e仅在上述if分支生效时才非零此时前置空白行让移出屏幕的占位符位置由空位补齐正是把时钟长度虚拟为两倍的收益所在。完成这道练习后for range遍历、%取模、数组整体比较与索引切片式的打印逻辑就全部串联起来了这也是文档中所说的你将真正感到自己掌握了此前学到的所有内容。如何运行与验证每个练习目录都采用题目 solution/答案的双目录结构例如01-refactor/main.go与01-refactor/solution/main.go。由于重构后涉及同包多文件运行方式为cd 15-project-retro-led-clock/exercises/01-refactor go run . # 或 go run *.go其中go run .会编译当前目录下同一包的所有.go文件这正是练习一注释中针对undefined: placeholder错误给出的解决方案。程序运行依赖github.com/inancgumus/screen包见仓库根目录 go.mod用于终端清屏与光标定位因此请在支持 ANSI 转义的终端中运行以获得最佳显示效果。各练习的期望输出都写在对应main.go顶部的注释块中如闹钟的 ALARM! 五层字形、百分秒时钟的多种组合形态你可以据此逐帧比对验证自己的实现是否正确。小结这四道练习环环相扣Refactor 强调代码组织与包级作用域Alarm 展示数组整体赋值替换Split Second 把time.Nanosecond、整数常量除法与数组扩围结合Ticker 则以取模回绕算法完成高难度的滑动动画。它们共同覆盖了learngo课程中数组章节的全部核心知识点适合在学习完 14-arrays 后通过动手改错的方式巩固掌握。若某一步卡住项目主 README 还提供了分步解答05-full-annotated-solution/main.go可以按步骤对照而不必一次看完整答案。赞分享示例工程教程【免费下载链接】learngo❤️ 1000 Hand-Crafted Go Examples, Exercises, and Quizzes. Learn Go by fixing 1000 tiny programs.项目地址https://gitcode.com/gh_mirrors/le/learngo点击查看免费下载相关推荐Zulip 部署在反向代理后面时如何配置信任代理和转发头Zulip 部署在反向代理后面时如何配置信任代理和转发头 如果你的 Zulip 服务器不直接暴露给公网而是要放在 nginx、Apache2 或 HAProx示例工程教程如何快速上手BrainRender神经解剖数据可视化的终极指南如何快速上手BrainRender神经解剖数据可视化的终极指南 BrainRender是一个强大的Python开源工具专门用于在脑图谱空间中可视化神经解剖数S3Proxy测试策略使用本地文件系统模拟云端存储环境S3Proxy测试策略使用本地文件系统模拟云端存储环境 S3Proxy是一款强大的工具它允许通过S3 API访问其他存储后端为开发者提供了极大的便利。在开后端API网关上一篇OpenZeppelin Contracts 的 ERC-4337 担保式 Paymaster 修复有效预存款Effective Prefund如何在扩展组合中正确传播下一篇Dashy Tailscale 私有网络部署指南借助 Tailscale Serve 与 Header Auth 实现免密自动登录创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表